忽略的网站,吉林有做网站的吗,网站 搜索怎么实现,网站用户互动因为DDR2本质上只是更高级的一种SRAM#xff0c;底层操作原理和SRAM是一样的#xff0c;所以很多基础的东西就不再赘述了。
一、原理
在初始化之前#xff0c;DDR2芯片需要先上电#xff0c;芯片有多个需要提供的电压#xff0c;其大小和顺序也有要求#xff0c;这部分…因为DDR2本质上只是更高级的一种SRAM底层操作原理和SRAM是一样的所以很多基础的东西就不再赘述了。
一、原理
在初始化之前DDR2芯片需要先上电芯片有多个需要提供的电压其大小和顺序也有要求这部分算是物理层的在此不作研究。
在上电稳定之后还需要等待时钟稳定才能进行操作。
时钟稳定后开始第一轮对LMR的操作配置四个(E)MRS实现激活DLL和DLL复位的功能。
随后进行至少两次自动刷新再开始第二轮对LMR的操作配置四个(E)MRS实现停止DLL复位和退出OCD的功能。
稳定后即完成了初始化DDR2可以正常工作。
二、模块框图和接口 三、时序图 注意这些延迟的具体值和数据速率(Data Rate)密切相关即和串口时钟频率相关在这里假设串口时钟频率为400MHz即下图中的-25那么一个周期就是T2.5ns延迟周期数将使用2.5ns计算。 假设容量为8Meg*16*4banks512Gb因此dq位宽为16ba位宽为2行addr位宽为13列addr位宽为10。
根据芯片手册的时序图舍弃部分无用的信号增添具体信号值查阅手册得到准确的延时延时部分内容太多涉及到的都放在本文末尾画出更清晰的时序图如下。 其中第三条之后的虚线为系统时钟sys_clk的上升沿用于输出值的改变输给DDR2的接口时钟clkclk_n应当比sys_clk延迟半个周期用于采样。
这里又遇到了如何生成sys_clk和clkclk_n的问题放在后文详述。又挖坑了
其中addr总线的具体值描述如下。 EMR(2)不用考虑高温自刷新的问题全为0即可。 EMR(3)保留全为0。 EMR_1此处需要打开DLL功能所以A0为0还有两个参数需要关注A3~A5和A7~A9。前者是关于AL的长度详见DDR2 SDRAM二信号和时序-CSDN博客后者是OCD校准在这里为了简化都设为0。另外也去掉一些不必要的信号和接口所以A10为1关闭dqs_nA11为0关闭rdqs。此处ODT必须禁用。 MR_1此处需要将DLL复位所以A8为1其余全为0。注意复位后要至少200个周期才能读。 MR_2此处需要停止DLL复位所以A8为0A0~A2是突发长度设为011(8)A4~A6是CAS延迟根据上文的假设设为110(6)A9~A11是自动预充电的写恢复时间本次设计中不打算加入此功能只需要知道这个时间是tWR可以通过查表得到此处为了方便直接设为101(6)。 EMR_2想要退出OCD校准要先在此处设置DLL default即A7~A9都为1。ODT就设为75Ω好了所以A6为0A2为1。 EMR_3此处需要退出OCD校准A7~A9都为0。
注意为了提高代码的灵活性以上提到的参数都应该使用parameter定义。
四、状态机
复位撤销后开始计数计数到80000时拉高cke并将init_amd设置为NOP。计数到80000160时拉高A10选中所有bank并将init_amd设置为PREC等待tRPA。将init_amd设置为LMBA设为10init_addr设为13’b0等待tMRD。将init_amd设置为LMBA设为11init_addr设为13’b0等待tMRD。将init_amd设置为LMBA设为01init_addr[10]设为1其余为0等待tMRD。将init_amd设置为LMBA设为00init_addr[8]设为1其余为0等待tMRD。拉高A10选中所有bank并将init_amd设置为PREC等待tRPA。将init_amd设置为REF等待tRFC。将init_amd设置为REF等待tRFC。将init_amd设置为LMBA设为00init_addr[2:0]为011init_addr[6:4]为110init_addr[11:9]为101,其余为0等待tMRD。将init_amd设置为LMBA设为01init_addr[9:7]为111init_addr[10]为1init_addr[2]为1其余为0等待tMRD。将init_amd设置为LMBA设为01init_addr[10]设为1init_addr[2]为1其余为0等待tMRD。初始化完成。
五、代码实现
/***************************************************************************************
作者:not_lubao
2024-11-1
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××*/// DDR2初始化模块初始化步骤:上电--延时200us--拉高cke--延时400ns--预充电--寄存器配置--刷新n次--寄存器配置--完成module ddr2_init(
input sys_clk , //系统时钟信号100MHz
input rstn , //系统复位信号output cke , //时钟使能
output [1:0] init_ba , //Bank
output [3:0] init_cmd , //命令
output [12:0] init_addr , //地址
output init_end //初始化结束标志
);/***********************参数************************/
//状态机
parameter IDLE 6d0 ,WAIT_IDLE 6d1 ,CLK_EN 6d2 ,WAIT_CKE 6d3 ,P_CHAR 6d4 ,WAIT_PREC 6d5 ,LM_EMR2 6d6 ,LM_EMR3 6d7 ,LM_EMR_1 6d8 ,LM_MR_1 6d9 ,LM_MR_2 6d10 ,LM_EMR_2 6d11 ,LM_EMR_3 6d12 ,WAIT_LM 6d13 ,AUTO_REF 6d14 ,WAIT_REF 6d15 ,WAIT_DLL_RST 6d16 ,END 6d17 ;//等待时间 比实际要求最小值多一个周期
parameter T_INIT 17d80000 , //上电后等待T_CKE 17d160 , //拉高cke后等待T_tRPA 17d6 , //充电后等待T_tMRD 17d1 , //配置寄存器后等待T_tRFC 17d42 , //刷新后等待T_DLL_RST 17d110 ; //拉高cke后等待大于99//指令
parameter LM 4b0000 ,REF 4b0001 ,PREC 4b0010 ,ACT 4b0011 ,WR 4b0100 ,RD 4b0101 ,NOP 4b0111 ;//自刷新次数
parameter REF_TIME 4d2 ;//模式寄存器的值
parameter EMR2 13b0 , //不用考虑高温自刷新的问题全为0EMR3 13b0 , //保留EMR_1 13b0_0010_0000_0000 , //[0]为0打开DLL功能[5:3]AL长度和[9:7]OCD校准都为0[10]为1关闭dqs_n[11]为0关闭rdqs{[6],[2]}为01ODT75ΩMR_1 13b0_0000_1000_0000 , //[8]为1DLL复位其余全为0MR_2 13b0_0101_0011_0011 , //[8]为0停止DLL复位[2:0]为011突发长度8[6:4]为110CAS延迟6[11:9]为101自动预充电的写恢复时间6EMR_2 13b0_0011_1100_0010 , //[9:7]为111OCD default{[6],[2]}为01ODT75ΩEMR_3 13b0_0010_0000_0010 ; //[9:7]为000退出OCD校准/* 模式寄存器的具体值受芯片型号影响以下仅做参考
MR[2:0] 突发长度 4010或8011[3] 突发类型 0顺序或1插入[6:4] CAS延迟 0102到1117一般大于3[7] 测试模式 0正常工作或1测试[8] DLL复位 0无效或1有效[11:9] 带自动预充电的写恢复时间 0102到1117一般大于2[12] 活跃低功耗模式的退出时间 0快退出 tXARD或1慢退出 tXARDSEMR[0] DLL功能 0开启或1关闭[1] D.I.C 输出驱动阻抗 0满强度或1降低强度{[6],[2]} Rtt 00无效或0175Ω或10150Ω或1150Ω[5:3] AL 额外延时 0000到1106111为保留[9:7] OCD校准 000退出或001驱动1或010驱动0或100调整或111default[10] 差分DQS 0启用或1禁用[11] RDQS 0禁用或1启用[12] Qoff输出控制 0启用或1禁用包括DQ/DQS/RDQS
*//***********************寄存器************************/
reg [5:0] r_state, r_next_state ;
reg [16:0] r_latency_T ; //延时长度寄存器
reg [16:0] r_cnt_wait ; //计时计数器值
reg [3:0] r_ref_cnt ; //刷新次数计数
reg [7:0] r_cke_cnt ; //CKE拉高时间计数器reg r_cke ;
reg [1:0] r_init_ba ;
reg [3:0] r_init_cmd ;
reg [12:0] r_init_addr ;
reg r_init_end ;/***********************时序逻辑************************/
always(posedge sys_clk or negedge rstn) begin //计时器模块if(!rstn)r_cnt_wait 17d0;else if(r_cnt_wait r_latency_T) //计满自动清零r_cnt_wait 17d0;elser_cnt_wait r_cnt_wait 17d1;
endalways(posedge sys_clk or negedge rstn) begin //刷新次数计数器if(!rstn)r_ref_cnt 4d0;else if((r_ref_cnt REF_TIME) (r_cnt_wait T_tRFC)) //达到设定刷新次数且本次刷新后等待时间tRFC结束r_ref_cnt 4d0;else if(r_next_state AUTO_REF) //下一个状态是刷新r_ref_cnt r_ref_cnt 4d1;elser_ref_cnt r_ref_cnt;
end/*各个state持续时间的设定
在切换状态的一瞬间计数器执行清零操作目标计数值被重新赋值这样就实现了延时参数的传递
那样就可以只使用一个计数器*/
always(posedge sys_clk or negedge rstn) begin if(!rstn)r_latency_T 10d0;elsecase(r_next_state)IDLE : r_latency_T 10d0 ;WAIT_IDLE : r_latency_T T_INIT ;CLK_EN : r_latency_T 10d0 ; WAIT_CKE : r_latency_T T_CKE ;P_CHAR : r_latency_T 10d0 ;WAIT_PREC : r_latency_T T_tRPA ;LM : r_latency_T 10d0 ;WAIT_LM : r_latency_T T_tMRD ;AUTO_REF : r_latency_T 10d0 ;WAIT_REF : r_latency_T T_tRFC ;WAIT_DLL_RST : r_latency_T T_DLL_RST ;END : r_latency_T 10d0 ;default : r_latency_T 10d0 ;endcase
end/***********************组合逻辑************************/
assign cke r_cke ;
assign init_cmd r_init_cmd ;
assign init_addr r_init_addr ;
assign init_ba r_init_ba ;
assign init_end r_init_end ;/***********************状态机************************/
always(posedge sys_clk or negedge rstn) begin//状态转移if(!rstn)r_state IDLE;elser_state r_next_state;
endalways(*) begin //状态转移判断模块根据计时时间判断是否已经持续相应时间长度if(!rstn)r_next_state IDLE;elsecase(r_state)IDLE :r_next_state WAIT_IDLE;WAIT_IDLE :if(r_cnt_wait r_latency_T)r_next_state CLK_EN;elser_next_state r_state;CLK_EN :r_next_state WAIT_CKE;WAIT_CKE :if(r_cnt_wait r_latency_T)r_next_state P_CHAR;elser_next_state r_state;P_CHAR :r_next_state WAIT_PREC;WAIT_PREC :if(r_cnt_wait r_latency_T)r_next_state LM_EMR2;elser_next_state r_state;LM_EMR2 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state LM_EMR3;elser_next_state r_state;LM_EMR3 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state LM_EMR_1;elser_next_state r_state;LM_EMR_1 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state LM_MR_1;elser_next_state r_state;LM_MR_1 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state P_CHAR;elser_next_state r_state;P_CHAR :r_next_state WAIT_PREC;WAIT_PREC :if(r_cnt_wait r_latency_T)r_next_state AUTO_REF;elser_next_state r_state;AUTO_REF :r_next_state WAIT_REF;WAIT_REF : if((r_ref_cnt REF_TIME) (r_cnt_wait r_latency_T)) //达到设定刷新次数且本次刷新后等待时间tRC结束r_next_state LM_MR_2;else if(r_cnt_wait r_latency_T)r_next_state AUTO_REF;elser_next_state r_state;LM_MR_2 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state LM_EMR_2;elser_next_state r_state;LM_EMR_2 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state LM_EMR_3;elser_next_state r_state;LM_EMR_3 :r_next_state WAIT_LM;WAIT_LM :if(r_cnt_wait r_latency_T)r_next_state WAIT_DLL_RST;elser_next_state r_state;WAIT_DLL_RST :if(r_cnt_wait r_latency_T)r_next_state END;elser_next_state r_state;END : r_next_state END;default : r_next_state IDLE;endcase
endalways(posedge sys_clk or negedge rstn) begin //输出模块三段式状态机if(!rstn) beginr_init_cmd NOP ;r_init_ba 2b11 ;r_init_addr 13h1fff ;r_init_end 1b0 ;end else case(r_state)IDLE,WAIT_IDLE,WAIT_CKE,WAIT_PREC,WAIT_LM,WAIT_REF,WAIT_DLL_RST : beginr_init_cmd NOP ;r_init_ba 2b11 ;r_init_addr 13h1fff ;endCLK_EN : beginr_cke 1b1 ;endP_CHAR : beginr_init_cmd PREC ;r_init_ba 2b11 ;r_init_addr 13h1fff ;endLM_EMR2 : beginr_init_cmd LM ;r_init_ba 2b10 ;r_init_addr EMR2 ;endLM_EMR3 : beginr_init_cmd LM ;r_init_ba 2b11 ;r_init_addr EMR3 ;endLM_EMR_1 : beginr_init_cmd LM ;r_init_ba 2b01 ;r_init_addr EMR_1 ;endLM_MR_1 : beginr_init_cmd LM ;r_init_ba 2b00 ;r_init_addr MR_1 ;endLM_MR_2 : beginr_init_cmd LM ;r_init_ba 2b00 ;r_init_addr MR_2 ;endLM_EMR_2 : beginr_init_cmd LM ;r_init_ba 2b01 ;r_init_addr EMR_2 ;endLM_EMR_3 : beginr_init_cmd LM ;r_init_ba 2b01 ;r_init_addr EMR_3 ;endAUTO_REF : beginr_init_cmd REF ;r_init_ba 2b11 ;r_init_addr 13h1fff ;endEND : beginr_init_cmd NOP ;r_init_ba 2b11 ;r_init_addr 13h1fff ;r_init_end 1b1 ;enddefault : beginr_init_cmd NOP ;r_init_ba 2b11 ;r_init_addr 13h1fff ;endendcase
endendmodule
注本模块和后续模块不再进行单独仿真可能会有bug最终仿真完成会统一修改然后删掉这句话。 附延时查找表