| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-07-01 | gingko | 初次建立 | \\ ===== 实验二十二:FIFO实验——基于FIFO的ARM与FPGA数据存取 ===== ==== 一、 实验目的与意义 ==== - 掌握双口RAM IP核的调用及例化方法。 - 掌握RAM读写时序。 - 掌握QuartusII的使用方法。 ==== 二、 实验设备及平台 ==== - iCore4TX 双核心板[[https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22598974120.3.29da532fLkazHH&id=614919247574|点击购买]]。 - USB-CABLE(或相同功能)仿真器。 - JLINK(或相同功能)仿真器。 - Micro USB线缆。 - Keil MDK 开发平台。 - ISE开发平台。 - 电脑一台。 ==== 三、 实验原理 ==== * FIFO(First Input First Output)是一种先进先出存储器。与之前的RAM相比较而言,FIFO存储器没有地址线,操作起来更加的简单,但其缺点就在于,只能顺序读写数据,不能随意指定读写数据的地址单元。根据读写时钟的相同与否,FIFO可分为异步FIFO和同步FIFO两种,本实验讲的是异步FIFO。 * FIFO的读写时钟在每个时钟上升沿到来时对数据进行操作;读写请求信号为高电平有效,低电平失能。 * FIFO读写操作的工作原理:在FIFO内部有读写指针,其中,读指针指向下一个将要读取数据的地址,复位时指针指向0地址;写指针指向下一个将要写入数据的地址,复位指针指向0地址。 * FIFO的空/满检测是FIFO应用中的一个重要参数,不过在应用过程中,这两项参数不是必须使用的,可以通过控制读写时钟及读写请求信号来避免溢出,即通过人为的控制数据长度避免读写溢出(本实验即使如此)。 * 根据上面的介绍可知,FIFO的读写操作时序如图22.1所示。 22-1(a)读操作时序 {{ :icore4tx:icore4tx_fpga_22_1_a.png?direct |读操作时序}} 22-1(b)写操作时序 {{ :icore4tx:icore4tx_fpga_22_1_b.png?direct |写操作时序}} * 本实验基于ARM+FPGA构架,通过SPI实现ARM与FPGA之间通信,ARM通过SPI总线向FPGA发送相关指令;FPGA内部例化的FIFO作为ARM的外部存储器,根据指令进行对应的读写操作,从而实现ARM对FPGA内部FIFO的数据读写功能。实验流程较为简单,重点是掌握FIFO IP核的调用及时序的描述。 ==== 四、 FIFO IP核调用 ==== 1、新建一个工程名为fifo的工程,然后选中工程右击,下拉菜单中选择New Source…,如图22-2所示。 {{ :icore4tx:icore4tx_fpga_22_2.png?direct |图22-2}} 2、弹出窗口选择新建IP核文件,既IP(CORE Generator & Architecture Wizard)选项。右侧的File name栏给IP核文件命名为fifo,点击Next。 {{ :icore4tx:icore4tx_fpga_22_3.png?direct |图22-3}} 3、弹出IP核选择界面,点击Memories & Storage Elements 前面的“+”,再点击FIFOs前面的“+”,然后点击FIFO Generator选定,点击Next。 {{ :icore4tx:icore4tx_fpga_22_4.png?direct |图22-4}} 4、点击Finish。 {{ :icore4tx:icore4tx_fpga_22_5.png?direct |图22-5}} 5、弹出FIFO IP核相关参数设置界面,如下图所示,这里的Interface Type 选择Native,然后点击Next。 {{ :icore4tx:icore4tx_fpga_22_6.png?direct |图22-6}} 6、选择时钟和存储器类型。本实验对FIFO的读和写是独立操作的,因此时钟选择异步模式;block RAM 是FPGA内部定制的RAM资源,Distributed RAM则是由LUT构成的RAM资源。所以本实验FIFO Implementation栏下选择Independent Clocks(RD_CLK,WR_CLK) Block RAM,然后点击Next。 {{ :icore4tx:icore4tx_fpga_22_7.png?direct |图22-7}} 7、如下界面中设置Read Mode为Standard FIFO,;设置FIFO的读和写的位宽为8,写深度参数为1024,读深度根据这几个参数自动计算出来为1024;这里需要注意的是Write Depth参数设置为1024,Actual Write Depth为1023。 {{ :icore4tx:icore4tx_fpga_22_8.png?direct |图22-8}} 8、此界面默认选项即可,点击Next。 {{ :icore4tx:icore4tx_fpga_22_9.png?direct |图22-9}} 9、这里Initialization栏下取消复位引脚,然后点击Next。 {{ :icore4tx:icore4tx_fpga_22_10.png?direct |图22-10}} 10、此界面默认,点击Next。 {{ :icore4tx:icore4tx_fpga_22_11.png?direct |图22-11}} 11、点击Generate,生成FIFO IP核文件。 {{ :icore4tx:icore4tx_fpga_22_12.png?direct |图22-12}} 12、在工程目录栏选中FIFO IP核文件,然后点击Processes: u0-spi_fifo窗口CORE Generator前面的“+”。双击View HDL Instantiation Template,可以看到所有需要例化的FIFO端口信号。 {{ :icore4tx:icore4tx_fpga_22_13.png?direct |图22-13}} ==== 五、 代码讲解 ==== * IP核调用只是生成相关的模块文件,在应用中要实现存储、读写功能,还需要对IP核进行实例化操作,FIFO IP核例化代码如下: //------------------------------------------------// //spi_fifo //负责存储SPI通信的数据 //FIFO:先进先出,主要用于缓存数据。 spi_fifo u0( .data(receive_byte), .wrclk(wrclk), .wrreq(wrreq), .wrfull(), .rdclk(rdclk), .rdreq(rdreq), .rdempty(), .q(data_out) ); case(rx_state) rx_idle_state:begin//空闲状态,匹配伪命令时钟 rx_state <= rx_judge_state; end rx_judge_state:begin//接收指令字节,判断指令含义分配跳转状态机状态 case(receive_byte) 8'h01:begin//存储指令编码(获取设备状态) order <= receive_byte; end 8'h04:begin rx_state <= rx_wr_add_state; order <= receive_byte; end 8'h07:begin rx_state <= rx_rd_add_state; order <= receive_byte; end default:; endcase end rx_wr_add_state:begin//控制写请求信号 case(rx_cnt) 8'd0:begin rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin wrreq_r <= 1'd1; end default:begin end endcase end rx_rd_add_state:begin//控制读请求信号,通过计数器rd_cnt控制读请求 case(rx_cnt) //信号的使能状态 8'd0:begin rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin rdreq_r <= 1'd1; rx_cnt <= rx_cnt + 1'd1; rd_cnt <= rd_cnt + 1'd1; end 8'd2:begin if(rd_cnt == 12'd1023) begin rd_cnt <= 12'd0; rdreq_r <= 1'd1; end else begin rd_cnt <= rd_cnt + 1'd1; end end default:; endcase end endcase ==== 六、 实验步骤及实验结果 ==== {{ :icore4tx:icore4tx_fpga_22_14.png?direct |图22-14}} - 将硬件正确连接,如图22-14所示。 - 打开putty串口调试工具,打开设备管理器查看对应的端口信息,在putty中打开对应的端口,波特率设置为115200,用于打印串口信息及控制FIFO读写; - 将编写好的FPGA代码进行编译,并下载到开发板中; - 将编写好的ARM代码编译,并下载到开发板中,putty工具中会打印相应的SPI通信相关信息(若想多次测试,查看结果,在putty中输入“test”即可); - 观察实验现象及putty终端打印信息——FPGA_LED闪烁,putty终端打印如图22-15所示。 {{ :icore4tx:icore4tx_fpga_22_15.png?direct |图22-15}} ==== 七、 拓展实验 ==== - 通过Modelsim观察FIFO读写时序是否和参考时序一致。 - 阅读FIFO IP核官方手册,观察IP核参数配置不同对其读写操作的影响。