SDRAM-学习8-fifo控制模块

431 阅读3分钟

例化了两个fifo,写fifo,读fifo。对数据进行缓存完成跨时钟域处理。

系统主板工作频率50MHZ,SDRAM工作频率100MHZ,所以需要用fifo实现跨时钟域处理。

fifo控制模块

image.png

波形绘制

sdram 时钟100mhz,sys_clk为100MHZ 串口外部传入数据,写fifo进行缓存。 串口时钟频率50mhz。

写部分

写fifo信号

写fifo信号wr_fifo_wr_clk 写请求信号wr_fifo_wr_data.

image.png

写sdram地址

数据需要写入sdram中,sdram_wr_b_addr,sdram_wr_e_addr.24位宽,bank地址 行地址 列地址组合在一起。开始到结束。 看上去是11个地址我们只用了10个地址。

image.png

突发长度wr_brust_len

写复位信号 wr_rst:

综上完成写部分波形图绘制

image.png

再加上复位信号,复位结束信号

image.png

数据读出,写入sdram

现在进行数据读出,写入sdram中突发存储,所以fifo必须满足一次突发长度,利用写fifo的计数信号,由写fifo传出,对写入个数进行计数,满足一次突发长度,此时sdram而且完成了一次初始化,可以进行数据写入。 请求信号会被传入仲裁模块,仲裁模块判断,可以进行写,发出写使能信号。 完成写入后,传出sdram_wr_ack响应信号。

数据作为sdram_data_in,此时信号时钟为100mhz,因为sdram工作时钟为100mhz,fifo读取数据会滞后一个时钟周期,所以此处数据也需要滞后一个时钟周期。

image.png

image.png

sdram_wr_addr image.png

wr_ack_dly 响应信号大一拍。利用下降沿完成写地址bank的更新。

image.png

读部分 读fifo

由sdram读取数据

外部传入读有效信号,read_vaild,sdram_rd_req读请求信号。

image.png

读请求响应信号延迟一拍,根据下降沿,控制地址更新。sdram读出的数据会写入fifo控制模块,读fifo中。

image.png

读fifo进行计数10字节的数据,从读fifo中读出数据传入串口,查看数据。

读fifo读时钟等信号,

image.png

读fifo读请求信号,读fifo的读数据传出,读fifo的读时钟,请求信号完成后拉低。 读FIFO的计数信号也要完成更新。读出来数据通过串口传到上位机。

16位宽 1024 字节,读时钟和写时钟分开。 image.png

image.png

默认:

image.png

空信号不要,选择异步清零信号 image.png

生成例化模板:

image.png

	.aclr ( aclr_sig ),
	.data ( data_sig ),
	.rdclk ( rdclk_sig ),
	.rdreq ( rdreq_sig ),
	.wrclk ( wrclk_sig ),
	.wrreq ( wrreq_sig ),
	.q ( q_sig ),
	.rdusedw ( rdusedw_sig ),
	.wrusedw ( wrusedw_sig )
	);

程序

(
input wire sys_clk,
input wire sys_rst_n,
//写fifo信号
input wire 	wr_fifo_wr_clk,
input wire 	wr_fifo_wr_req,
input wire  [15:0]wr_fifo_wr_data,
input wire  [23:0]sdram_wr_b_addr,
input wire  [23:0]sdram_wr_e_addr,
input wire  [9:0]wr_brust_len,
input wire  wr_rst,


//读fifo信号
input wire 	rd_fifo_rd_clk,
input wire 	rd_fifo_rd_req,
input wire  [23:0]sdram_rd_e_addr,
input wire  [23:0]sdram_rd_b_addr,
input wire  [9:0]rd_brust_len,
input wire  rd_rst,

input wire init_end,
input wire read_vaild,




output wire [15:0]rd_fifo_rd_data,
output wire [9:0]rd_fifo_num,
//sdram 写信号
input wire sdram_wr_ack,
output reg sdram_wr_req,
output reg [23:0]sdram_wr_addr,
output wire [15:0]sdram_data_in,
//sdram 读信号
input wire sdram_rd_ack,
output reg sdram_rd_req,
input wire [15:0]sdram_data_out,
output reg [23:0]sdram_rd_addr

);


wire [9:0]wr_fifo;
wire wr_ack_fall;
wire rd_ack_fall;
reg wr_ack_dly;

reg rd_ack_dly;


always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		rd_ack_dly <= 1'b0;
	else
		rd_ack_dly <= sdram_rd_ack;

//提取下降沿
assign wr_ack_fall = (wr_ack_dly&~sdram_wr_ack);
assign rd_ack_fall = (rd_ack_dly&~sdram_rd_ack);


//写地址进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		sdram_wr_addr <= 24'd0;
	else if(wr_rst==1'b1)
		sdram_wr_addr <= sdram_wr_b_addr;
	else if(wr_ack_fall == 1'b1)
		begin
			if(sdram_wr_addr<(sdram_wr_e_addr-wr_brust_len))
				sdram_wr_addr <= sdram_wr_addr + wr_brust_len;
			else
				sdram_wr_addr <= sdram_wr_b_addr;
		
		end 
//读地址赋值
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		sdram_rd_addr <= 24'd0;
	else if(rd_rst==1'b1)
		sdram_rd_addr <= sdram_rd_b_addr;
	else if(rd_ack_fall == 1'b1)
		begin
			if(sdram_rd_addr<(sdram_rd_e_addr-rd_brust_len))
				sdram_rd_addr <= sdram_rd_addr + rd_brust_len;
			else
				sdram_rd_addr <= sdram_rd_b_addr;
		end 

always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		begin
			sdram_wr_req <= 1'b0;
			sdram_rd_req <= 1'b0;
	
		end
	else	if(init_end == 1'b1)
		begin 
			if(wr_fifo_num >= wr_brust_len)
				begin	
					sdram_wr_req <= 1'b1;
					sdram_rd_req <= 1'b0;
				end
			else	
			if((rd_fifo_num<rd_brust_len)&&(read_vaild ==1'b1 ))
				begin	
					sdram_wr_req <= 1'b0;
					sdram_rd_req <= 1'b1;
				end
			else
				begin	
					sdram_wr_req <= 1'b0;
					sdram_rd_req <= 1'b0;
				end
				
				
		end
	else
		begin	
					sdram_wr_req <= 1'b0;
					sdram_rd_req <= 1'b0;
		end













//声明fifo

fifo_data	wr_fifo_data_inst1 (
	//用户接口
	.wrclk ( wr_fifo_wr_clk ),
	.wrreq ( wr_fifo_wr_req),
	.data (wr_fifo_wr_data ),
	//sdram接口
	.rdclk ( sys_clk ),
	.rdreq ( sdram_wr_ack ),
	.q ( sdram_data_in ),
	
	.aclr ( wr_rst||~sys_rst_n ),
	.rdusedw ( wr_fifo_num ),
	.wrusedw (  )
	);


fifo_data	rd_fifo_data_inst1 (
	//sdram接口
	.wrclk ( sys_clk ),
	.wrreq (sdram_rd_ack ),
	.data (sdram_data_out ),
	//用户接口
	.rdclk ( rd_fifo_rd_clk ),
	.rdreq ( rd_fifo_rd_req ),
	.q (rd_fifo_rd_data  ),
	
	.aclr ( wr_rst||~sys_rst_n  ),
	.rdusedw (  ),
	.wrusedw (rd_fifo_num   )
	);





endmodule