FPGA中使用友晶科技4端口SDRAM控制器
1赞在实际工程中用到的外部控制器主要是SDR SDRAM(后面简称sdram)和DDR SDRAM,而SRAM由于容量小、价格昂贵,我一般不用。在使用嵌入式软核NIOS的系统中,使用altera官方的sdram Controller, sdram作为运行内存,同时,还可以使用sdram作为数据存储,通过自定义的带avalon总线的模块也可以访问sdram。
在做VGA、HDMI、DVI等视频显示的时候,需用到外部存储器作数据缓存,在一些图像处理算法中,有时也需用外部存储器存储校正参数。由于sdram操作复杂,使用时,要不用altera官方提供sdram Controller,要不用第三方公司写的控制器,当然,也有些牛人自己写出控制器。
玩过友晶科技DE2-70的同学应该都知道,友晶科技写了一个4端口sdram控制器,在DE2-70的D5M摄像机例程中有,使用sdram作vga显示数据的缓存。这个4端口控制器配有2组读写fifo,位宽为16bit,深度为512words。对于写fifo,控制器外部以较低时钟往fifo中写数据,当fifo中数据大于fifo容量的一半(256)时,在控制器内部会以sdram的时钟来快速突发往sdram中写入256个数据,对于读fifo,同理,当读fifo中数据个数小于256时,在控制器内部,会以sdram的时钟来快速突发往读fifo中写入256个数据,读fifo输出的数据直接用作vga显示,根据vga显示标准,不同分辨率时钟频率一般不同,这个时钟频率就是读fifo的时钟频率。
控制器下载地址:
https://pan.baidu.com/s/1dEG0FL3
使用这个控制器,需在Sdram_Control_4Port.v(449行处)和中设置起始地址、最大地址,突发长度。工程中图像分辨率为640×480,设置如下:
rWR1_ADDR <= 0; rWR2_ADDR <= 22'h100000; rRD1_ADDR <= 0; rRD2_ADDR <= 22'h100000; rWR1_MAX_ADDR <= 640*480; rWR2_MAX_ADDR <= 22'h100000+640*480; rRD1_MAX_ADDR <= 640*480; rRD2_MAX_ADDR <= 22'h100000+640*480; rWR1_LENGTH <= 256; rWR2_LENGTH <= 256; rRD1_LENGTH <= 256; rRD2_LENGTH <= 256;
另外,需在顶层文件中添加起始地址、最大地址,突发长度、读写fifo时钟,sdram时钟即可,控制器sdram side引脚中包含了sdram芯片除时钟之外的所有信号,所以时钟需要另外添加,如下所示。
assign DRAM3_CLK = sdram4_clk;
下面放上一段我在一个项目工程中用到的顶层代码,图像分辨率为640×480,一帧图像data_valid信号高电平81920个时钟周期, data_valid为高时,数据全部写入。读数据时,Read_DATA1会滞后Read信号一个时钟周期。
Sdram_Control_4Port Sdram_Control_4Port_inst( // HOST Side // .REF_CLK(clk_50M), .RESET_N(1), .CLK(sdram3_clk), // FIFO Write Side 1 .WR1_DATA(data_valid1), .WR1(data1), .WR1_ADDR(0), .WR1_MAX_ADDR(640*480), .WR1_LENGTH(9'h100), .WR1_LOAD(sdram_wr_clr), .WR1_CLK(top_clk25M), // FIFO Write Side 2 .WR2_DATA(data_valid2), .WR2(data2), .WR2_ADDR(22'h100000), .WR2_MAX_ADDR(22'h100000+640*480), .WR2_LENGTH(9'h100), .WR2_LOAD(!DLY_RST_0), .WR2_CLK(top_clk25M), // FIFO Read Side 1 .RD1_DATA(Read_DATA1), .RD1(Read1), .RD1_ADDR(0), .RD1_MAX_ADDR(640*480), .RD1_LENGTH(9'h100), .RD1_LOAD(!DLY_RST_0), .RD1_CLK(top_clk25M), // FIFO Read Side 2 .RD2_DATA(Read_DATA2), .RD2(Read2), .RD2_ADDR(22'h100000), .RD2_MAX_ADDR(22'h100000+640*480), .RD2_LENGTH(9'h100), .RD2_LOAD(!DLY_RST_0), .RD2_CLK(top_clk25M), // SDRAM Side .SA(DRAM3_ADDR[12:0]), .BA({DRAM3_BA_1,DRAM3_BA_0}), .CS_N(DRAM3_CS_N), .CKE(DRAM3_CKE), .RAS_N(DRAM3_RAS_N), .CAS_N(DRAM3_CAS_N), .WE_N(DRAM3_WE_N), .DQ(DRAM3_DQ), .DQM({DRAM3_UDQM,DRAM3_LDQM}) );
这个控制器还有WR_LOAD和 RD_LOAD信号,这4个信号有两个作用,当为高时,一方面清空fifo,另一方面,sdram读写地址都复位到起始地址。在作视频缓存时,从sdram中按所需的格式生成读信号,然后接收sdram控制器输出的信号即可。