`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company :
// Engineer :
// Create Date :
// Design Name :
// Module Name : sdram_top
// Project Name :
// Target Device: Cyclone EP1C3T144C8
// Tool versions: Quartus II 8.1
// Description : SDRAM状态控制模块
// SDRAM初始化以及定时刷新、读写控制
//
// Revision : V1.0
// Additional Comments :
//
////////////////////////////////////////////////////////////////////////////////
module sdram_ctrl(
clk,rst_n,
/*sdram_udqm,sdram_ldqm,*/
sdwr_byte,sdrd_byte,sys_r_wn,
sys_en,sdram_wr_ack,sdram_rd_ack,
sdram_busy,sys_dout_rdy,
init_state,work_state,cnt_clk
);
//系统信号接口
input clk; //系统时钟,50MHz
input rst_n; //复位信号,低电平有效
// SDRAM硬件接口
//output sdram_udqm; // SDRAM高字节屏蔽
//output sdram_ldqm; // SDRAM低字节屏蔽
// SDRAM封装接口
//input sdram_wr_req; //系统写SDRAM请求信号
//input sdram_rd_req; //系统读SDRAM请求信号
input sys_en;
input sys_r_wn;
output sdram_wr_ack; //系统写SDRAM响应信号,作为wrFIFO的输出有效信号
output sdram_rd_ack; //系统读SDRAM响应信号
//output sdram_ref_w; // SDRAM自刷新请求信号
output sdram_busy; // SDRAM忙标志位,高表示忙
output sys_dout_rdy; // SDRAM数据输出完成标志
input[8:0] sdwr_byte;
input[8:0] sdrd_byte;
// SDRAM内部接口
output[4:0] init_state; // SDRAM初始化寄存器
output[3:0] work_state; // SDRAM工作状态寄存器
output[8:0] cnt_clk; //时钟计数
wire done_200us; //上电后200us输入稳定期结束标志位
wire sdram_init_done; // SDRAM初始化完成标志,高表示完成
wire sdram_busy; // SDRAM忙标志,高表示SDRAM处于工作中
reg sdram_ref_req; // SDRAM自刷新请求信号
wire sdram_ref_ack; // SDRAM自刷新请求应答信号
`include "sdr_para.v" // 包含SDRAM参数定义模块
// SDRAM时序延时参数
parameter TRP_CLK = 9'd4,//1, //TRP=18ns预充电有效周期
TRFC_CLK = 9'd6,//3, //TRC=60ns自动预刷新周期
TMRD_CLK = 9'd6,//2, //模式寄存器设置等待时钟周期
TRCD_CLK = 9'd2,//1, //TRCD=18ns行选通周期
TCL_CLK = 9'd3, //潜伏期TCL_CLK=3个CLK,在初始化模式寄存器中可设置
TREAD_CLK = 9'd256, //突发读数据周期256CLK
TWRITE_CLK = 9'd256, //突发写数据256CLK
TDAL_CLK = 9'd3; //写入等待
//------------------------------------------------------------------------------
//assign sdram_udqm = 1'b0; // SDRAM数据高字节有效
//assign sdram_ldqm = 1'b0; // SDRAM数据低字节有效
//------------------------------------------------------------------------------
//上电后200us计时,计时时间到,则done_200us=1 50MHZ
//------------------------------------------------------------------------------
reg[14:0] cnt_200us;
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt_200us else if(cnt_200us < 15'd20_000) cnt_200us
assign done_200us = (cnt_200us == 15'd20_000); //条件满足则done_200us=1
//------------------------------------------------------------------------------
//SDRAM的初始化操作状态机
//------------------------------------------------------------------------------
reg[4:0] init_state_r; // SDRAM初始化状态
always @ (posedge clk or negedge rst_n)
if(!rst_n) init_state_r else //初始化阶段
case (init_state_r)
`I_NOP: init_state_r `I_PRE: init_state_r `I_TRP: init_state_r `I_AR1: init_state_r `I_TRF1: init_state_r `I_AR2: init_state_r `I_TRF2: init_state_r `I_AR3: init_state_r `I_TRF3: init_state_r `I_AR4: init_state_r `I_TRF4: init_state_r `I_AR5: init_state_r `I_TRF5: init_state_r `I_AR6: init_state_r `I_TRF6: init_state_r `I_AR7: init_state_r `I_TRF7: init_state_r `I_AR8: init_state_r `I_TRF8: init_state_r `I_MRS: init_state_r `I_TMRD: init_state_r `I_DONE: init_state_r default: init_state_r endcase
assign init_state = init_state_r;
assign sdram_init_done = (init_state_r == `I_DONE); // SDRAM初始化完成标志
//------------------------------------------------------------------------------
//15us计时,每60ms全部4096行存储区进行一次自刷新
// ( 存储体中电容的数据有效保存期上限是64ms )
//------------------------------------------------------------------------------
reg[10:0] cnt_15us; //计数寄存器
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt_15us else if(cnt_15us < 11'd1499) cnt_15us else cnt_15us
always @ (posedge clk or negedge rst_n)
if(!rst_n) sdram_ref_req else if(cnt_15us == 11'd1498) sdram_ref_req else if(sdram_ref_ack) sdram_ref_req
//------------------------------------------------------------------------------
//SDRAM的读写以及自刷新操作状态机
//------------------------------------------------------------------------------
reg[3:0] work_state_r; // SDRAM读写状态
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) work_state_r else
case (work_state_r)
//SDRAM空闲,初始化完成并且产生自刷新请求
`W_IDLE: if(sdram_ref_req && sdram_init_done && !sdram_busy)
work_state_r else if(sys_en & sdram_init_done)
work_state_r else work_state_r
//行有效状态 判断TRCD=18ns行选通延时是否结束
`W_ACTIVE: if(TRCD_CLK == 0) //时间到行有效
if(sys_r_wn) work_state_r else work_state_r else work_state_r //行有效等待
`W_TRCD: if(`end_trcd)
if(sys_r_wn) work_state_r else work_state_r else work_state_r // SDRAM读数据状态
`W_READ: work_state_r `W_CL: work_state_r `W_RD: work_state_r `W_RWAIT: work_state_r // SDRAM写数据状态
`W_WRITE: work_state_r `W_WD: work_state_r `W_TDAL: work_state_r // SDRAM自动刷新状态
`W_AR: work_state_r `W_TRFC: work_state_r
`W_RBST: work_state_r `W_WBST: work_state_r
default: work_state_r endcase
end
assign work_state = work_state_r; // SDRAM工作状态寄存器
assign sdram_busy = (sdram_init_done && work_state_r == `W_IDLE) ? 1'b0:1'b1; // SDRAM忙标志位
assign sdram_ref_ack = (work_state_r == `W_AR); // SDRAM自刷新应答信号
assign sdram_wr_ack = ((work_state == `W_TRCD) & ~sys_r_wn) | (work_state == `W_WRITE) |
((work_state == `W_WD) & (cnt_clk_r < sdwr_byte-2'd2)); //写SDRAM响应信号,作为wrFIFO的输出有效信号??
assign sdram_rd_ack = (work_state_r == `W_RD) & (cnt_clk_r > 9'd1) & (cnt_clk_r < sdrd_byte+2'd2); //读SDRAM响应信号
assign sys_dout_rdy = (work_state_r == `W_RD && `end_tread); // SDRAM数据输出完成标志
//------------------------------------------------------------------------------
//产生SDRAM时序操作的延时
//------------------------------------------------------------------------------
reg[8:0] cnt_clk_r; //时钟计数
reg cnt_rst_n; //时钟计数复位信号
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt_clk_r else if(!cnt_rst_n) cnt_clk_r else cnt_clk_r
assign cnt_clk = cnt_clk_r; //计数寄存器引出,内部`define中使用
//计数器控制逻辑
always @ (*) begin
case (init_state_r)
`I_NOP: cnt_rst_n `I_PRE: cnt_rst_n `I_TRP: cnt_rst_n `I_AR1,`I_AR2,`I_AR3,`I_AR4,`I_AR5,`I_AR6,`I_AR7,`I_AR8:
cnt_rst_n `I_TRF1,`I_TRF2,`I_TRF3,`I_TRF4,`I_TRF5,`I_TRF6,`I_TRF7,`I_TRF8:
cnt_rst_n `I_MRS: cnt_rst_n `I_TMRD: cnt_rst_n `I_DONE:
case (work_state_r)
`W_IDLE: cnt_rst_n `W_ACTIVE: cnt_rst_n `W_TRCD: cnt_rst_n `W_CL: cnt_rst_n `W_RD: cnt_rst_n `W_RWAIT: cnt_rst_n `W_WD: cnt_rst_n `W_TDAL: cnt_rst_n `W_TRFC: cnt_rst_n default: cnt_rst_n endcase
default: cnt_rst_n endcase
end
endmodule