为了方便用户读写DDR3,我们设计了一个AXI4接口转换模块fifo_axi4_adapter(部分例程中也叫ddr3_ctrl_2port)。在该模块中,经常有用户不明白用于读取DDR3数据的axi4_to_fifo子模块产生读DDR3请求信号的原理,这里详细为大家分析一下。
在分析之前,我们需要先知道一个小知识点。xilinx的FIFO软核有两种读模式,即标准读模式和首字直通模式(FWFT),两者最明显的区别就是标准读模式下,数据会在读使能信号有效后的下一拍被送到数据线上,因此数据需要晚一拍再读取。而FWFT则是会提前将数据送到数据线上,这样读使能信号有效时,数据就能被直接读取。
最初的fifo_axi4_adapter模块中,读写FIFO都是使用的FWFT模式,对应的读DDR3请求信号的产生条件如下:
[C] 纯文本查看 复制代码 assign rd_req_cnt_thresh = 2**FIFO_ADDR_WIDTH - (AXI_BURST_LEN[7:0]+1'b1);
assign rd_ddr3_req = (fifo_rst_busy == 1'b0) && (fifo_wr_cnt < rd_req_cnt_thresh-2'd2) ? 1'b1:1'b0;
这里的FIFO_ADDR_WIDTH为FIFO写深度对应位宽,rd_req_cnt_thresh用来计算FIFO中至多写入多少数据后,仍留有一次突发的空间,也就是能够产生读DDR3条件的阈值。又由于FIFO使用的是FWFT模式,数据会提前一拍送到数据线上,所以最终判断fifo_wr_cnt信号是,在rd_req_cnt_thresh-2'd1的基础上还需要再减一。
使用FWFT模式虽然数据能够在读使能信号有效时立马被读取,但是这种模式下,根据同步级以及读写接口位宽比的不同,读写侧信号的延迟计算方式不同。写计数在FIFO接近almost_empty和empty时会出现“过渡”现象(根据写和读接口位宽比,写计数会逐渐多出一定计数值),过渡现象在手册中原文如下:
因此,如果用户在使用该模式FIFO的fifo_axi4_adapter模块进行设计没有实现预期功能,需要结合FIFO内部信号进行分析时,较为复杂的时序关系将会使得分析难度极大程度的提高。
所以,考虑到这一点,在后续的fifo_axi4_adapter模块中,FIFO都使用标准读模式,这种模式下FIFO内部信号时序更为简单。相对应的,此时读DDR3请求信号的产生条件如下:
[C] 纯文本查看 复制代码 assign rd_req_cnt_thresh = 2**FIFO_ADDR_WIDTH - (AXI_BURST_LEN[7:0]+1'b1);
assign rd_ddr3_req = (fifo_rst_busy == 1'b0) && (fifo_wr_cnt < rd_req_cnt_thresh-2'd1) ? 1'b1:1'b0;
可以看到,这里判断fifo_wr_cnt时,rd_req_cnt_thresh不再减2而是减1。由于一些历史遗留问题,部分例程中仍是使用的减2,这种情况下的写法也不算错,只是说不够标准,对FIFO的利用率没那么高。
关于标准读模式与FWFT模式下FIFO的详细差异,可以参考B站小梅哥爱漂流的相关视频:
https://www.bilibili.com/video/BV1zw41117HS?p=59
|