1、知识点
FIFO的引入:
- 调用SDRAM读写模块的其他模块必须与此模块时钟同步,否则将引入跨时钟域传输的问题
- 虽然仲裁模块可以解决读写请求、刷新请求的冲突,但是在存在冲突时,无法将冲突数据缓存会造成数据丢失(例如写操作、刷新操作冲突。则必定会执行刷新操作后再执行写操作,而在等待刷新操作完成的这段时间可能会将原来要写入的数据覆盖)
FIFO模块能解决多bit数据跨时钟域同步的问题;其次,在存在SDRAM操作冲突时可以将数据寄存在FIFO以防止数据被覆盖或丢失;通过引入FIFO使得对SDARM的操作实际上变成了对FIFO的操作,而FIFO的控制时序又相对简单,所以能大大简化操作。
2、FIFO模块设计
应设计两个FIFO:写FIFO模块、读FIFO模块。
写FIFO模块:用户侧将要写入的数据存入写FIFO,待SDRAM响应了写请求后,从写FIFO中读取数据作为数据源写入SDRAM
读FIFO模块:用户侧发起读请求,待SDRAM响应了读请求后,从SDRAM中读取的数据被写入读FIFO,用户侧从读FIFO读取数据
FIFO模块的Verilog代码设计主要有以下几点:
分别例化2个双端口异步fifo模块,分别作为读模块与写模块
读、写响应信号均为异步信号,需要打拍采取其下降沿
每当写FIFO模块中数据量大于突发长度时,就进行SDRAM写入操作;每当读FIFO模块中数据量小于突发长度时,就进行SDRAM读取操作
写请求优先级高于读请求
3、代码
时序图:
FIFO写:
FIFO读 :
//----------------------------------------------------------------------------------------------------
//--FIFO控制模块
//----------------------------------------------------------------------------------------------------
module FIFO_Ctrl
(
input sys_clk ,
input sys_rst_n ,
// write FIFO
input wr_fifo_wr_clk ,
input wr_fifo_wr_req ,
input [15:0] wr_fifo_wr_data ,//准备写入SDRAM的数据
input [23:0] sdram_wr_b_addr ,//写数据开始地址
input [23:0] sdram_wr_e_addr ,//写数据结束地址
input [9:0] wr_burst_len ,//写突发长度
input wr_rst ,//写复位信号
// read fifo
input rd_fifo_rd_clk ,
input rd_fifo_rd_req ,
input [23:0] sdram_rd_b_addr ,//读数据开始地址
input [23:0] sdram_rd_e_addr ,//读数据结束地址
input [9:0] rd_burst_len ,//读突发长度
input rd_rst ,//读复位信号
output [15:0] rd_fifo_rd_data ,
output [9:0] rd_fifo_num ,
input init_end ,
input read_valid ,//读有效信号
//SDRA