一.实验任务
实现PC向FPGA发送数据保存进SDRAM,再通过按键控制读出SDRAM中的数据发送给PC端,实现数据回环。
二.SDRAM介绍
同步动态随机存取内存(synchronous dynamic random-access memory,简称SDRAM)是有一个同步接口的动态随机存取内存(DRAM)。
本次实验使用的SDRAM芯片(HY57V561620FTP)内部被分成了4个bank,每个bank有64Mbit大小,SDRAM与输入时钟同步,时钟信号上升沿采样,行列地址线复用,数据线输入输出复用。读写访问是突发的,突发(Burst)是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输所涉及到存储单元(列)的数量就是突发长度(Burst Lengths,简称BL)。本次SDRAM芯片对应的突发长度有1、2、4、8、全页,自动预充电在突发访问结束自动进行预充电。访问从激活命令开始,紧接着是读写命令。激活命令选择激活的bank和行,而读写命令选择激活的bank和列。
SDRAM的数据存储是利用电容实现的,因为电容存在放电的特性,所以需要定时刷新芯片才可以保证数据不丢失。查看芯片手册,可以看见刷新周期为64ms,也就是说在64ms内要保证每一块内存都要刷新一次,内存共8192行,平均下来,只要每7.8us刷新一行,就能保证64ms内刷新所有内存。
SDRAM原理框图:
由上图可以看见行列地址线被复用了,SDRAM接收到地址,会将数据传递给相应的地址预译码器和地址计数器,行地址预译码器会激活bank的行,列地址预译码器会激活bank的列,同时模式寄存器设置的突发长度会联合列地址计数器共同决定当前操作的列地址。外部状态机给出时钟信号,时钟使能信号,片选信号,行地址,列地址,数据允许信号,数据屏蔽信号,输入数据;SDRAM输出数据。
每块bank大小为4M*16bit,如果想要扩展内存,有两种方法:
①扩展深度,将两块bank的地址线并联,片选信号并联,将数据线串联能够实现8M16bit。
②扩展宽度,将两块bank的地址线并联,数据线并联,通过一个2输入译码器选择片选信号就能实现4M32bit。
如果既想扩展深度,又想扩展宽度,可以将上述两个方法结合起来。
注意:时钟和其他输入信号被异步重新启用,需要等待200us,同时FPGA和SDRAM的时钟存在时钟偏移,这是为了SDRAM能够采到稳定的数据,在芯片手册中有说到,具体偏移角度须自己调试。
SDRAM内部存在一个有限状态机,其状态跳转如下:
本次实验实现的是蓝色箭头表示的过程。
在读写命令之前,必须先激活相应的bank和行地址,激活命令和读写命令之间需要一个tRCD的间隔,READ突发读取,BA0和BA10用于选择bank,A10的值决定是否使用自动预充电,自动预充电用于突发结束时自动预充电,不选择自动预充电,则行保持打开供后续访问READ命令发出后,经过列激活延迟才可以得到数据。写命令用于启动对活动行的突发写访问。BA0和BA1的值用于选择数据开始传输的bank地址和列地址。A10的值决定了是否使用自动预充电。如果选择了自动预充电,则正在访问的行将在写突发结束时进行预充电;如果未选择自动预充电,则该行将保持打开状态以供后续访问。
SDRAM控制操作比较复杂,所以我们使用了SDRAM的接口IP,这大大减少了我们的工作量,在调用IP的基础上,我们只需要设计一个控制模块就能操作SDRAM进行读写操作了。
三.设计思路
程序框图:
四.代码实现
调用IP核(这里IP核的调用不同于之前的PLL,RAM等):
设置配置文件参数:
添加相关延时:
设置时钟为100MHZ:
完成相关连线和端口命名:
顶层模块设计:
/**********************************************************
// Copyright 2022.05-2025.05
// Contact with xxxxxxxxx@qq.com
================ xxx.v ======================
>> Author : lj
>> Date : 20XX/XX/XX
>> Description :
>> note :
>> :
>> V180121 :
************************************************************/
module sdram_top(
input clk ,//时钟信号 50MHZ
input rst_n ,//复位信号
input rx ,//串口接收数据
input key_in ,//按键输入 作为读请求信号
output [12:0] mem_addr ,
output [1 :0] mem_bank ,
output mem_cas_n ,
output mem_cke ,
output mem_cs_n ,
inout [15:0] mem_dq ,
output [1 :0] mem_dqm ,
output mem_ras_n ,
output mem_we_n ,
output sdram_clk ,
output tx //串口发送数据
);
//参数定义
//信号定义
wire key_done ;
wire clk_100m ;
wire clk_100m_s ;
wire [7:0] din ;
wire din_vld ;
wire ready ;
wire [7:0] dout ;
wire dout_vld ;
wire locked ;
//模块例化
//按键消抖模块
key u_key(
/*input */.clk (clk ),//时钟信号
/*input */.rst_n (rst_n ),//复位信号
/*input [1:0] */.key_in (key_in ),//按键输入信号
/*output reg [1:0] */.key_done