天天看点

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

本文设计思路与讲解于参考邓堪文老师的视频,感谢…(不太适合一点基础都没有的小白)

SDRAM简介

SDRAM(synchronous Dynamic Random ),同步动态随机存储器,同步指内存工作需要同步时钟,内存的命令的发送和数据的接收都以它为标准。动态是指需要不断地刷新来保证数据不丢失(电容存储),随机指的是储存位置可以随机指定,自由储存。

这里引荐博文DDR3详解

这里是我买黑金板子里带的资料

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

SDRAM储存计算方式

SDRAM 的空间 = 4(资源库-Bank)× 2^12 行×2^8 列(寻址深度)× 16 bits

= 4 × 1048576 × 16 bits

= 4 × 1048576 / 1024 × 16 bits

= 4 × 1024 K / 1024 × 16bits

= 4 × 1M × 16 bits

= 64Mbits 或者 67,108,864 bits

常用单词总结

  • row 行
  • column 列
  • nop(no operation) 无操作
  • precharge 预充电
  • outorefresh 自动刷新
    基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化
    这里还有数据手册里边有一些有关单词的解释描述(带"—"表示低电平有效)

数据手册分析(及时序分析)

时钟产生

这里首先看一下时钟的产生

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

因为需要读取数据在时钟的上升沿。这里和iic里边也有点类似,为了使SDRAM时钟采集为数据的中点。视频里讲的是要求把系统时钟反转,反转后的时钟作为SDRAM时钟。

从仿真截图可以看出,反转后SDRAM时钟采样点恰好为数据中点。从而达到要求。

时序图

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

设计时序

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

可以看出这是初始化的模式寄存器配置的时序图(program mode register 暂时不去考虑-后续博文填坑)

接下来看语言描述

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

100us的延时需要在任何操作之前除过NOP和INHIBIT命令。这两个命令必须在200us期间应用并且持续在这个区间结束后。(这句话不懂什么意思)在满足上述条件后,precharge命令应该被应用在100us延时以后。所有的bank必须预充电,这将使得所有的bank进入idle状态。在两个auto refresh命令之后,SDRAM准备进行模式寄存器配置。

就是说这里需要上电后进行**(1)最少200us的延时。之后所有bank进入idle状态,然后进行(2)两次auto refresh 状态。之后对其进行(3)**模式寄存器配置。

即完成操作。下面看各个操作的时间间隔。

时间间隔

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

trp的最大时间间隔就是20ns

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化
基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化
基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

以上就是所有的时序需要知道的时间间隔。

COMMAND 与 LOAD MODE REGISTER

同样看数据手册

LOAD MODE REGISTER

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

在模式寄存器配置在A0到A12,只有在所有bank空闲状态这个命令才可以被发出。可以看出,这里通过A0-A12来进行配置模式寄存器。

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

突发长度(连续读出写入数据的长度),突发类型,cas潜伏期,操作模式,写突发所有作为模式寄存器定义。

先来看看每一个是什么意思(这里有详细的介绍)

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

这里解释下潜伏期。(简单理解就是读使能信号来了之后数据输出的延时,时序图如下)

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

这里是数据手册对突发类型的解释。突发类型,就是读数的映射读数方法

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

COMMAND

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

代码书写

接下来就是代码实现。理解起来开始这个不会很难。

module sdram_init(
	//system singles
	clk,rst_n,
	//others singles
	cmd_reg,sdram_addr,flag_init_end
    );
input 					clk 			;
input 					rst_n 			;
output [ 3:0] 			cmd_reg 		;
output [11:0] 			sdram_addr 		;
output 					flag_init_end 	;
reg 	[ 3:0]			cmd_reg 		;
reg 					flag_init_end	;
//*************************************************\
//define parameter and intennal singles
//*************************************************/
localparam DELAY_200US = 10000 	;
reg  [13:0] 	cnt_200us  		;
reg  [ 3:0]		cnt_cmd			;
wire 			flag_200us		;
//sdram command
localparam NOP  = 4'b0111		;
localparam PRE  = 4'b0010		;
localparam AREF = 4'b0001		;
localparam MSET = 4'b0000		;
//*************************************************\
//main code
//*************************************************/
//200us_cnt
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt_200us <= 14'd0;
	else 
		if(!flag_200us)
			cnt_200us <= cnt_200us + 1'b1;
end

assign flag_200us = (cnt_200us >= DELAY_200US) ? 1'b1 : 1'b0;

//cnt_cmd
always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt_cmd <= 'd0;
	else 
		if(flag_200us == 1'b1 && flag_init_end == 1'b0)
			cnt_cmd <= cnt_cmd + 'd1;
end
//flag_init_end
always	@(posedge clk or negedge rst_n)	begin
		if(!rst_n)
				flag_init_end	<=	0;
		else if(cnt_cmd == 4'd10)
				flag_init_end	<=	1;	
			
end
//cmd_reg
always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cmd_reg <= NOP;
	else 
		if(flag_200us)
			case(cnt_cmd)
				0:cmd_reg <= PRE;
				1:cmd_reg <= AREF;
				5:cmd_reg <= AREF;
				9:cmd_reg <= MSET;
				default:cmd_reg <= NOP;
			endcase
end

//sdram_addr
assign	sdram_addr		=		(cmd_reg == MSET) ? 12'b0000_0011_0010 :12'b0100_0000_0000;
//突发长度为4,潜伏期为3 Burst Type       = Sequential  Write Burst Mode = Programmed Burst Length
endmodule
           

放着结果,这里用仿真器仿真,模拟SDRAM,同时在控制面板打印相关信息

基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化
基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化