SDRAM控制器在连续读写数据时的优化

本文探讨了在FPGA控制SDRAM时使用FIFO的重要性,详细分析了FIFO深度的确定方法,根据写入速率和读取速率进行估算。同时,阐述了FIFO与SDRAM的读写请求处理,当FIFO存储量大于等于突发长度时启动写入,低于一半存储量时启动读取。时钟处理方面,FIFO的写时钟由输入模块决定,读时钟则根据需求和写时钟设定。最后,介绍了SDRAM的读写地址处理,按突发长度递增。整个过程旨在确保数据流的连续性和避免数据遗漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. FIFO深度的确定?

2. FIFO与SDRAM的读写请求的处理?FIFO什么时候读,什么时候写?

3. FIFO与SDRAM的时钟处理?即FIFO的读写时钟如何设置?

4. SDRAM的读写数据和地址如何处理?


用FPGA对SDRAM的控制,存在一个主要缺点:对于数据流只能间歇性的读写,不能连续对数据流进行缓存。在某些特殊的情况,读写请求可能会被忽略,造成数据遗漏。因此在以数据流的形式访问SDRAM时,一般配合FIFO使用。

问题点及分析:(下面对问题的解析限于个人理解,可能不全或者有误的地方,路过的大神还请帮忙指出!感谢~~~)

1. FIFO深度的确定?

需要根据FIFO连续写入的时钟、数据量和速以及读取的时钟进行估计FIFO深度。可以参考:FIFO深度如何确定_赤橙黄绿蓝_新浪博客 (sina.com.cn)

在一般的应用场景中,读写FIFO可能时随机的,即并不是确定的连续一段时间内写入确定的数据量以及有确定的读的速率。因此,在这种场景下,要确定FIFO的深度,需要估计出最大的写入速率以及最小的读出速率,这样才能计算出在写完的时刻,会有多少数据剩余没有读出。

2. FIFO与SDRAM的读写请求的处理?FIFO什么时候读,什么时候写?

FIFO写(FIFO往SDRAM中写),在FIFO的存放数量大于等于burst长度,就拉高写使能;

FIFO读(FIFO从SDRAM中读),当FIFO的存放数量小于所能存放数量的一半时,拉高读使能;

在往FIFO中写以及从FIFO中读取数据时,需要判断FIFO的满、空标志位。

//只要FIFO不在清空阶段,且目前FIFO中数据量大于突发长度,FIFO就可以继续往SDRAM中写入数据
assign sd_wr_req=(!wr_load)&&(fifo_rduse>=SC_BL)? 1'b1:1'b0;

//只要FIFO不在清空阶段,且目前FIFO中数据量小于FIFO一般的存储量,FIFO就可以继续从SDRAM中读取数据
assign sd_rd_req=(!rd_load)&&(fifo_wruse[7]==1'b0)? 1'b1:1'b0;

3. FIFO与SDRAM的时钟处理?即FIFO的读写时钟如何设置?

FIFO主要应用于跨时钟处理,以及数据缓存。FIFO的写入时钟一般取决于连接的模块的时钟,而读时钟可以根据SDRAM的需求时钟以及写时钟确定。

当FIFO读写时钟差别很大,可以参考:今天华为面试题:异步FIFO读时钟是写时钟的100倍,或者写是读的100倍会出现什么问题? - 第2页 - FPGA/ASIC/IC前端设计 - EETOP 创芯网论坛 (原名:电子顶级开发网) ,觉得挺有意思的。建议自己动手试试。

4. SDRAM的读写数据和地址如何处理?

对于数据流的存取,主控制器只需要提供存取在SDRAM的起始地址和最大地址即可。FPGA代码设计根据SDRAM的burst length来自动生成每次读写SDRAM的地址。然后再在其基础上,生成SDRAM模块需要的行、列、BANK地址。代码中,只要往SDRAM中读写一个突发长度的数据完成,地址就自动+SC_BL。

以下代码实现对SDRAM顺序读写数据。

//写SDRAM的地址,写完一次增加一个突发长度
always @(posedge clk or negedge rst_n)
begin
	if(~rst_n)   wr_sdram_addr<=wr_addr;      //写起始地址
	else if(wr_load)  wr_sdram_addr<=wr_addr; //对wr_fifo清零后,重新开始写
	else if(sd_wrdata_done)    //SDRAM一次突发写完毕
		begin
			if(wr_sdram_addr==wr_max_addr-SC_BL) wr_sdram_addr<=wr_addr;  //达到最大地址
			else wr_sdram_addr<=wr_sdram_addr+SC_BL;
		end
	else wr_sdram_addr<=wr_sdram_addr;			
end

//读SDRAM的地址,读完一次增加一个突发长度
always @(posedge clk or negedge rst_n)
begin
	if(~rst_n)   rd_sdram_addr<=rd_addr;      //读起始地址
	else if(rd_load)  rd_sdram_addr<=rd_addr; //对rd_fifo清零后,重新开始读
	else if(sd_rddata_done)    //SDRAM一次突发读完毕
		begin
			if(rd_sdram_addr==rd_max_addr-SC_BL) rd_sdram_addr<=rd_addr;
			else rd_sdram_addr<=rd_sdram_addr+SC_BL;
		end
	else rd_sdram_addr<=rd_sdram_addr;			
end

//SDRAM的行地址
always @(posedge clk or negedge rst_n)
begin
	if(~rst_n) sd_raddr<=13'd0;
	else if (sd_wr_req) sd_raddr<=wr_sdram_addr[21:9];
	else if (sd_rd_req) sd_raddr<=rd_sdram_addr[21:9];
	else sd_raddr<=sd_raddr;
end

//SDRAM的列地址
always @(posedge clk or negedge rst_n)
begin
	if(~rst_n) sd_caddr<=13'd0;
	else if (sd_wr_req) sd_caddr<=wr_sdram_addr[8:0];
	else if (sd_rd_req) sd_caddr<=rd_sdram_addr[8:0];
	else sd_caddr<=sd_caddr;
end

//SDRAM的bank地址
always @(posedge clk or negedge rst_n)
begin
	if(~rst_n) sd_baddr<=13'd0;
	else if (sd_wr_req) sd_baddr<=wr_sdram_addr[23:22];
	else if (sd_wr_req) sd_baddr<=rd_sdram_addr[23:22];
	else sd_baddr<=sd_baddr;
end

代码的仿真及调试情况,下篇文章继续总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值