lemonHe

主要关注FPGA信号处理和数字图像处理技术,欢迎交流 邮箱:heliminlemon@163.com

FPGA中使用友晶科技4端口SDRAM控制器

1
阅读(4168)

在实际工程中用到的外部控制器主要是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控制器输出的信号即可。