From 24ce90a1ea2d173b26dceee52fdea046d082b36d Mon Sep 17 00:00:00 2001 From: WangXuan95 <629708558@qq.com> Date: Thu, 8 Jun 2023 20:40:07 +0800 Subject: [PATCH] change to Verilog2001 --- README.md | 363 +++++++------- RTL/{sd_file_reader.sv => sd_file_reader.v} | 189 ++++--- RTL/{sd_reader.sv => sd_reader.v} | 98 ++-- RTL/{sdcmd_ctrl.sv => sdcmd_ctrl.v} | 98 ++-- SIM/{sd_fake.sv => sd_fake.v} | 470 ++++++++++-------- ..._sd_file_reader.sv => tb_sd_file_reader.v} | 8 +- SIM/tb_sd_file_reader_run_iverilog.bat | 2 +- example-vivado-readfile.zip | Bin 0 -> 85564 bytes example-vivado-readfile/Nexys-4-DDR-pins.xdc | 41 -- example-vivado-readfile/Nexys4-ReadFile.xpr | 234 --------- example-vivado-readfile/RTL/top.sv | 84 ---- example-vivado-readfile/RTL/uart_tx.sv | 188 ------- example-vivado-readsector.zip | Bin 0 -> 8350 bytes .../Nexys-4-DDR-pins.xdc | 41 -- .../Nexys4-ReadSector.xpr | 228 --------- example-vivado-readsector/RTL/top.sv | 96 ---- example-vivado-readsector/RTL/uart_tx.sv | 188 ------- figures/pin.png | Bin 23691 -> 0 bytes pin.png | Bin 0 -> 4861 bytes 19 files changed, 708 insertions(+), 1620 deletions(-) rename RTL/{sd_file_reader.sv => sd_file_reader.v} (80%) rename RTL/{sd_reader.sv => sd_reader.v} (76%) rename RTL/{sdcmd_ctrl.sv => sdcmd_ctrl.v} (54%) rename SIM/{sd_fake.sv => sd_fake.v} (54%) rename SIM/{tb_sd_file_reader.sv => tb_sd_file_reader.v} (97%) create mode 100644 example-vivado-readfile.zip delete mode 100644 example-vivado-readfile/Nexys-4-DDR-pins.xdc delete mode 100644 example-vivado-readfile/Nexys4-ReadFile.xpr delete mode 100644 example-vivado-readfile/RTL/top.sv delete mode 100644 example-vivado-readfile/RTL/uart_tx.sv create mode 100644 example-vivado-readsector.zip delete mode 100644 example-vivado-readsector/Nexys-4-DDR-pins.xdc delete mode 100644 example-vivado-readsector/Nexys4-ReadSector.xpr delete mode 100644 example-vivado-readsector/RTL/top.sv delete mode 100644 example-vivado-readsector/RTL/uart_tx.sv delete mode 100644 figures/pin.png create mode 100644 pin.png diff --git a/README.md b/README.md index fb802a5..48bbe36 100644 --- a/README.md +++ b/README.md @@ -1,154 +1,8 @@ -![语言](https://img.shields.io/badge/语言-systemverilog_(IEEE1800_2005)-CAD09D.svg) ![仿真](https://img.shields.io/badge/仿真-iverilog-green.svg) ![部署](https://img.shields.io/badge/部署-quartus-blue.svg) ![部署](https://img.shields.io/badge/部署-vivado-FF1010.svg) - -中文 | [English](#en) - -FPGA SDcard File Reader -=========================== - -基于 FPGA 的 SD卡文件读取器 - -* **功能** :FPGA作为 **SD-host** , 指定文件名读取文件内容;或指定扇区号读取扇区内容。 -* **性能** :使用 SD总线,而不是 SPI总线。读取速度更快。 -* **兼容性强** :自动适配 **SD卡版本** ,自动适配 **FAT16/FAT32文件系统**。 -* 纯 RTL 实现,便于移植和仿真。 - -| | SDv1.1 card | SDv2 card | SDHCv2 card | -| :----- | :------------: | :------------: | :------------: | -| **读取扇区** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| **读取文件 (FAT16)** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| **读取文件 (FAT32)** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | - - - -# 背景知识 - -## SD总线 - -SD卡使用 SD 总线与 SD-host (比如读卡器)连接,SD总线的信号包括: - -| 信号名 | 输入输出方向 | -| ------------------------------ | ------------------------------------------------ | -| sdclk | host→ card | -| sdcmd | 当发起命令时 host→ card ,当响应命令时 card→host | -| sddat0、sddat1、sddat2、sddat3 | 当写数据时 host→card ,当读数据时 card→host | - -这些信号在 SD 卡和 microSD 卡上的引脚定义如下图(SD卡和microSD卡除了外形尺寸外,功能上没有差别) - -| ![pin](./figures/pin.png) | -| :------------------------------------------: | -| 图:SD 卡(左)与 microSD 卡(右)的引脚定义 | - - - -## 文件系统 - -SD卡本身只是一大块线性的数据存储空间,分为多个扇区 (sector),每个扇区 512 字节,扇区0的地址范围为 0x00000000\~0x000001FF,扇区1的地址范围为 0x00000200\~0x000003FF,以此类推……。底层的读取和写入操作都以扇区为单位。为了在这片线性的存储空间中组织磁盘分区和文件,人们规定了复杂的数据结构——文件系统,SD卡最常用的文件系统是 FAT16 和 FAT32 。 - -为了从 SD 卡中读取文件数据,本库分为两个功能模块: - -- 按照 SD 总线标准操控 SD 总线,指定扇区号,读取扇区。 -- 在能够读取扇区的基础上,解析文件系统,也就是给定文件名,找到文件所在的位置和长度。实际上,文件可能不是连续存储的(被拆成多块放在不同扇区),本库会正确地处理这种情况。 - - - - -# 如何调用本模块 - -RTL 文件夹中的 sd_file_reader.sv 是 SD卡文件读取器的顶层模块,它的定义如下: - -``` -module sd_file_reader #( - parameter FILE_NAME = "example.txt", - parameter [2:0] CLK_DIV = 3'd1, - parameter SIMULATE = 0 -)( - // rstn active-low, 1:working, 0:reset - input wire rstn, - // clock - input wire clk, - // SDcard signals (connect to SDcard), this design do not use sddat1~sddat3. - output wire sdclk, - inout sdcmd, - input wire sddat0, // FPGA only read SDDAT signal but never drive it - // status output (optional for user) - output wire [3:0] card_stat, // show the sdcard initialize status - output wire [1:0] card_type, // 0=UNKNOWN , 1=SDv1 , 2=SDv2 , 3=SDHCv2 - output wire [1:0] filesystem_type, // 0=UNASSIGNED , 1=UNKNOWN , 2=FAT16 , 3=FAT32 - output reg file_found, // 0=file not found, 1=file found - // file content data output (sync with clk) - output reg outen, // when outen=1, a byte of file content is read out from outbyte - output reg [7:0] outbyte // a byte of file content -); -``` - -其中: - -- `FILE_NAME` 指定要读的目标文件名。 -- `CLK_DIV` 是时钟分频系数,它的取值需要根据你提供的 clk 时钟频率来决定(详见代码注释)。 -- `SIMULATE` 是仿真加速选项。**平常要设为 `0` **。只有仿真时才可以设 为 `1` 来加速 SD 卡初始化进度,防止仿真占用过多时间。 -- `clk` 是模块驱动时钟。 -- `rstn` 是复位信号,在开始工作前需要令 `rstn=0` 复位一下,然后令 `rstn=1` 释放。 -- `sdclk` 、 `sdcmd` 、 `sddat0` 是 SD 总线信号,需要连接到 SD 卡。 - - 注意到本模块只用到了 `sddat0` 而没用到 `sddat1~sddat3` ,因为 SD 卡上电会默认运行在 1bit 窄数据总线模式,可以用命令切换到 4bit 宽数据总线模式,我没有做切换,一直只用 `sddat0` 。而 `sddat1~sddat3` 需要弱上拉或强上拉到高电平(避免 SD 卡进入 SPI 总线模式)。 -- `card_type` 指示检测到的 SD 卡的类型:0对应未知、1对应SDv1、2对应SDv2、3对应SDHCv2。 -- `file_system_type` 指示检测到的 SD 卡的文件系统:1对应未知、2对应FAT16、3对应FAT32。 -- `file_found` 指示是否找到目标文件:0代表未找到,1代表找到。 -- 如果找到目标文件,模块会逐个输出目标文件中的所有字节,每输出一个字节,`outen` 上就产生一个高电平脉冲,同时该字节出现在 `outbyte` 上。 - -> **注意**:本库只使用了 sddat0 ,而不使用 sddat1\~3 (也即SD 1-bit总线模式)。在工作时需要将 sddat1\~3 持续拉高(可以在 FPGA 代码里 `assign sddat[3:1] = 3'b111;` ,或者在PCB板上使用上拉电阻),这样 SD 卡才能正常进入 SD 总线模式,否则会进入 SPI 总线模式。 - - - -# 仿真 - -仿真相关的文件都在 SIM 文件夹中,其中: - -- sd_fake.sv :是一个 FPGA 模拟 SD 卡的代码,它模拟了一个具有 FAT32 系统,里面有一个 example.txt 文件的 SD 卡。它来自我的另一个库:[FPGA-SDfake](https://github.com/WangXuan95/FPGA-SDfake) -- tb_sd_file_reader.sv 是仿真顶层,它会调用 sd_file_reader 读取 sd_fake 中的 example.txt 。 -- tb_sd_file_reader_run_iverilog.bat 是运行 iverilog 仿真的脚本。 - -使用 iverilog 进行仿真前,需要安装 iverilog ,见:[iverilog_usage](https://github.com/WangXuan95/WangXuan95/blob/main/iverilog_usage/iverilog_usage.md) - -然后双击 tb_sd_file_reader_run_iverilog.bat 运行仿真,会运行大约几分钟。 - -仿真运行完后,可以打开生成的 dump.vcd 文件查看波形。 - - - -读取文件示例 -=========================== - -example-vivado-readfile 文件夹中包含一个 vivado 工程,它运行在 [Nexys4开发板](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga-trainer-board.html) 上(Nexys4 开发板有 microSD 卡槽,比较方便)。它会从 SD卡根目录中找到文件 example.txt 并读取其全部内容,然后用 **UART** 发送出给PC机。 - -按以下步骤运行该示例: - -1. 准备一张 **microSD卡** 。如果是标准尺寸的SD卡(大SD卡),可以用大卡转 microSD 卡的转接板转接一下。 -1. 确保卡中的文件系统是 **FAT16** 或 **FAT32** 。如果不是,则需要格式化一下。 -2. 在根目录下创建 **example.txt** (文件名大小写不限) , 在文件中随便写入一些内容。 -3. 将卡插入 Nexys4 的卡槽。 -4. 将 Nexys4 的USB口插在PC机上,用 **串口助手** 或 **Putty** 等软件打开对应的串口。 -5. 用 vivado 打开目录 example-vivado-readfile 中的工程,综合并烧录。 -6. 观察到串口打印出文件内容。 -7. 同时,还能看到 Nexys4 上的 LED 灯发生变化,它们指示了SD卡的类型和状态,具体含义见代码。 -8. 按下 Nexys4 上的红色 CPU_RESET 按钮可以重新读取,再次打印出文件内容。 - - - -读取扇区示例 -=========================== - -example-vivado-readsector 文件夹中包含一个 vivado 工程,它运行在 [Nexys4开发板](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga-trainer-board.html) 上。它会从 SD卡中读取扇区0(它在文件系统中往往叫 MBR 扇区),然后用 **UART** 发送出给PC机。 - -按以下步骤运行该示例: - -1. 准备一张 **microSD卡** 。如果是标准尺寸的SD卡(大SD卡),可以用大卡转 microSD 卡的转接板转接一下。 -2. 将 Nexys4 的USB口插在PC机上,用 **串口助手** 打开对应的串口,请选择 “HEX接收” ,以十六进制的形式打印每个字节,这样我们才能看到那些 ASCII 不可打印字符。 -3. 用 vivado 打开目录 example-vivado-readsector 中的工程,综合并烧录。 -4. 观察到串口打印出扇区0的内容。 -5. 同时,还能看到 Nexys4 上的 LED 灯发生变化,它们指示了SD卡的类型和状态,具体含义见代码注释。 -6. 按下 Nexys4 上的红色 CPU_RESET 按钮可以重新读取,再次打印出扇区内容。 +![语言](https://img.shields.io/badge/语言-verilog_(IEEE1364_2001)-9A90FD.svg) ![仿真](https://img.shields.io/badge/仿真-iverilog-green.svg) ![部署](https://img.shields.io/badge/部署-quartus-blue.svg) ![部署](https://img.shields.io/badge/部署-vivado-FF1010.svg) +[English](#en) | [中文](#cn) +  FPGA SDcard File Reader =========================== @@ -158,7 +12,7 @@ FPGA-based SDcard file reader * **Function**: FPGA acts as **SD-host**, specifying the file name to read the file content; or specifying the sector number to read the sector content. * **Performance**: Use SD bus instead of SPI bus. Read faster. * **Strong compatibility**: automatically adapt to **SDcard version**, automatically adapt to **FAT16/FAT32 file system**. -* pure RTL implement, easy to simulate and transplant. +* pure Verilog implement, easy to simulate and transplant. | | SDv1.1 card | SDv2 card | SDHCv2 card | | :-------------------- | :----------------: | :----------------: | :----------------: | @@ -166,7 +20,7 @@ FPGA-based SDcard file reader | **Read File (FAT16)** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | **Read File (FAT32)** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | - +  # Background @@ -182,7 +36,7 @@ The SDcard is connected to the SD-host (such as a card adaptor) using the SD bus The pin definitions of these signals on SDcard and microSDcard are as follows (SDcard and microSDcard have no difference in function except for the shape and appearance). -| ![pin](./figures/pin.png) | +| ![pin](./pin.png) | | :----------------------------------------------------------: | | Figure : pin defination of SDcard (left) and microSDcard (right) | @@ -195,19 +49,26 @@ In order to read file data from SDcard, this library is divided into two functio - Manipulate the SD bus according to the SD bus standard, specify the sector number and read the sector. - On the basis of being able to read sectors, parse the file system, that is, given the file name, to find the location and length of the file. In fact, the file may not be stored contiguously (that is, split into multiple blocks in different sectors), my code will handle this case correctly. - +  # How to use this module -sd_file_reader.sv in the [RTL](./RTL) folder is the top-level module of the SD card file reader, and it is defined as follows: +sd_file_reader.v in the [RTL](./RTL) folder is the top-level module of the SD card file reader, and it is defined as follows: -``` +```verilog module sd_file_reader #( - parameter FILE_NAME = "example.txt", - parameter [2:0] CLK_DIV = 3'd1, + parameter FILE_NAME_LEN = 11 , // valid length of FILE_NAME (in bytes) + parameter [52*8-1:0] FILE_NAME = "example.txt", // file to read, ignore Upper and Lower Case + // For example, if you want to read a file named HeLLo123.txt in the SD card, + // this parameter can be hello123.TXT, HELLO123.txt or HEllo123.Txt + parameter [2:0] CLK_DIV = 3'd2, // when clk = 0~ 25MHz , set CLK_DIV = 3'd1, + // when clk = 25~ 50MHz , set CLK_DIV = 3'd2, + // when clk = 50~100MHz , set CLK_DIV = 3'd3, + // when clk = 100~200MHz , set CLK_DIV = 3'd4, + // ...... parameter SIMULATE = 0 -)( +) ( // rstn active-low, 1:working, 0:reset input wire rstn, // clock @@ -230,6 +91,7 @@ module sd_file_reader #( where: - `FILE_NAME` specifies the name of the target file to read. +- `FILE_NAME_LEN` specifies the file name's length (in bytes). E.g., length of "example.txt" is 11. - `CLK_DIV` is the clock frequency division factor, its value needs to be determined according to the `clk` frequency you provide (see code comments for details). - `SIMULATE` is the simulation speed-up option. **Usually set to `0`**. It can be set to `1` only during simulation to speed up the SD card initialization progress and prevent the simulation from taking too much time. - `clk` is the module driving clock. @@ -241,16 +103,16 @@ where: - `file_found` will output whether the target file was found: 0 means not found, 1 means found. - If the target file is found, the module will output all the bytes in the file. For each output byte, a high-level pulse will be generated on `outen`, and the byte will appear on `outbyte`. -> **Note**: This repo only uses sddat0 (i.e. SD 1-bit bus mode) instead of sddat1\~3. When working, you need to continuously pull sddat1\~3 high (you can write `assign sddat[3:1] = 3'b111;` in the FPGA code, or use pull-up resistors on the PCB). This is to ensure that the SD card can enter SD bus mode normally, otherwise it will enter SPI bus mode. - +> :warning: This repo only uses sddat0 (i.e. SD 1-bit bus mode) instead of sddat1\~3. When working, you need to continuously pull sddat1\~3 high (you can write `assign sddat[3:1] = 3'b111;` in the FPGA code, or use pull-up resistors on the PCB). This is to ensure that the SD card can enter SD bus mode normally, otherwise it will enter SPI bus mode. +  # RTL Simulation Simulation related files are in the [SIM](./SIM) folder, where: -- sd_fake.sv is a code for FPGA to imitate an SDcard. In this simulation program, it imitates an SDcard with FAT32 system and has an file example.txt inside. It comes from another repository of mine: [FPGA-SDfake](https://github.com/WangXuan95/FPGA-SDfake) -- tb_sd_file_reader.sv is the top level of the simulation, it will call sd_file_reader.sv to read the file in sd_fake.sv . +- sd_fake.v is the code for FPGA to imitate an SDcard. It comes from another repo of mine: [FPGA-SDfake](https://github.com/WangXuan95/FPGA-SDfake) . In this simulation, it imitates an SDcard with FAT32 system with a file "example.txt" inside. And it will be readed by the design under test (sd_file_reader.v). +- tb_sd_file_reader.v is the top level of the simulation, it will call sd_file_reader.v to read the file in sd_fake.v . - tb_sd_file_reader_run_iverilog.bat is a command script to run iverilog simulations. Before simulate using iverilog, you need to install iverilog , see: [iverilog_usage](https://github.com/WangXuan95/WangXuan95/blob/main/iverilog_usage/iverilog_usage.md) @@ -259,12 +121,12 @@ Then double-click tb_sd_file_reader_run_iverilog.bat to run simulation, which wi After the simulation runs, you can open the generated dump.vcd file to view the waveform. - +  FPGA Demo: Read File =========================== -The [example-vivado-readfile](./example-vivado-readfile) folder contains a vivado project, which runs on the [Nexys4 development board](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga- trainer-board.html) (it has a microSDcard slot,). It will find the file example.txt from the root directory of the SDcard and read its entire content, and then send it to PC via **UART**. +example-vivado-readfile.zip contains a vivado project, which runs on the [Nexys4 development board](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga- trainer-board.html) (it has a microSDcard slot). It will search the file example.txt from the root directory of the SDcard and read its entire content, and then send it to PC via **UART**. Run the demo as follows: @@ -272,24 +134,189 @@ Run the demo as follows: 2. Create **example.txt** in the root directory (the file name is not limited in case), and write some content in the file. 3. Insert the SDcard into the card slot of Nexys4. 4. Plug the USB port of Nexys4 into PC, and open the corresponding serial port with software such as **Serial Assistant**, **Putty**, **HyperTerminal** or **minicom**. -5. Open the project in the directory [example-vivado-readfile](./example-vivado-readfile) with vivado, synthesize and program it. +5. Unzip example-vivado-readfile.zip . Then open the project in it with vivado, synthesize and program it. 6. Observe that the serial port prints the contents of the file. 7. Simutinously, you can see that the LEDs on the Nexys4 change, they indicate the type and status of the SDcard, see the code for the specific meaning. 8. Press the red CPU\_RESET button on Nexys4 to re-read and print out the file content again. - +  FPGA Demo: Read Sector =========================== -The [example-vivado-readsector](./example-vivado-readsector) folder contains a vivado project, which runs on the [Nexys4 development board](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga- trainer-board.html), it will read sector 0 from the SD card (it is often called the MBR sector in file systems) and send it to PC via **UART**. +example-vivado-readsector.zip contains a vivado project, which runs on the [Nexys4 development board](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga- trainer-board.html), it will read sector 0 from the SD card (it is often called the MBR sector in file systems) and send it to PC via **UART**. Run the demo as follows: 1. Prepare a **microSDcard**. Plug it into the card slot of Nexys4. 2. Plug the USB port of Nexys4 into PC, use **Serial Assistant** to open the corresponding serial port, please select "HEX Receive Mode", print each byte in hexadecimal form, so that we can see those ASCII non-printable characters. -3. Use vivado to open the project in the directory [example-vivado-readsector](./example-vivado-readsector) , synthesize and program it. +3. Unzip example-vivado-readsector.zip . Then use vivado to open the project in it, synthesize and program it. 4. Observe that the serial port prints the contents of sector 0. 5. At the same time, you can also see that the LEDs on the Nexys4 change, they indicate the type and status of the SDcard, see the code comments for the specific meaning. 6. Press the red CPU\_RESET button on Nexys4 to re-read and print out the sector content again. +  + +  + +  + +  + +  + + +FPGA SDcard File Reader +=========================== + +基于 FPGA 的 SD卡文件读取器 + +* **功能** :FPGA作为 **SD-host** , 指定文件名读取文件内容;或指定扇区号读取扇区内容。 +* **性能** :使用 SD总线,而不是 SPI总线。读取速度更快。 +* **兼容性强** :自动适配 **SD卡版本** ,自动适配 **FAT16/FAT32文件系统**。 +* 纯 Verilog 实现,便于移植和仿真。 + +| | SDv1.1 card | SDv2 card | SDHCv2 card | +| :----- | :------------: | :------------: | :------------: | +| **读取扇区** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| **读取文件 (FAT16)** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| **读取文件 (FAT32)** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | + +  + +# 背景知识 + +## SD总线 + +SD卡使用 SD 总线与 SD-host (比如读卡器)连接,SD总线的信号包括: + +| 信号名 | 输入输出方向 | +| ------------------------------ | ------------------------------------------------ | +| sdclk | host→ card | +| sdcmd | 当发起命令时 host→ card ,当响应命令时 card→host | +| sddat0、sddat1、sddat2、sddat3 | 当写数据时 host→card ,当读数据时 card→host | + +这些信号在 SD 卡和 microSD 卡上的引脚定义如下图(SD卡和microSD卡除了外形尺寸外,功能上没有差别) + +| ![pin](./pin.png) | +| :------------------------------------------: | +| 图:SD 卡(左)与 microSD 卡(右)的引脚定义 | + +  + +## 文件系统 + +SD卡本身只是一大块线性的数据存储空间,分为多个扇区 (sector),每个扇区 512 字节,扇区0的地址范围为 0x00000000\~0x000001FF,扇区1的地址范围为 0x00000200\~0x000003FF,以此类推……。底层的读取和写入操作都以扇区为单位。为了在这片线性的存储空间中组织磁盘分区和文件,人们规定了复杂的数据结构——文件系统,SD卡最常用的文件系统是 FAT16 和 FAT32 。 + +为了从 SD 卡中读取文件数据,本库分为两个功能模块: + +- 按照 SD 总线标准操控 SD 总线,指定扇区号,读取扇区。 +- 在能够读取扇区的基础上,解析文件系统,也就是给定文件名,找到文件所在的位置和长度。实际上,文件可能不是连续存储的(被拆成多块放在不同扇区),本库会正确地处理这种情况。 + +  + + +# 如何调用本模块 + +RTL 文件夹中的 sd_file_reader.v 是 SD卡文件读取器的顶层模块,它的定义如下: + +```verilog +module sd_file_reader #( + parameter FILE_NAME_LEN = 11 , // valid length of FILE_NAME (in bytes) + parameter [52*8-1:0] FILE_NAME = "example.txt", // file to read, ignore Upper and Lower Case + // For example, if you want to read a file named HeLLo123.txt in the SD card, + // this parameter can be hello123.TXT, HELLO123.txt or HEllo123.Txt + parameter [2:0] CLK_DIV = 3'd2, // when clk = 0~ 25MHz , set CLK_DIV = 3'd1, + // when clk = 25~ 50MHz , set CLK_DIV = 3'd2, + // when clk = 50~100MHz , set CLK_DIV = 3'd3, + // when clk = 100~200MHz , set CLK_DIV = 3'd4, + // ...... + parameter SIMULATE = 0 +) ( + // rstn active-low, 1:working, 0:reset + input wire rstn, + // clock + input wire clk, + // SDcard signals (connect to SDcard), this design do not use sddat1~sddat3. + output wire sdclk, + inout sdcmd, + input wire sddat0, // FPGA only read SDDAT signal but never drive it + // status output (optional for user) + output wire [3:0] card_stat, // show the sdcard initialize status + output wire [1:0] card_type, // 0=UNKNOWN , 1=SDv1 , 2=SDv2 , 3=SDHCv2 + output wire [1:0] filesystem_type, // 0=UNASSIGNED , 1=UNKNOWN , 2=FAT16 , 3=FAT32 + output reg file_found, // 0=file not found, 1=file found + // file content data output (sync with clk) + output reg outen, // when outen=1, a byte of file content is read out from outbyte + output reg [7:0] outbyte // a byte of file content +); +``` + +其中: + +- `FILE_NAME` 指定要读的目标文件名。 +- 需要在 `FILE_NAME_LEN` 指定文件名的长度 (字节数量) ,例如 "example.txt" 的长度为 11。 +- `CLK_DIV` 是时钟分频系数,它的取值需要根据你提供的 clk 时钟频率来决定(详见代码注释)。 +- `SIMULATE` 是仿真加速选项。**平常要设为 `0` **。只有仿真时才可以设 为 `1` 来加速 SD 卡初始化进度,防止仿真占用过多时间。 +- `clk` 是模块驱动时钟。 +- `rstn` 是复位信号,在开始工作前需要令 `rstn=0` 复位一下,然后令 `rstn=1` 释放。 +- `sdclk` 、 `sdcmd` 、 `sddat0` 是 SD 总线信号,需要连接到 SD 卡。 + - 注意到本模块只用到了 `sddat0` 而没用到 `sddat1~sddat3` ,因为 SD 卡上电会默认运行在 1bit 窄数据总线模式,可以用命令切换到 4bit 宽数据总线模式,我没有做切换,一直只用 `sddat0` 。而 `sddat1~sddat3` 需要弱上拉或强上拉到高电平(避免 SD 卡进入 SPI 总线模式)。 +- `card_type` 指示检测到的 SD 卡的类型:0对应未知、1对应SDv1、2对应SDv2、3对应SDHCv2。 +- `file_system_type` 指示检测到的 SD 卡的文件系统:1对应未知、2对应FAT16、3对应FAT32。 +- `file_found` 指示是否找到目标文件:0代表未找到,1代表找到。 +- 如果找到目标文件,模块会逐个输出目标文件中的所有字节,每输出一个字节,`outen` 上就产生一个高电平脉冲,同时该字节出现在 `outbyte` 上。 + +> :warning: 本库只使用了 sddat0 ,而不使用 sddat1\~3 (也即SD 1-bit总线模式)。在工作时需要将 sddat1\~3 持续拉高(可以在 FPGA 代码里 `assign sddat[3:1] = 3'b111;` ,或者在PCB板上使用上拉电阻),这样 SD 卡才能正常进入 SD 总线模式,否则会进入 SPI 总线模式。 + +  + +# 仿真 + +仿真相关的文件都在 SIM 文件夹中,其中: + +- sd_fake.v :是一个 FPGA 模拟 SD 卡的代码。它来自我的另一个库:[FPGA-SDfake](https://github.com/WangXuan95/FPGA-SDfake) 。在本仿真中,我们把它当作 SD 卡仿真模型,我们用它模拟了一个具有 FAT32 系统,里面有一个 example.txt 文件的 SD 卡。它会被我们的 SD 读取器 (sd_file_reader.v) 读取。 +- tb_sd_file_reader.v 是仿真顶层,它会调用 sd_file_reader 读取 sd_fake 中的 example.txt 。 +- tb_sd_file_reader_run_iverilog.bat 是运行 iverilog 仿真的脚本。 + +使用 iverilog 进行仿真前,需要安装 iverilog ,见:[iverilog_usage](https://github.com/WangXuan95/WangXuan95/blob/main/iverilog_usage/iverilog_usage.md) + +然后双击 tb_sd_file_reader_run_iverilog.bat 运行仿真,会运行大约几分钟。 + +仿真运行完后,可以打开生成的 dump.vcd 文件查看波形。 + +  + +读取文件示例 +=========================== + +example-vivado-readfile.zip 中包含一个 vivado 工程,它运行在 [Nexys4开发板](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga-trainer-board.html) 上(Nexys4 开发板有 microSD 卡槽,比较方便)。它会从 SD卡根目录中找到文件 example.txt 并读取其全部内容,然后用 **UART** 发送出给PC机。 + +按以下步骤运行该示例: + +1. 准备一张 **microSD卡** 。如果是标准尺寸的SD卡(大SD卡),可以用大卡转 microSD 卡的转接板转接一下。 +1. 确保卡中的文件系统是 **FAT16** 或 **FAT32** 。如果不是,则需要格式化一下。 +2. 在根目录下创建 **example.txt** (文件名大小写不限) , 在文件中随便写入一些内容。 +3. 将卡插入 Nexys4 的卡槽。 +4. 将 Nexys4 的USB口插在PC机上,用 **串口助手** 或 **Putty** 等软件打开对应的串口。 +5. 解压 example-vivado-readfile.zip ,然后用 vivado 打开目录 example-vivado-readfile 中的工程,综合并烧录。 +6. 观察到串口打印出文件内容。 +7. 同时,还能看到 Nexys4 上的 LED 灯发生变化,它们指示了SD卡的类型和状态,具体含义见代码。 +8. 按下 Nexys4 上的红色 CPU_RESET 按钮可以重新读取,再次打印出文件内容。 + +  + +读取扇区示例 +=========================== + +example-vivado-readsector.zip 中包含一个 vivado 工程,它运行在 [Nexys4开发板](http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga-trainer-board.html) 上。它会从 SD卡中读取扇区0(它在文件系统中往往叫 MBR 扇区),然后用 **UART** 发送出给PC机。 + +按以下步骤运行该示例: + +1. 准备一张 **microSD卡** 。如果是标准尺寸的SD卡(大SD卡),可以用大卡转 microSD 卡的转接板转接一下。 +2. 将 Nexys4 的USB口插在PC机上,用 **串口助手** 打开对应的串口,请选择 “HEX接收” ,以十六进制的形式打印每个字节,这样我们才能看到那些 ASCII 不可打印字符。 +3. 解压 example-vivado-readsector.zip ,然后用 vivado 打开目录 example-vivado-readsector 中的工程,综合并烧录。 +4. 观察到串口打印出扇区0的内容。 +5. 同时,还能看到 Nexys4 上的 LED 灯发生变化,它们指示了SD卡的类型和状态,具体含义见代码注释。 +6. 按下 Nexys4 上的红色 CPU_RESET 按钮可以重新读取,再次打印出扇区内容。 + diff --git a/RTL/sd_file_reader.sv b/RTL/sd_file_reader.v similarity index 80% rename from RTL/sd_file_reader.sv rename to RTL/sd_file_reader.v index 6aa1fcf..5483ba0 100644 --- a/RTL/sd_file_reader.sv +++ b/RTL/sd_file_reader.v @@ -2,24 +2,25 @@ //-------------------------------------------------------------------------------------------------------- // Module : sd_file_reader // Type : synthesizable, IP's top -// Standard: SystemVerilog 2005 (IEEE1800-2005) -// Function: A SD-host. +// Standard: Verilog 2001 (IEEE1364-2001) +// Function: A SD-card host to initialize SD-card and read files // Specify a filename, sd_file_reader will read out file content -// Compatibility: CardType : SDv1.1 , SDv2 or SDHCv2 -// FileSystem : FAT16 or FAT32 +// Support CardType : SDv1.1 , SDv2 or SDHCv2 +// Support FileSystem : FAT16 or FAT32 //-------------------------------------------------------------------------------------------------------- module sd_file_reader #( - parameter FILE_NAME = "example.txt", // file to read, ignore Upper and Lower Case - // For example, if you want to read a file named HeLLo123.txt in the SD card, - // this parameter can be hello123.TXT, HELLO123.txt or HEllo123.Txt - parameter [2:0] CLK_DIV = 3'd1, // when clk = 0~ 25MHz , set CLK_DIV = 3'd0, - // when clk = 25~ 50MHz , set CLK_DIV = 3'd1, - // when clk = 50~100MHz , set CLK_DIV = 3'd2, - // when clk = 100~200MHz , set CLK_DIV = 3'd3, + parameter FILE_NAME_LEN = 11 , // valid length of FILE_NAME (in bytes) + parameter [52*8-1:0] FILE_NAME = "example.txt", // file to read, ignore Upper and Lower Case + // For example, if you want to read a file named HeLLo123.txt in the SD card, + // this parameter can be hello123.TXT, HELLO123.txt or HEllo123.Txt + parameter [2:0] CLK_DIV = 3'd2, // when clk = 0~ 25MHz , set CLK_DIV = 3'd1, + // when clk = 25~ 50MHz , set CLK_DIV = 3'd2, + // when clk = 50~100MHz , set CLK_DIV = 3'd3, + // when clk = 100~200MHz , set CLK_DIV = 3'd4, // ...... parameter SIMULATE = 0 -)( +) ( // rstn active-low, 1:working, 0:reset input wire rstn, // clock @@ -38,20 +39,29 @@ module sd_file_reader #( output reg [7:0] outbyte // a byte of file content ); -initial file_found = 1'b0; -initial {outen,outbyte} = '0; -function automatic logic [7:0] toUpperCase(input [7:0] in); - return (in>=8'h61 && in<=8'h7A) ? in&8'b11011111 : in; + +function [7:0] toUpperCase; + input [7:0] in; +begin + toUpperCase = (in>=8'h61 && in<=8'h7A) ? (in & 8'b11011111) : in; +end endfunction -localparam TARGET_FNAME_LEN = ($bits(FILE_NAME)/8); -wire [$bits(FILE_NAME)-1:0] TARGET_FNAME = FILE_NAME; -reg [$bits(FILE_NAME)-1:0] TARGET_FNAME_UPPER; -always_comb - for(int ii=0; ii0) begin // FAT16 case + if(sectors_per_fat>0) begin // FAT16 case filesystem_parsed = FAT16; end else if(sector_content['h56]==8'h32) begin // FAT32 case filesystem_parsed = FAT32; @@ -165,7 +198,8 @@ always @ (posedge clk or negedge rstn) rootdir_sectorcount_t = rootdir_sectorcount; read_start <= 1'b0; - if(read_done) begin + + if (read_done) begin case(filesystem_state) SEARCH_MBR : if(is_boot_sector) begin filesystem_state <= SEARCH_DBR; @@ -210,7 +244,7 @@ always @ (posedge clk or negedge rstn) read_sector_no <= first_data_sector_no_t + cluster_size_t * curr_cluster_t + cluster_sector_offset_t; filesystem_state <= READ_A_FILE; end else if(cluster_sector_offset_t5'h0&&raddr[4:0]<5'hB || raddr[4:0]>=5'hE&&raddr[4:0]<5'h1A || raddr[4:0]>=5'h1C)begin if(raddr[4:0]<5'hB ? raddr[0] : ~raddr[0]) begin lastchar <= rdata; - fdtnamelen_t++; + fdtnamelen_t = fdtnamelen_t + 8'd1; end else begin //automatic logic [15:0] unicode = {rdata,lastchar}; if({rdata,lastchar} == 16'h0000) begin @@ -456,16 +501,16 @@ always @ (posedge clk or negedge rstn) begin if(raddr[4:0]<5'h8) begin if(rdata!=8'h20) begin file_name[sdtnamelen_t] <= rdata; - sdtnamelen_t++; + sdtnamelen_t = sdtnamelen_t + 8'd1; end end else if(raddr[4:0]<5'hB) begin if(raddr[4:0]==5'h8) begin file_name[sdtnamelen_t] <= 8'h2E; - sdtnamelen_t++; + sdtnamelen_t = sdtnamelen_t + 8'd1; end if(rdata!=8'h20) begin file_name[sdtnamelen_t] <= rdata; - sdtnamelen_t++; + sdtnamelen_t = sdtnamelen_t + 8'd1; end end else if(raddr[4:0]==5'hB) begin file_namelen <= sdtnamelen_t; @@ -494,12 +539,12 @@ always @ (posedge clk or negedge rstn) file_cluster <= 0; file_size <= 0; end else begin - if(fready && fnamelen==TARGET_FNAME_LEN) begin + if (fready && fnamelen==FILE_NAME_LEN) begin file_found <= 1'b1; file_cluster <= fcluster; file_size <= fsize; - for(int ii=0; ii=8 && cnt2<48) req_crc <= CalcCrc7(req_crc, request[cnt2]); end - end else if( clkcnt == {clkdivr[16:0],1'b1} && cnt1=='0 && cnt2=='1 ) begin - if(cnt3 != '0) begin + end else if( clkcnt == {clkdivr[16:0],1'b1} && cnt1==16'd0 && cnt2==6'h3F ) begin + if(cnt3 != 8'd0) begin cnt3 <= cnt3 - 8'd1; if(~sdcmdin) - cnt3 <= '0; + cnt3 <= 8'd0; else if(cnt3 == 8'd1) {done, timeout, syntaxe} <= 3'b110; - end else if(cnt4 != '1) begin + end else if(cnt4 != 8'hFF) begin cnt4 <= cnt4 - 8'd1; if(cnt4 >= 8'd96) - response <= {response[37:0], sdcmdin}; - if(cnt4 == '0) begin + {resp_st, resp_cmd, resp_arg} <= {resp_cmd, resp_arg, sdcmdin}; + if(cnt4 == 8'd0) begin {done, timeout} <= 2'b10; - syntaxe <= response.st || ((response.cmd!=req_cmd) && (response.cmd!='1) && (response.cmd!='0)); + syntaxe <= resp_st || ((resp_cmd!=req_cmd) && (resp_cmd!=6'h3F) && (resp_cmd!=6'd0)); end end end diff --git a/SIM/sd_fake.sv b/SIM/sd_fake.v similarity index 54% rename from SIM/sd_fake.sv rename to SIM/sd_fake.v index 96c2fe5..693da14 100644 --- a/SIM/sd_fake.sv +++ b/SIM/sd_fake.v @@ -2,7 +2,7 @@ //-------------------------------------------------------------------------------------------------------- // Module : sd_fake // Type : synthesizable, IP's top -// Standard: SystemVerilog 2005 (IEEE1800-2005) +// Standard: Verilog 2001 (IEEE1364-2001) // Function: Imitate a SDHCv2 Read-Only SD card //-------------------------------------------------------------------------------------------------------- @@ -24,30 +24,33 @@ module sd_fake ( output reg [31:0] show_sdcmd_arg ); -initial rdreq = '0; -initial rdaddr = '0; -initial show_sdcmd_en = '0; -initial show_sdcmd_cmd = '0; -initial show_sdcmd_arg = '0; +initial rdreq = 1'b0; +initial rdaddr = 40'd0; + +initial show_sdcmd_en = 1'b0; +initial show_sdcmd_cmd = 6'h0; +initial show_sdcmd_arg = 0; // generate reset sync with posedge of sdclk -reg rstn_sdclk_p = '0; -reg [1:0] rstn_sdclk_p_l = '0; +reg rstn_sdclk_p = 1'b0; +reg [1:0] rstn_sdclk_p_l = 2'b0; + always @ (posedge sdclk or negedge rstn_async) if(~rstn_async) - {rstn_sdclk_p, rstn_sdclk_p_l} <= '0; + {rstn_sdclk_p, rstn_sdclk_p_l} <= 3'b0; else {rstn_sdclk_p, rstn_sdclk_p_l} <= {rstn_sdclk_p_l, 1'b1}; // generate reset sync with negedge of sdclk -reg rstn_sdclk_n = '0; -reg [1:0] rstn_sdclk_n_l = '0; +reg rstn_sdclk_n = 1'b0; +reg [1:0] rstn_sdclk_n_l = 2'b0; + always @ (negedge sdclk or negedge rstn_async) if(~rstn_async) - {rstn_sdclk_n, rstn_sdclk_n_l} <= '0; + {rstn_sdclk_n, rstn_sdclk_n_l} <= 3'b0; else {rstn_sdclk_n, rstn_sdclk_n_l} <= {rstn_sdclk_n_l, 1'b1}; @@ -56,19 +59,30 @@ always @ (negedge sdclk or negedge rstn_async) reg sdcmdoe = 1'b0; reg sdcmdout = 1'b1; reg sddatoe = 1'b0; -reg [3:0] sddatout = '1; +reg [3:0] sddatout = 4'hF; assign sdcmd = sdcmdoe ? sdcmdout : 1'bz; assign sddat = sddatoe ? sddatout : 4'bz; -function automatic logic [ 6:0] CalcCrcCMD(input [ 6:0] crc, input inbit); - return {crc[5:0],crc[6]^inbit} ^ {3'b0,crc[6]^inbit,3'b0}; + +function [6:0] CalcCrcCMD; + input [6:0] crc; + input [0:0] inbit; +begin + CalcCrcCMD = {crc[5:0],crc[6]^inbit} ^ {3'b0,crc[6]^inbit,3'b0}; +end endfunction -function automatic logic [15:0] CalcCrcDAT(input [15:0] crc, input inbit); - return {crc[14:0],crc[15]^inbit} ^ {3'b0,crc[15]^inbit,6'b0,crc[15]^inbit,5'b0}; + +function [15:0] CalcCrcDAT; + input [15:0] crc; + input [ 0:0] inbit; +begin + CalcCrcDAT = {crc[14:0],crc[15]^inbit} ^ {3'b0,crc[15]^inbit,6'b0,crc[15]^inbit,5'b0}; +end endfunction + localparam BLOCK_SIZE = 512; // 512B per block localparam [ 15:0] RCA_REG = 16'h0013; @@ -85,71 +99,101 @@ localparam [ 64:0] SCR_REG = 64'h0005_0000_00000000; // 64'h0231_0000_00000000; // Normal card, disable 4-bit bus mode // 64'h0235_0000_00000000; // Normal card, enable 4-bit bus mode -reg last_is_acmd=1'b0; +reg last_is_acmd = 1'b0; -enum logic [1:0] {WAITINGCMD, LOADRESP, RESPING} respstate = WAITINGCMD; -struct packed{ - logic [ 3:0] pre_st; - logic [ 5:0] cmd; - logic [31:0] arg; - logic [ 6:0] crc; - logic stop; -} request = '0; +localparam [1:0] WAITINGCMD = 2'd0, + LOADRESP = 2'd1, + RESPING = 2'd2; +reg [1:0] respstate = WAITINGCMD; -typedef enum logic [3:0] {IDLE, READY, IDENT, STBY, TRAN, DATA, RCV, PRG, DIS} current_state_t; -struct packed{ - logic out_of_range; - logic address_error; - logic block_len_error; - logic erase_seq_error; - logic erase_param; - logic wp_violation; - logic card_is_locked; - logic lock_unlock_failed; - logic com_crc_error; - logic illegal_command; - logic card_ecc_failed; - logic cc_error; - logic error; - logic [1:0] rsvd1; // reserved - logic csd_overwrite; - logic wp_erase_skip; - logic card_ecc_disabled; - logic erase_reset; - current_state_t current_state; - logic ready_for_data; - logic [1:0] rsvd2; - logic app_cmd; - logic rsvd3; - logic ake_seq_error; - logic [2:0] rsvd4; -} cardstatus = '0; +reg [49:0] request = 50'h3ffffffffffff; +wire [ 3:0] request_pre_st; +wire [ 5:0] request_cmd; +wire [31:0] request_arg; +wire [ 6:0] request_crc; +wire request_stop; +assign {request_pre_st, request_cmd, request_arg, request_crc, request_stop} = request; + + +localparam [3:0] IDLE = 4'd0, + READY = 4'd1, + IDENT = 4'd2, + STBY = 4'd3, + TRAN = 4'd4, + DATA = 4'd5, + RCV = 4'd6, + PRG = 4'd7, + DIS = 4'd8; +//typedef enum logic [3:0] {IDLE, READY, IDENT, STBY, TRAN, DATA, RCV, PRG, DIS} current_state_t; + + +//struct packed{ +reg cardstatus_out_of_range = 0; +reg cardstatus_address_error = 0; +reg cardstatus_block_len_error = 0; +reg cardstatus_erase_seq_error = 0; +reg cardstatus_erase_param = 0; +reg cardstatus_wp_violation = 0; +reg cardstatus_card_is_locked = 0; +reg cardstatus_lock_unlock_failed = 0; +reg cardstatus_com_crc_error = 0; +reg cardstatus_illegal_command = 0; +reg cardstatus_card_ecc_failed = 0; +reg cardstatus_cc_error = 0; +reg cardstatus_error = 0; +reg [1:0] cardstatus_rsvd1 = 0; // reserved +reg cardstatus_csd_overwrite = 0; +reg cardstatus_wp_erase_skip = 0; +reg cardstatus_card_ecc_disabled = 0; +reg cardstatus_erase_reset = 0; +reg [3:0] cardstatus_current_state = 0; +reg cardstatus_ready_for_data = 0; +reg [1:0] cardstatus_rsvd2 = 0; +reg cardstatus_app_cmd = 0; +reg cardstatus_rsvd3 = 0; +reg cardstatus_ake_seq_error = 0; +reg [2:0] cardstatus_rsvd4 = 0; + +wire [31:0] cardstatus = {cardstatus_out_of_range, cardstatus_address_error, cardstatus_block_len_error, cardstatus_erase_seq_error, cardstatus_erase_param, cardstatus_wp_violation, cardstatus_card_is_locked, cardstatus_lock_unlock_failed, cardstatus_com_crc_error, cardstatus_illegal_command, cardstatus_card_ecc_failed, cardstatus_cc_error, cardstatus_error, cardstatus_rsvd1, cardstatus_csd_overwrite, cardstatus_wp_erase_skip, cardstatus_card_ecc_disabled, cardstatus_erase_reset, cardstatus_current_state, cardstatus_ready_for_data, cardstatus_rsvd2, cardstatus_app_cmd, cardstatus_rsvd3, cardstatus_ake_seq_error, cardstatus_rsvd4}; wire [15:0] cardstatus_short = {cardstatus[23:22], cardstatus[19], cardstatus[12:0]}; // for R6 (CMD3) + localparam HIGHZLEN = 1; localparam WAITLEN = HIGHZLEN + 3; -reg [ 5:0] cmd='0; -reg [119:0] arg='0; -reg [ 6:0] crc='0; + +reg [ 5:0] cmd = 6'd0; +reg [119:0] arg = 120'd0; +reg [ 6:0] crc = 7'd0; reg response_end = 1'b0; -reg valid='0, dummycrc='0; -int idx=0, arglen=0; +reg valid=1'b0, dummycrc=1'b0; +reg [31:0] idx = 0; +reg [ 7:0] arglen = 0; -task automatic response_init(input _valid, input _dummycrc, input [5:0] _cmd, input int _arglen, input [119:0] _arg); + +task response_init; + input _valid; + input _dummycrc; + input [5:0] _cmd; + input [7:0] _arglen; + input [119:0] _arg; +begin cmd = _cmd; arg = _arg; - crc = '0; + crc = 0; valid = _valid; dummycrc = _dummycrc; idx = 0; arglen = _arglen; response_end = 1'b0; +end endtask -task automatic response_yield; + +task response_yield; +begin response_end = 1'b0; if ( ~valid) begin sdcmdoe = 0; @@ -184,18 +228,21 @@ task automatic response_yield; sdcmdout = 1; response_end = 1'b1; end - if(~response_end) idx++; + if(~response_end) idx = idx + 1; +end endtask + localparam DATAWAITLEN = HIGHZLEN + 16; localparam DATASTARTLEN = DATAWAITLEN + 1; + reg read_task=0, read_continue=0, read_scr=0, read_sdstat=0, read_cmd6stat=0; reg [31:0] read_idx = 0; wire [31:0] read_byte_idx = (read_idx-DATASTARTLEN); wire [ 3:0] readbyteidx = 4'hf - read_byte_idx[3:0]; wire [ 1:0] readquadidx = 2'h3 - read_byte_idx[1:0]; reg [15:0] read_crc = 0; -reg [15:0] read_crc_wide[4]; +reg [15:0] read_crc_wide [0:3]; wire [15:0] rddata_reversed = {rddata[7:0], rddata[15:8]}; reg widebus = 1'b0; // 0:1bit Mode 1:4bit Mode @@ -207,15 +254,23 @@ wire [511:0] SD_STAT = { widebus,1'b0, 1'b0, 13'h0, // bus-width, no security 4'h9, 428'h0 }; -reg [5:0] cmd6_invalid = 6'h0; +reg [ 5:0] cmd6_invalid = 6'h0; wire [511:0] CMD6_RESP = { 12'h0, (~(|cmd6_invalid)), 3'h0, // 8mA when not invalid 16'h8001, 16'h8001, 16'h8001, 16'h8001, 16'h8001, 16'h8001, {4{cmd6_invalid[5]}}, {4{cmd6_invalid[4]}}, {4{cmd6_invalid[3]}}, {4{cmd6_invalid[2]}}, {4{cmd6_invalid[1]}}, {4{cmd6_invalid[0]}}, 376'h0 }; -assign show_status_bits = { response_end, widebus, cardstatus.ready_for_data, cardstatus.app_cmd, cardstatus.current_state }; +assign show_status_bits = { response_end, widebus, cardstatus_ready_for_data, cardstatus_app_cmd, cardstatus_current_state }; -task automatic data_response_init(input [31:0] _read_sector_no=0, input _read_continue=1'b0); + + +integer i; + + +task data_response_init; + input [31:0] _read_sector_no; + input [ 0:0] _read_continue; +begin read_task = 1; read_continue = _read_continue; read_scr = 0; @@ -224,59 +279,74 @@ task automatic data_response_init(input [31:0] _read_sector_no=0, input _read_co rdaddr <= {_read_sector_no,8'h0}; read_idx = 0; read_crc = 0; - for(int i=0;i<4;i++) read_crc_wide[i] = '0; + for(i=0;i<4;i=i+1) read_crc_wide[i] = 0; +end endtask -task automatic data_response_sdstat_init; + +task data_response_sdstat_init; +begin read_task = 1; read_continue = 0; read_scr = 0; read_sdstat = 1; read_cmd6stat = 0; - rdaddr <= '0; + rdaddr <= 0; read_idx = 0; read_crc = 0; - for(int i=0;i<4;i++) read_crc_wide[i] = '0; + for(i=0;i<4;i=i+1) read_crc_wide[i] = 0; +end endtask -task automatic data_response_cmd6stat_init; + +task data_response_cmd6stat_init; +begin read_task = 1; read_continue = 0; read_scr = 0; read_sdstat = 0; read_cmd6stat = 1; - rdaddr <= '0; + rdaddr <= 0; read_idx = 0; read_crc = 0; - for(int i=0;i<4;i++) read_crc_wide[i] = '0; + for(i=0;i<4;i=i+1) read_crc_wide[i] = 0; +end endtask -task automatic data_response_scr_init; + +task data_response_scr_init; +begin read_task = 1; read_continue = 0; read_scr = 1; read_sdstat = 0; read_cmd6stat = 0; - rdaddr <= '0; + rdaddr <= 0; read_idx = 0; read_crc = 0; - for(int i=0;i<4;i++) read_crc_wide[i] = '0; + for(i=0;i<4;i=i+1) read_crc_wide[i] = 0; +end endtask -task automatic data_response_stop; + +task data_response_stop; +begin read_task = 0; read_continue = 0; read_scr = 0; read_sdstat = 0; read_cmd6stat = 0; - rdaddr <= '0; + rdaddr <= 0; read_idx = 0; read_crc = 0; - for(int i=0;i<4;i++) read_crc_wide[i] = '0; + for(i=0;i<4;i=i+1) read_crc_wide[i] = 0; +end endtask -task automatic data_response_yield; - rdreq <='0; + +task data_response_yield; +begin + rdreq <=0; sddatoe = 1'b1; if(~read_task) begin sddatoe = 1'b0; @@ -289,7 +359,7 @@ task automatic data_response_yield; end else if(read_idx 512) cardstatus.block_len_error = 1'b1; - response_init( 1, 0 , request.cmd , 32 , cardstatus ); - cardstatus.illegal_command = 1'b0; + 16 : if(cardstatus_current_state==TRAN) begin // SET_BLOCKLEN + if(request_arg > 512) cardstatus_block_len_error = 1'b1; + response_init( 1, 0 , request_cmd , 32 , cardstatus ); + cardstatus_illegal_command = 1'b0; end - 17 : if(cardstatus.current_state==TRAN) begin // READ_SINGLE_BLOCK - response_init( 1, 0 , request.cmd , 32 , cardstatus ); - data_response_init(request.arg); - cardstatus.illegal_command = 1'b0; + 17 : if(cardstatus_current_state==TRAN) begin // READ_SINGLE_BLOCK + response_init( 1, 0 , request_cmd , 32 , cardstatus ); + data_response_init(request_arg, 0); + cardstatus_illegal_command = 1'b0; end - 18 : if(cardstatus.current_state==TRAN) begin // READ_MULTIPLE_BLOCK - response_init( 1, 0 , request.cmd , 32 , cardstatus ); - data_response_init(request.arg, 1); - cardstatus.illegal_command = 1'b0; + 18 : if(cardstatus_current_state==TRAN) begin // READ_MULTIPLE_BLOCK + response_init( 1, 0 , request_cmd , 32 , cardstatus ); + data_response_init(request_arg, 1); + cardstatus_illegal_command = 1'b0; end - 55 : if(request.arg[31:16]=='0 || request.arg[31:16]==RCA_REG) begin // APP_CMD + 55 : if(request_arg[31:16]==16'd0 || request_arg[31:16]==RCA_REG) begin // APP_CMD last_is_acmd <= 1'b1; - cardstatus.app_cmd = 1'b1; - response_init( 1, 0 , request.cmd , 32 , cardstatus ); - cardstatus.illegal_command = 1'b0; + cardstatus_app_cmd = 1'b1; + response_init( 1, 0 , request_cmd , 32 , cardstatus ); + cardstatus_illegal_command = 1'b0; end 41 : if(last_is_acmd) begin // SD_SEND_OP_COND - cardstatus.app_cmd = 1'b1; + cardstatus_app_cmd = 1'b1; response_init( 1, 1 , 6'b111111 , 32 , OCR_REG ); - cardstatus.illegal_command = 1'b0; + cardstatus_illegal_command = 1'b0; end 42 : if(last_is_acmd) begin // SET_CLR_CARD_DETECT - cardstatus.app_cmd = 1'b1; - response_init( 1, 0 , request.cmd , 32 , cardstatus ); - cardstatus.illegal_command = 1'b0; + cardstatus_app_cmd = 1'b1; + response_init( 1, 0 , request_cmd , 32 , cardstatus ); + cardstatus_illegal_command = 1'b0; end - 51 : if(last_is_acmd && cardstatus.current_state==TRAN) begin // SEND_SCR - cardstatus.app_cmd = 1'b1; - response_init( 1, 0 , request.cmd , 32 , cardstatus ); + 51 : if(last_is_acmd && cardstatus_current_state==TRAN) begin // SEND_SCR + cardstatus_app_cmd = 1'b1; + response_init( 1, 0 , request_cmd , 32 , cardstatus ); data_response_scr_init; - cardstatus.illegal_command = 1'b0; + cardstatus_illegal_command = 1'b0; end default : begin // undefined CMD response_init( 0, 0 , 0 , 0 , 0 ); - cardstatus.illegal_command = 1'b1; + cardstatus_illegal_command = 1'b1; end endcase end @@ -566,14 +644,14 @@ always @ (negedge sdclk or negedge rstn_sdclk_n) always @ (posedge sdclk or negedge rstn_sdclk_p) if(~rstn_sdclk_p) begin show_sdcmd_en <= 1'b0; - show_sdcmd_cmd <= '0; - show_sdcmd_arg <= '0; + show_sdcmd_cmd <= 0; + show_sdcmd_arg <= 0; end else begin show_sdcmd_en <= 1'b0; - if(respstate == LOADRESP) begin + if (respstate == LOADRESP) begin show_sdcmd_en <= 1'b1; - show_sdcmd_cmd <= request.cmd; - show_sdcmd_arg <= request.arg; + show_sdcmd_cmd <= request_cmd; + show_sdcmd_arg <= request_arg; end end diff --git a/SIM/tb_sd_file_reader.sv b/SIM/tb_sd_file_reader.v similarity index 97% rename from SIM/tb_sd_file_reader.sv rename to SIM/tb_sd_file_reader.v index 400b982..5f478ed 100644 --- a/SIM/tb_sd_file_reader.sv +++ b/SIM/tb_sd_file_reader.v @@ -2,7 +2,7 @@ //-------------------------------------------------------------------------------------------------------- // Module : tb_sd_file_reader // Type : simulation, top -// Standard: SystemVerilog 2005 (IEEE1800-2005) +// Standard: Verilog 2001 (IEEE1364-2001) // Function: testbench for sd_file_reader // connect sd_file_reader (SD-host) to sd_fake (SD-card) // sd_file_reader will read sd_fake's content @@ -45,7 +45,7 @@ always @ (posedge clk) if(outen) $display("readout byte: %c", outbyte); //-------------------------------------------------------------------------------------------------------- sd_file_reader #( .FILE_NAME ( "example.txt" ), - .CLK_DIV ( 0 ), + .CLK_DIV ( 1 ), .SIMULATE ( 1 ) ) sd_file_reader_i ( .rstn ( rstn ), @@ -102,8 +102,8 @@ sd_fake sd_fake_i ( // A ROM, contains a complete FAT32 partition data mirror //-------------------------------------------------------------------------------------------------------- always @ (posedge sdclk) - if(rom_req) - case(rom_addr) + if (rom_req) + case (rom_addr) 40'h00000000df: rom_data <= 16'h8200; 40'h00000000e0: rom_data <= 16'h0003; 40'h00000000e1: rom_data <= 16'hd50b; diff --git a/SIM/tb_sd_file_reader_run_iverilog.bat b/SIM/tb_sd_file_reader_run_iverilog.bat index 24643c9..365d5b9 100644 --- a/SIM/tb_sd_file_reader_run_iverilog.bat +++ b/SIM/tb_sd_file_reader_run_iverilog.bat @@ -1,5 +1,5 @@ del sim.out dump.vcd -iverilog -g2005-sv -o sim.out tb_sd_file_reader.sv sd_fake.sv ../RTL/sd_file_reader.sv ../RTL/sd_reader.sv ../RTL/sdcmd_ctrl.sv +iverilog -g2001 -o sim.out tb_sd_file_reader.v sd_fake.v ../RTL/sd_file_reader.v ../RTL/sd_reader.v ../RTL/sdcmd_ctrl.v vvp -n sim.out del sim.out pause \ No newline at end of file diff --git a/example-vivado-readfile.zip b/example-vivado-readfile.zip new file mode 100644 index 0000000000000000000000000000000000000000..fa3e0348e47c43956071d7b77e75b806d3e7502d GIT binary patch literal 85564 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

>Wk+Awd7?NPlIj36PsGYMJZ~#ts1kE5 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 EKei0#wEzGB literal 0 HcmV?d00001 diff --git a/example-vivado-readfile/Nexys-4-DDR-pins.xdc b/example-vivado-readfile/Nexys-4-DDR-pins.xdc deleted file mode 100644 index 757eacf..0000000 --- a/example-vivado-readfile/Nexys-4-DDR-pins.xdc +++ /dev/null @@ -1,41 +0,0 @@ - -## Clock -set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk100mhz }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz -create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk100mhz}]; - - -set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { resetn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn - -## LEDs -set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L18P_T2_A24_15 Sch=led[0] -set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1] -set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[2] -set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L8P_T1_D11_14 Sch=led[3] -set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L7P_T1_D09_14 Sch=led[4] -set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5] -set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { led[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6] -set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7] -set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8] -set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9] -set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { led[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10] -set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { led[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11] -set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { led[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12] -set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { led[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13] -set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { led[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14] -set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { led[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15] - - -# UART -set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_tx }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out - - -# SDcard -set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { sdcard_pwr_n }]; #IO_L14P_T2_SRCC_35 Sch=sd_resetn -#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd -set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { sdclk }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sdclk -set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { sdcmd }]; #IO_L16N_T2_35 Sch=sdcmd -set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { sddat0 }]; #IO_L16P_T2_35 Sch=sd_dat[0] -set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { sddat1 }]; #IO_L18N_T2_35 Sch=sd_dat[1] -set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { sddat2 }]; #IO_L18P_T2_35 Sch=sd_dat[2] -set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { sddat3 }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3] - diff --git a/example-vivado-readfile/Nexys4-ReadFile.xpr b/example-vivado-readfile/Nexys4-ReadFile.xpr deleted file mode 100644 index dbccc20..0000000 --- a/example-vivado-readfile/Nexys4-ReadFile.xpr +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default_dashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example-vivado-readfile/RTL/top.sv b/example-vivado-readfile/RTL/top.sv deleted file mode 100644 index 4ce66ac..0000000 --- a/example-vivado-readfile/RTL/top.sv +++ /dev/null @@ -1,84 +0,0 @@ - -//-------------------------------------------------------------------------------------------------------- -// Module : top -// Type : synthesizable, FPGA's top, IP's example design -// Standard: SystemVerilog 2005 (IEEE1800-2005) -// Function: an example of sd_file_reader, read a file from SDcard and send file content to UART -// this example runs on Digilent Nexys4-DDR board (Xilinx Artix-7), -// see http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga-trainer-board.html -//-------------------------------------------------------------------------------------------------------- - -module top ( - // clock = 100MHz - input wire clk100mhz, - // rstn active-low, You can re-read SDcard by pushing the reset button. - input wire resetn, - // when sdcard_pwr_n = 0, SDcard power on - output wire sdcard_pwr_n, - // signals connect to SD bus - output wire sdclk, - inout sdcmd, - input wire sddat0, - output wire sddat1, sddat2, sddat3, - // 16 bit led to show the status of SDcard - output wire [15:0] led, - // UART tx signal, connected to host-PC's UART-RXD, baud=115200 - output wire uart_tx -); - -assign led[15:9] = '0; - -assign sdcard_pwr_n = 1'b0; - -assign {sddat1, sddat2, sddat3} = 3'b111; // Must set sddat1~3 to 1 to avoid SD card from entering SPI mode - - -wire outen; // when outen=1, a byte of file content is read out from outbyte -wire [7:0] outbyte; // a byte of file content - - -//---------------------------------------------------------------------------------------------------- -// sd_file_reader -//---------------------------------------------------------------------------------------------------- -sd_file_reader #( - .FILE_NAME ( "example.txt" ), // file name to read - .CLK_DIV ( 2 ), // because clk=100MHz, CLK_DIV is set to 2 - .SIMULATE ( 0 ) -) sd_file_reader_i ( - .rstn ( resetn ), - .clk ( clk100mhz ), - .sdclk ( sdclk ), - .sdcmd ( sdcmd ), - .sddat0 ( sddat0 ), - .card_stat ( led[3:0] ), // show the sdcard initialize status - .card_type ( led[5:4] ), // 0=UNKNOWN , 1=SDv1 , 2=SDv2 , 3=SDHCv2 - .filesystem_type ( led[7:6] ), // 0=UNASSIGNED , 1=UNKNOWN , 2=FAT16 , 3=FAT32 - .file_found ( led[ 8] ), // 0=file not found, 1=file found - .outen ( outen ), - .outbyte ( outbyte ) -); - - -//---------------------------------------------------------------------------------------------------- -// send file content to UART -//---------------------------------------------------------------------------------------------------- -uart_tx #( - .CLK_DIV ( 868 ), // 100MHz/868 = 115200 - .PARITY ( "NONE" ), // no parity bit - .ASIZE ( 14 ), // - .DWIDTH ( 1 ), // tx_data is 8 bit (1 Byte) - .ENDIAN ( "LITTLE" ), // - .MODE ( "RAW" ), // - .END_OF_DATA ( "" ), // - .END_OF_PACK ( "" ) // -) uart_tx_i ( - .rstn ( resetn ), - .clk ( clk100mhz ), - .tx_data ( outbyte ), - .tx_last ( 1'b0 ), - .tx_en ( outen ), - .tx_rdy ( ), - .o_uart_tx ( uart_tx ) -); - -endmodule diff --git a/example-vivado-readfile/RTL/uart_tx.sv b/example-vivado-readfile/RTL/uart_tx.sv deleted file mode 100644 index 62e62c6..0000000 --- a/example-vivado-readfile/RTL/uart_tx.sv +++ /dev/null @@ -1,188 +0,0 @@ - -//-------------------------------------------------------------------------------------------------------- -// Module : uart_tx -// Type : synthesizable, IP's top -// Standard: SystemVerilog 2005 (IEEE1800-2005) -// Function: buffer input data and send them to UART -// UART format: 8 data bits -//-------------------------------------------------------------------------------------------------------- - -module uart_tx #( - parameter CLK_DIV = 434, // UART baud rate = clk freq/(2*UART_TX_CLK_DIV). for example, when clk=50MHz, UART_TX_CLK_DIV=434, then baud=50MHz/(2*434)=115200 - parameter PARITY = "NONE", // "NONE", "ODD" or "EVEN" - parameter ASIZE = 10, // UART TX buffer size = 2^ASIZE bytes, Set it smaller if your FPGA doesn't have enough BRAM - parameter DWIDTH = 1, // Specify width of tx_data , that is, how many bytes can it input per clock cycle - parameter ENDIAN = "LITTLE", // "LITTLE" or "BIG". when DWIDTH>=2, this parameter determines the byte order of tx_data - parameter MODE = "RAW", // "RAW", "PRINTABLE", "HEX" or "HEXSPACE" - parameter END_OF_DATA = "", // Specify a extra send byte after each tx_data. when ="", do not send this extra byte - parameter END_OF_PACK = "" // Specify a extra send byte after each tx_data with tx_last=1. when ="", do not send this extra byte -)( - input wire rstn, - input wire clk, - // user interface - input wire [DWIDTH*8-1:0] tx_data, - input wire tx_last, - input wire tx_en, - output wire tx_rdy, - // uart tx output signal - output reg o_uart_tx -); - -initial o_uart_tx = 1'b1; - - - -function automatic logic [7:0] hex2ascii (input [3:0] hex); - return {4'h3, hex} + ((hex<4'hA) ? 8'h0 : 8'h7) ; -endfunction - - -function automatic logic is_printable_ascii(input [7:0] ascii); - return (ascii>=8'h20 && ascii<8'h7F) || ascii==8'h0A || ascii==8'h0D; -endfunction - - -function automatic logic [11:0] build_send_byte(input [7:0] send_byte); - if ( PARITY == "ODD" ) - return {1'b1, (~(^send_byte)), send_byte, 2'b01}; - else if( PARITY == "EVEN" ) - return {1'b1, (^send_byte) , send_byte, 2'b01}; - else - return {1'b1, 1'b1 , send_byte, 2'b01}; -endfunction - - -function automatic logic [6+35:0] build_send_data(input [7:0] send_data); - logic [ 5:0] dcnt = '0; - logic [35:0] data = '1; - if( MODE != "PRINTABLE" || is_printable_ascii(send_data) ) begin - if( MODE == "HEXSPACE" ) begin - dcnt += 6'd12; - data[11:0] = build_send_byte(8'h20); - end - dcnt += 6'd12; - data <<= 12; - if( MODE == "HEX" || MODE == "HEXSPACE" ) begin - data[11:0] = build_send_byte(hex2ascii(send_data[3:0])); - dcnt += 6'd12; - data <<= 12; - data[11:0] = build_send_byte(hex2ascii(send_data[7:4])); - end else begin - data[11:0] = build_send_byte(send_data); - end - end - return {dcnt, data}; -endfunction - - -function automatic logic [6+35:0] build_send_eod(input send_last); - logic [ 5:0] dcnt = '0; - logic [35:0] data = '1; - if( END_OF_PACK != "" && send_last ) begin - dcnt += 6'd12; - data[11:0] = build_send_byte((8)'(END_OF_PACK)); - end - if( END_OF_DATA != "" ) begin - dcnt += 6'd12; - data <<= 12; - data[11:0] = build_send_byte((8)'(END_OF_DATA)); - end - return {dcnt, data}; -endfunction - - - - -reg [DWIDTH*8-1:0] tx_data_endian; - -always_comb - if(ENDIAN == "BIG") begin - for(int i=0; i '0 ) begin - if( cyc+1 == CLK_DIV ) begin - txdcnt <= txdcnt - 6'd1; - {txdata, o_uart_tx} <= {1'b1, txdata}; - end - end else if( bcnt > '0 ) begin - bcnt <= bcnt - 16'd1; - send_data <= send_data >> 8; - {txdcnt, txdata} <= build_send_data(send_data[7:0]); - end else if( eod ) begin - eod <= '0; - {txdcnt, txdata} <= build_send_eod(send_last); - end else if( fifo_empty_n ) begin - fifo_rptr <= fifo_rptr + (ASIZE+1)'(1); - fifo_rd_en <= 1'b1; - end - end - - -endmodule diff --git a/example-vivado-readsector.zip b/example-vivado-readsector.zip new file mode 100644 index 0000000000000000000000000000000000000000..280203481340a025a6d2abefdce47b642ba2c904 GIT binary patch literal 8350 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

nP8HKT6t14R||D z%0B-qo)k;z*N;@hGkHP-01{*X0H(j)Gri2+Jxo|?f-JOz@qXiRc6o0|C$t#*;nZdOTdY}r8RHymSz zne-gZcFiSvdM6P~LMg29FpeC!PVY|x#U47Xe9vvS_z- zSZ7j);xg>!X8~UB+?(m|7EmzrF>UxY?eo7IV<#*sa%eizu%V@HDVy&FRN}Tl%^acH zjO%K|gJg)(BiZigCzYc_Tk}J^#v!+9$K(lXYSVPAt+txcI1|r2z)w!Uc7TmMRdFnh zRg3wW2NmjSorXs(%FnxX2{0DsUSRpK<$ilx;!wgVBhyoa&dXZl(F*j5^KzFrKMLsu zVZE}i-PJxIY@(pJaz_ZHJJUJ|4@ocU27Xk4f+rnN-YsEo-C>Fb+~K)SDaJv>gv(C} z9W4y`{W12W#?0^!iJe>JJ$b;E4u-Hu2oshOOX$miP7wT<3jOIbG-1($V3>_iDT$ne z4X_JUlkmh)_hM_eXg+bLM7w9!^+diFQ)h>=E^=86x2D+L_rO9!ioStcJmRia3 z2l$)oArIV(>`b1MmhMx(Yf9a&-KZ47rjQ-H<;R_3eyy6XckgRi4IL3-y~q4cjbE^h zWYN%y%EGV;GE#BCkaZwT1ZROVG`w9cG$8MMNhm&hry@1B*obDdrkAZEPZLOMV)#Wg zLMbz@D?Y0dsgLmN#rZLEE6P=e&ilA2O}4Mm!7}Le?rhQRR`*(wu(#jxhFWovB?;ZL zO@P(r8Ml6_l|R;vk63xbO(+T`i9@_Hj!8Cc^PvsIY5(3h64e?>*AKJJcizCgD#n!7= ztH^HA{nJihle=KV?H0(}r5>IGi_xa(HOOC2#d~=Q)x;)v2@8E&X*Z`XJByG>m%rxQ z0DMc?`-bWQuFE5rH@RUEP;c@2nKM?)b_{%?&tWJ2;Bu(IKK$bMZE?+)2_I)O(vUuXqy!ZgB8-KKY@6JajLa3mR%VBNpzfKcbkP{GU|oy@&?%<3{cDZ zfUaH@_G55n+XH``ZULe6YSpZ|5F>xaX{K0hAEH3cDN`Y~IZ4LgVr5G1dl(^nUWGWC zAVJ>POsVF4?N$!uZiT%hjl=HzVc!IVFw>#on$#@-3UPiaeCwj)<;7-`kD>~Zv0p*f zg7yUE#*dwl>xCmT0t7U6Q>$gnoPCdUlbTjRuQYFDQXL7y z{azOA4m0KB-l5W-sWNsw^B=A;pqg*npm41e($?}81bk%S3c||2jC3?9_n{m>!rbg) zmFiIphY^k9tyf`;iCoGE&=cZ3NNsiAqw4qDAPaFTH&8ak8(#i+Rkrn;S2tO+f_51$el zC&hT&NP(=h9%;-x2PL;8&g+5Nrf+5FU#T^OTRv}WJtJKQC8DvlZy+Q&qS714nZU~h zt7Gn&uQxCe#(7>+@fCvAN{Lj4oTI+Ja#|8*aD#co zkb)mD@;RnGG|h-;X`6tDs$lr_=gPev%50XcxK*r?H=3~&{TPg`>H4$KuClz~ln-B| zd-;TZnEI2zTdvmk3ax@BTh6-Qy_J1=am5OQ+kajJhZZMuU5c)b$1MTZ_SzugL<0fk zP_Yu}*dDW=DhL;svE{M6w}oy!PT?HA`DcJ-eS{`j#Vf90IZtwgZu}gMU=6T$Wje}< z+6Qdgr%Cbo;@}p!YY&ibirAqBslp6|&!J74fVn7D)bKgc9zM)74=B-4+dl{@Afa1(BEWG8qsKmDSKYkh#KrO60OcC>4kfsteJ5QV_U%d;5U z>Qj)3?;0s3`PZ3N9LiHi#L%#~J-^`*2wTxS!<7Z}*-YtLM2b_h2ZDwxrx(xpO*E~R zhyL~OU6V8cSF!r42&;q2rt2cq!c9vx>-eIHfuHU>{yyG}f>f0ws)Z#3ER>s>wI4;i zwdM&+^P_&t(vp7?u^@;EJu}`!j8?U9Ee}2ihn&90sorM8gz^9x9-Q~-6O|KNVOwm4 zk~7>2D?DK`e7(O8-#Y@k={d*z;oFL=RSi{GEb!k0fyQ<-!9{(N%r-$W2!F9OmZ^ zNhn+<-)k|I@4N+*=B54=z13_ro}3kKqilV^&*1TtZL07K6Nr_MOt@OX`51SQ>8h8j zaDH-0nLwPZ!!Qo@!A; zp=hDMyt|Ful_4%bHSj&6>snVF;Tzk0Ua>8y=c~CYQ!NCq;jO9pz=oyG>pLograJD+ zy_*rrEr#wF2s*Tt%1T21Wt$O=KGlY)W|(|6k0WI=n}-Yp<_jk7 zd(&0ZW2@I0_gT?4;|ob*IM^Grq;rahv!Z+jz69q_Zzi-Av}3f=@6wN1S4yd6<3eR* zanH1~MD6hfYaL21Vf(1yr?)sQ)!#cve)gE5wyv_+B;U5jFS@{drO#jBscP|2m1`OA zmR0yvJv#U4$W-sn*^;T6`&+h!%TR4eP-YH?c|?@`%vf(mFBv>fHwZqBeQ&EBvw!LTiI#2OC_Z zr+sJ>!x!|`&!z8_lz>KH^OhAoil$9Kl~a+@hS(&WD#eQ1IE?Xiu~p)N1*>#gJ%{2D zK+&@lDC;V7sKW`kSN<~LI#!E7(OovhZTRVjMju-*^gf1jzx#*35Qkqrj>0L^=VXjA z_jZoZpLUDYXy~2S7OfMz+xt$IJ`R(1r*<(q(@`kP0dBF<$@>CE15_Z8o`EszxnFg56JWqrOV znD1n`IbQQbLD5#6H?)8-uu_2kRJo=96-NASzp^lYwf|hlMFmj*^#%-p7$8Tgumqd2 z2os~*^jCjZZvM$cXA$Nftp8N){U_`9cZ7eP|C#mwtNs4T52eJKtC?Pa$xR4|o=abZ znWnb*H~zmD;Qr(@!2K=%|1HP;DL_MtF7Es<@IU)&UdulO_)i(Ke+uy1*a+zVO@QC| zvOjrumw~fmzj#uh0o3PTeOS<+ynh({-?M7}Km8B3mkZ7S literal 0 HcmV?d00001 diff --git a/example-vivado-readsector/Nexys-4-DDR-pins.xdc b/example-vivado-readsector/Nexys-4-DDR-pins.xdc deleted file mode 100644 index 757eacf..0000000 --- a/example-vivado-readsector/Nexys-4-DDR-pins.xdc +++ /dev/null @@ -1,41 +0,0 @@ - -## Clock -set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk100mhz }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz -create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk100mhz}]; - - -set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { resetn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn - -## LEDs -set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L18P_T2_A24_15 Sch=led[0] -set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1] -set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[2] -set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L8P_T1_D11_14 Sch=led[3] -set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L7P_T1_D09_14 Sch=led[4] -set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5] -set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { led[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6] -set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7] -set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8] -set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9] -set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { led[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10] -set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { led[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11] -set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { led[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12] -set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { led[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13] -set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { led[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14] -set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { led[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15] - - -# UART -set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_tx }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out - - -# SDcard -set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { sdcard_pwr_n }]; #IO_L14P_T2_SRCC_35 Sch=sd_resetn -#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd -set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { sdclk }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sdclk -set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { sdcmd }]; #IO_L16N_T2_35 Sch=sdcmd -set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { sddat0 }]; #IO_L16P_T2_35 Sch=sd_dat[0] -set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { sddat1 }]; #IO_L18N_T2_35 Sch=sd_dat[1] -set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { sddat2 }]; #IO_L18P_T2_35 Sch=sd_dat[2] -set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { sddat3 }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3] - diff --git a/example-vivado-readsector/Nexys4-ReadSector.xpr b/example-vivado-readsector/Nexys4-ReadSector.xpr deleted file mode 100644 index 968a7d2..0000000 --- a/example-vivado-readsector/Nexys4-ReadSector.xpr +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default_dashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example-vivado-readsector/RTL/top.sv b/example-vivado-readsector/RTL/top.sv deleted file mode 100644 index dc365e8..0000000 --- a/example-vivado-readsector/RTL/top.sv +++ /dev/null @@ -1,96 +0,0 @@ - -//-------------------------------------------------------------------------------------------------------- -// Module : top -// Type : synthesizable, FPGA's top, IP's example design -// Standard: SystemVerilog 2005 (IEEE1800-2005) -// Function: an example of sd_reader, read a sector (512B) from SDcard and send its content to UART -// this example runs on Digilent Nexys4-DDR board (Xilinx Artix-7), -// see http://www.digilent.com.cn/products/product-nexys-4-ddr-artix-7-fpga-trainer-board.html -//-------------------------------------------------------------------------------------------------------- - -module top ( - // clock = 100MHz - input wire clk100mhz, - // rstn active-low, You can re-read SDcard by pushing the reset button. - input wire resetn, - // when sdcard_pwr_n = 0, SDcard power on - output wire sdcard_pwr_n, - // signals connect to SD bus - output wire sdclk, - inout sdcmd, - input wire sddat0, - output wire sddat1, sddat2, sddat3, - // 16 bit led to show the status of SDcard - output wire [15:0] led, - // UART tx signal, connected to host-PC's UART-RXD, baud=115200 - output wire uart_tx -); - -assign led[15:6] = 10'h0; - -assign sdcard_pwr_n = 1'b0; - -assign {sddat1, sddat2, sddat3} = 3'b111; // Must set sddat1~3 to 1 to avoid SD card from entering SPI mode - - -wire rdone; -reg rstart = 1'b1; - -wire outen; -wire [7:0] outbyte; - -always @ (posedge clk100mhz or negedge resetn) - if(~resetn) begin - rstart <= 1'b1; - end else begin - if(rdone) rstart <= 1'b0; // read a sector only once, so set rstart=0 when rdone=1. - end - - -//---------------------------------------------------------------------------------------------------- -// sd_reader -//---------------------------------------------------------------------------------------------------- -sd_reader #( - .CLK_DIV ( 2 ), - .SIMULATE ( 0 ) -) sd_reader_i ( - .rstn ( resetn ), - .clk ( clk100mhz ), - .sdclk ( sdclk ), - .sdcmd ( sdcmd ), - .sddat0 ( sddat0 ), - .card_stat ( led[ 3: 0] ), // show the sdcard initialize status - .card_type ( led[ 5: 4] ), // 0=UNKNOWN , 1=SDv1 , 2=SDv2 , 3=SDHCv2 - .rstart ( rstart ), - .rsector ( 0 ), // read No. 0 sector (the first sector) in SDcard - .rbusy ( ), - .rdone ( rdone ), - .outen ( outen ), - .outaddr ( ), - .outbyte ( outbyte ) -); - - -//---------------------------------------------------------------------------------------------------- -// send file content to UART -//---------------------------------------------------------------------------------------------------- -uart_tx #( - .CLK_DIV ( 868 ), // 100MHz/868 = 115200 - .PARITY ( "NONE" ), // no parity bit - .ASIZE ( 14 ), // - .DWIDTH ( 1 ), // tx_data is 8 bit (1 Byte) - .ENDIAN ( "LITTLE" ), // - .MODE ( "RAW" ), // - .END_OF_DATA ( "" ), // - .END_OF_PACK ( "" ) // -) uart_tx_i ( - .rstn ( resetn ), - .clk ( clk100mhz ), - .tx_data ( outbyte ), - .tx_last ( 1'b0 ), - .tx_en ( outen ), - .tx_rdy ( ), - .o_uart_tx ( uart_tx ) -); - -endmodule diff --git a/example-vivado-readsector/RTL/uart_tx.sv b/example-vivado-readsector/RTL/uart_tx.sv deleted file mode 100644 index 62e62c6..0000000 --- a/example-vivado-readsector/RTL/uart_tx.sv +++ /dev/null @@ -1,188 +0,0 @@ - -//-------------------------------------------------------------------------------------------------------- -// Module : uart_tx -// Type : synthesizable, IP's top -// Standard: SystemVerilog 2005 (IEEE1800-2005) -// Function: buffer input data and send them to UART -// UART format: 8 data bits -//-------------------------------------------------------------------------------------------------------- - -module uart_tx #( - parameter CLK_DIV = 434, // UART baud rate = clk freq/(2*UART_TX_CLK_DIV). for example, when clk=50MHz, UART_TX_CLK_DIV=434, then baud=50MHz/(2*434)=115200 - parameter PARITY = "NONE", // "NONE", "ODD" or "EVEN" - parameter ASIZE = 10, // UART TX buffer size = 2^ASIZE bytes, Set it smaller if your FPGA doesn't have enough BRAM - parameter DWIDTH = 1, // Specify width of tx_data , that is, how many bytes can it input per clock cycle - parameter ENDIAN = "LITTLE", // "LITTLE" or "BIG". when DWIDTH>=2, this parameter determines the byte order of tx_data - parameter MODE = "RAW", // "RAW", "PRINTABLE", "HEX" or "HEXSPACE" - parameter END_OF_DATA = "", // Specify a extra send byte after each tx_data. when ="", do not send this extra byte - parameter END_OF_PACK = "" // Specify a extra send byte after each tx_data with tx_last=1. when ="", do not send this extra byte -)( - input wire rstn, - input wire clk, - // user interface - input wire [DWIDTH*8-1:0] tx_data, - input wire tx_last, - input wire tx_en, - output wire tx_rdy, - // uart tx output signal - output reg o_uart_tx -); - -initial o_uart_tx = 1'b1; - - - -function automatic logic [7:0] hex2ascii (input [3:0] hex); - return {4'h3, hex} + ((hex<4'hA) ? 8'h0 : 8'h7) ; -endfunction - - -function automatic logic is_printable_ascii(input [7:0] ascii); - return (ascii>=8'h20 && ascii<8'h7F) || ascii==8'h0A || ascii==8'h0D; -endfunction - - -function automatic logic [11:0] build_send_byte(input [7:0] send_byte); - if ( PARITY == "ODD" ) - return {1'b1, (~(^send_byte)), send_byte, 2'b01}; - else if( PARITY == "EVEN" ) - return {1'b1, (^send_byte) , send_byte, 2'b01}; - else - return {1'b1, 1'b1 , send_byte, 2'b01}; -endfunction - - -function automatic logic [6+35:0] build_send_data(input [7:0] send_data); - logic [ 5:0] dcnt = '0; - logic [35:0] data = '1; - if( MODE != "PRINTABLE" || is_printable_ascii(send_data) ) begin - if( MODE == "HEXSPACE" ) begin - dcnt += 6'd12; - data[11:0] = build_send_byte(8'h20); - end - dcnt += 6'd12; - data <<= 12; - if( MODE == "HEX" || MODE == "HEXSPACE" ) begin - data[11:0] = build_send_byte(hex2ascii(send_data[3:0])); - dcnt += 6'd12; - data <<= 12; - data[11:0] = build_send_byte(hex2ascii(send_data[7:4])); - end else begin - data[11:0] = build_send_byte(send_data); - end - end - return {dcnt, data}; -endfunction - - -function automatic logic [6+35:0] build_send_eod(input send_last); - logic [ 5:0] dcnt = '0; - logic [35:0] data = '1; - if( END_OF_PACK != "" && send_last ) begin - dcnt += 6'd12; - data[11:0] = build_send_byte((8)'(END_OF_PACK)); - end - if( END_OF_DATA != "" ) begin - dcnt += 6'd12; - data <<= 12; - data[11:0] = build_send_byte((8)'(END_OF_DATA)); - end - return {dcnt, data}; -endfunction - - - - -reg [DWIDTH*8-1:0] tx_data_endian; - -always_comb - if(ENDIAN == "BIG") begin - for(int i=0; i '0 ) begin - if( cyc+1 == CLK_DIV ) begin - txdcnt <= txdcnt - 6'd1; - {txdata, o_uart_tx} <= {1'b1, txdata}; - end - end else if( bcnt > '0 ) begin - bcnt <= bcnt - 16'd1; - send_data <= send_data >> 8; - {txdcnt, txdata} <= build_send_data(send_data[7:0]); - end else if( eod ) begin - eod <= '0; - {txdcnt, txdata} <= build_send_eod(send_last); - end else if( fifo_empty_n ) begin - fifo_rptr <= fifo_rptr + (ASIZE+1)'(1); - fifo_rd_en <= 1'b1; - end - end - - -endmodule diff --git a/figures/pin.png b/figures/pin.png deleted file mode 100644 index f840aa3d3ecbe375ca64c97e2f310daca40a6f04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23691 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