当前位置:网站首页>02-SDRAM:自动刷新
02-SDRAM:自动刷新
2022-07-29 20:47:00 【刘颜儿】
SDRAM自动刷新模块
- cnt_7: 自动刷新是周期性的,因此需要时钟去重复计数,计满后就可以发出自动刷新请求信号给仲裁模块(依赖 init_end,计满清零)
- auto_ref_req: 传给仲裁模块的自动刷新请求信号,计数器加满拉高,得到内部应答后拉低(依赖计数器 cnt_7、auto_ref_ack)
- auto_ref_en:
- auto_ref_ack: 当状态跳转到预充电 ATREF_PRE,内部产生应答信号(依赖 ATREF_PRE)
- state
- cnt_cmd: 计数器,用来给2个等待时间计数 (依赖 cnt_cmd_reset)
- cnt_cmd_reset: 上一个计数器的清零信号 (依赖计满信号:trp_end、trfc_end)
- trp_end、trfc_end: 自家延时结束的信号(依赖 状态)
- cnt_ref: 自动刷新的次数,至少需要2次自动刷新(依赖状态 ATREF_AR 、 ATREF_IDLE)
设计文件
// SDRAM自动刷新模块
// 1. cnt_7: 自动刷新是周期性的,因此需要时钟去重复计数,计满后就可以发出自动刷新请求信号给仲裁模块(依赖 init_end,计满清零)
// 2. auto_ref_req: 传给仲裁模块的自动刷新请求信号,计数器加满拉高,得到内部应答后拉低(依赖计数器 cnt_7、auto_ref_ack)
// 3. auto_ref_en:
// 4. auto_ref_ack: 当状态跳转到预充电 ATREF_PRE,内部产生应答信号(依赖 ATREF_PRE)
// 5. state
// 6. cnt_cmd: 计数器,用来给2个等待时间计数 (依赖 cnt_cmd_reset)
// 7. cnt_cmd_reset: 上一个计数器的清零信号 (依赖计满信号:trp_end、trfc_end)
// 8. trp_end、trfc_end: 自家延时结束的信号(依赖 状态)
// 9. cnt_ref: 自动刷新的次数,至少需要2次自动刷新(依赖状态 ATREF_AR 、 ATREF_IDLE)
module sdram_auto_ref(
input clk,
input rst_n,
input init_end,//初始化模块传入
input auto_ref_en,//仲裁模块传入,仲裁模块用来判断当前SDRAM是否可以自动刷新
output reg auto_ref_req,//传给仲裁模块(要得到仲裁模块传来的刷新使能信号auto_ref_en才能开始自动刷新)
output reg [3:0] auto_ref_cmd,//SDRAM命令,组成{CS#,RAS#,CAS#,WE#}
output [1:0] auto_ref_bank,//BANK地址,共4个BANK
output [12:0] auto_ref_addr,//SDRAM地址总线
output auto_ref_end//初始化完成信号,初始化完成后拉高,其他时间保持低电平
);
//==========================================parameter===========================================================
//状态机
localparam ATREF_IDLE = 3'b000, //自动刷新初始状态
ATREF_PRE = 3'b001, //预充电状态
ATREF_TRP = 3'b011, //预充电等待状态
ATREF_AR = 3'b010, //自动刷新状态
ATREF_TRFC = 3'b110, //自动刷新等待状态
ATREF_END = 3'b111; //自动刷新结束状态
parameter MAX_CNT_700 = 12'd700; //计算出来是 7812ns,但是仲裁模块需要时间去给出auto_ref_en,需要花费时间,因此这里使用7000ns
parameter MAX_REF_TIME = 2'd2;
//等待时间参数定义
localparam TRP = 3'd2 , //发送预充电指令后进行下一个操作需要等待的时间
TRFC = 3'd7 ; //发送自动刷新指令后进行下一个操作需要等待的时间
//命令指令参数
localparam PRECHARGE = 4'b0010 , //预充电指令
AT_REF = 4'b0001 , //自动刷新指令
NOP = 4'b0111 ; //空操作指令
//==========================================reg=================================================================
reg [5:0] state;
reg [5:0] next_state;
reg [3:0] cnt_cmd;
reg [11:0] cnt_7;//64_000/2^13=7.8125us,于是需要10ns的时钟计数7_00次
reg [1:0] cnt_ref;
//==========================================wire=================================================================
wire auto_ref_ack;
wire trp_end;
wire trfc_end;
wire cnt_cmd_reset;
//==========================================assign=================================================================
// 内部应答信号
assign auto_ref_ack = (state == ATREF_PRE) ? 1'd1:1'd0;
assign trp_end = ((state == ATREF_TRP) && (cnt_cmd == TRP-1)) ? 1'd1:1'd0;
assign trfc_end = ((state == ATREF_TRFC) && (cnt_cmd == TRFC-1))? 1'd1:1'd0;
assign cnt_cmd_reset = ((state == ATREF_IDLE) || (state == ATREF_END) || trp_end || trfc_end) ? 1'd1:1'd0;
assign auto_ref_bank = 2'd11;
assign auto_ref_addr = 13'h1fff;
assign auto_ref_end = (state == ATREF_END)?1'd1:1'd0;
//==========================================always=================================================================
// 自动刷新周期计数器
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n )begin
cnt_7 <= 12'd0;
end
else if(init_end)// 初始化成功后,才开始计数
if(cnt_7 == MAX_CNT_700)begin
cnt_7 <= 12'd0;
end
else
cnt_7 <= cnt_7 + 12'd1;
else
cnt_7 <= cnt_7;
end
// 请求信号
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n )begin
auto_ref_req <= 1'd0;
end
else if(cnt_7 == MAX_CNT_700 - 1)begin
auto_ref_req <= 1'd1;
end
else if(auto_ref_ack)
auto_ref_req <= 1'd0;
else
auto_ref_req <= auto_ref_req;
end
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n )begin
cnt_cmd <= 4'd0;
end
else if(cnt_cmd_reset)begin
cnt_cmd <= 4'd0;
end
else
cnt_cmd <= cnt_cmd + 4'd1;
end
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n )begin
cnt_ref <= 2'd0;
end
else if(state == ATREF_AR)begin
cnt_ref <= cnt_ref + 2'd1;
end
else if(state == ATREF_IDLE)
cnt_ref <= 2'd0;
else
cnt_ref <= cnt_ref ;
end
//==========================================状态机=================================================================
// 第一段
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n )begin
state <= ATREF_IDLE;
end
else
state <= next_state;
end
//第二段
[email protected](*)begin
case(state)
ATREF_IDLE:
if(init_end && auto_ref_en)//auto_ref_ack
next_state = ATREF_PRE;
else
next_state = ATREF_IDLE;
ATREF_PRE :next_state = ATREF_TRP;
ATREF_TRP :
if(trp_end)
next_state = ATREF_AR;
else
next_state = ATREF_TRP;
ATREF_AR :next_state = ATREF_TRFC;
ATREF_TRFC:
if(trfc_end)
if(cnt_ref == MAX_REF_TIME)
next_state = ATREF_END;
else
next_state = ATREF_AR;
else
next_state = ATREF_TRFC;
ATREF_END :next_state = ATREF_IDLE;
default:next_state = ATREF_IDLE;
endcase
end
// 第三段
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n )begin
auto_ref_cmd <= NOP;
end
else
case(state)
ATREF_IDLE : auto_ref_cmd <= NOP;
ATREF_PRE : auto_ref_cmd <= PRECHARGE;
ATREF_TRP : auto_ref_cmd <= NOP;
ATREF_AR : auto_ref_cmd <= AT_REF;
ATREF_TRFC : auto_ref_cmd <= NOP;
ATREF_END : auto_ref_cmd <= NOP;
default:auto_ref_cmd <= NOP;
endcase
end
endmodule
测试文件
`timescale 1ns/1ns
// Author : EmbedFire
// Create Date : 2019/08/25
// Module Name : tb_sdram_init
// Project Name : uart_sdram
// Target Devices: Altera EP4CE10F17C8N
// Tool Versions : Quartus 13.0
// Description : SDRAM初始化模块仿真
//
// Revision : V1.0
// Additional Comments:
//
// 实验平台: 野火_征途Pro_FPGA开发板
// 公司 : http://www.embedfire.com
// 论坛 : http://www.firebbs.cn
// 淘宝 : https://fire-stm32.taobao.com
module tb_sdram_auto_ref();
//********************************************************************//
//****************** Internal Signal and Defparam ********************//
//********************************************************************//
//wire define
//clk_gen
wire clk_50m ; //PLL输出50M时钟
wire clk_100m ; //PLL输出100M时钟
wire clk_100m_shift ; //PLL输出100M时钟,相位偏移-30deg
wire locked ; //PLL时钟锁定信号
wire rst_n ; //复位信号,低有效
//sdram_init
wire [3:0] init_cmd ; //初始化阶段指令
wire [1:0] init_ba ; //初始化阶段L-Bank地址
wire [12:0] init_addr ; //初始化阶段地址总线
wire init_end ; //初始化完成信号
wire auto_ref_req ;
wire [3:0] auto_ref_cmd ;
wire [1:0] auto_ref_bank;
wire [12:0] auto_ref_addr;
wire auto_ref_end ;
//sdram
wire [3:0] sdram_cmd ; //SDRAM操作指令
wire [1:0] sdram_bank ; //SDRAM L-Bank地址
wire [12:0] sdram_addr ; //SDRAM地址总线
//reg define
reg clk_c1 ; //系统时钟
reg sys_rst_n ; //复位信号
reg auto_ref_en;
//defparam
//重定义仿真模型中的相关参数
defparam sdram_model_plus_inst.addr_bits = 13; //地址位宽
defparam sdram_model_plus_inst.data_bits = 16; //数据位宽
defparam sdram_model_plus_inst.col_bits = 9; //列地址位宽
defparam sdram_model_plus_inst.mem_sizes = 2*1024*1024; //L-Bank容量
//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************//
//时钟、复位信号
initial
begin
clk_c1 = 1'b1 ;
sys_rst_n <= 1'b0 ;
#200
sys_rst_n <= 1'b1 ;
end
always #10 clk_c1 = ~clk_c1;
//rst_n:复位信号
assign rst_n = sys_rst_n & locked;
//atref_en:自动刷新使能
[email protected](posedge clk_100m or negedge rst_n)begin
if(rst_n == 1'b0)
auto_ref_en <= 1'b0;
else if((init_end == 1'b1) && (auto_ref_req == 1'b1))
auto_ref_en <= 1'b1;
else if(auto_ref_end == 1'b1)
auto_ref_en <= 1'b0;
end
//sdram_cmd,sdram_ba,sdram_addr
assign sdram_cmd = (init_end == 1'b1) ? auto_ref_cmd : init_cmd;
assign sdram_bank = (init_end == 1'b1) ? auto_ref_bank : init_ba;
assign sdram_addr = (init_end == 1'b1) ? auto_ref_addr : init_addr;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- clk_gen_inst -------------
clk_gen clk_gen_inst (
.inclk0 (clk_c1 ),
.areset (~sys_rst_n ),
.c0 (clk_50m ),
.c1 (clk_100m ),
.c2 (clk_100m_shift ),
.locked (locked )
);
//------------- sdram_init_inst -------------
sdram_initial sdram_initial_inst(
.clk (clk_100m ),
.rst_n (rst_n ),
.init_cmd (init_cmd ),
.init_bank (init_ba ),
.init_addr (init_addr ),
.init_end (init_end )
);
sdram_auto_ref sdram_auto_ref_inst(
.clk (clk_100m ),
.rst_n (rst_n ),
.init_end (init_end ),
.auto_ref_en (auto_ref_en),
.auto_ref_req (auto_ref_req ),
.auto_ref_cmd (auto_ref_cmd ),
.auto_ref_bank (auto_ref_bank ),
.auto_ref_addr (auto_ref_addr ),
.auto_ref_end (auto_ref_end )
);
//-------------sdram_model_plus_inst-------------
sdram_model_plus sdram_model_plus_inst(
.Dq ( ),
.Addr (sdram_addr ),
.Ba (sdram_bank ),
.Clk (clk_100m_shift ),
.Cke (1'b1 ),
.Cs_n (sdram_cmd[3] ),
.Ras_n (sdram_cmd[2] ),
.Cas_n (sdram_cmd[1] ),
.We_n (sdram_cmd[0] ),
.Dqm (2'b0 ),
.Debug (1'b1 )
);
//------------------------------------------------
//-- 状态机名称查看器
//------------------------------------------------
reg [79:0] name_state_cur; //每字符8位宽,这里取最多10个字符80位宽
always @(*) begin
case(sdram_auto_ref_inst.state)
3'b000: name_state_cur = "ATREF_IDLE";
3'b001: name_state_cur = "ATREF_PRE ";
3'b011: name_state_cur = "ATREF_TRP ";
3'b010: name_state_cur = "ATREF_AR ";
3'b110: name_state_cur = "ATREF_TRFC";
3'b111: name_state_cur = "ATREF_END ";
default: name_state_cur = "ATREF_IDLE";
endcase
end
endmodule
窗口打印信息

边栏推荐
猜你喜欢

The sword refers to Offer II 097. Number of subsequences

.NET 6.0中使用Identity框架实现JWT身份认证与授权

MySQL数据查询 - 简单查询

分析少年派2中的Crypto

OneNote tutorial, how to take notes in OneNote?

4. Implementation Guide for GET_ENTITYSET Method of SAP ABAP OData Service Data Provider Class

UDP协议详解

7 行代码搞崩溃 B 站,原因令人唏嘘!

MySQL数据查询 - 联合查询
![[ACTF2020 Freshman Competition]Exec 1](/img/1e/a3c19d514207e6965d09c66b86e519.png)
[ACTF2020 Freshman Competition]Exec 1
随机推荐
全自动化机器学习建模!效果吊打初级炼丹师!
【无标题】
Analysis of Crypto in Pi 2
酷客导航助你商场轻松购物,业务办理不迷茫
分析少年派2中的Crypto
Cooler Navigation helps you shop easily in shopping malls without confusion
微信小程序 31 分包机制
LeetCode--单链表--146.LRU缓存
4. Implementation Guide for GET_ENTITYSET Method of SAP ABAP OData Service Data Provider Class
336. Palindromic Pairs
促进二十一世纪创客教育的新发展
Huawei laptop keyboard locked (how does the laptop keyboard light up)
378. 有序矩阵中第 K 小的元素
一线技术人应该关注的四种思维能力
The difference between analog, digital and switching
1. Promise usage in JS, 2. The concept and usage of closures, 3. The difference between the four methods and areas of object creation, 4. How to declare a class
TCP协议详解
Liu Genghong, boys and girls, come here!Sports data analysis and mining!(with a full set of code and data sets)
:style中颜色使用函数动态获取赋值
刘畊宏男孩女孩看过来!运动数据分析挖掘!(附全套代码和数据集)