📄 init_fsm.v
字号:
`timescale 1ns/1ps
`include "sdr_par.v"
module init_fsm(
clk,
rst_n,
init_done,
i_state);
//----------------input and output io declare-----------------------
input wire clk; //系统时钟50M
input wire rst_n;
output reg init_done; //暗示初始化是否完成
output reg[2:0] i_state; //状态变量
//----------------test port declare--------------------------------
//----------------parameter declare---------------------------------
//sdram 时序参数单位为ns
//实际若按照下面程序,tRP=60ns,tRFC=100ns,tMRD>60ns
parameter tCK = 20; //系统时钟50M
parameter tMRD = 40; //模式寄存器设置有效命令发出后,tMRD延时后才能发下个命令,手册上给最小2ns
parameter tRP = 40; //充电命令发出后,tRP延时后才能发下个命令,手册上给最小20ns
parameter tRFC = 80; //刷新命令发出后,延时tRFC后才能发下个命令,手册上给最小63ns
//把参数转换成对应的时钟数
parameter NUM_CLK_tMRD = tMRD/tCK-1;
parameter NUM_CLK_tRP = tRP /tCK-1;
parameter NUM_CLK_tRFC = tRFC/tCK-1;
//初始化状态机
/*
parameter i_NOP = 3'b000;
parameter i_PRE = 3'b001;
parameter i_tRP = 3'b010;
parameter i_AR = 3'b011;
parameter i_tRFC = 3'b100;
parameter i_MRS = 3'b101;
parameter i_tMRD = 3'b110;
parameter i_ready = 3'b111;
*/
//为了简化操作引入下面的宏定义
`define endOf_tRP clk_cnt == NUM_CLK_tRP
`define endOf_tRFC clk_cnt == NUM_CLK_tRFC
`define endOf_tMRD clk_cnt == NUM_CLK_tMRD
parameter DELAY_300us=14'd15000; //针对系统跑50M,如果不是则需要修改
parameter Tp=2; //RTL simulation parameter
//-------------internal variable declare---------------------------------
(* syn_preserve = 1 *)reg en_clk; //是否允许计数
(* syn_preserve = 1 *)reg[3:0] clk_cnt; //对clk进行计数
(* syn_preserve = 1 *)reg[2:0] refresh_time; //刷新次数
(* syn_preserve = 1 *)reg[13:0] delay_cnt; //延时300us计数器
(* syn_preserve = 1 *)reg delay_300us_done;//delay 300ns is done
//-----------main code--------------------------------------------------
always@(posedge clk)
begin
if(!rst_n)
begin
//init output port
init_done <=#Tp 1'b0;
i_state <=#Tp `i_NOP;
//init the reg
en_clk <=#Tp 1'b0;
clk_cnt <=#Tp 4'd0;
refresh_time <=#Tp 3'd0;
delay_cnt <=#Tp 14'd0;
delay_300us_done<=#Tp 1'b0;
end
else
begin
//----------clk_cnt operation
if(en_clk)
clk_cnt <=#Tp clk_cnt+1'b1;
else
clk_cnt <=#Tp 4'd0;
//-----------delay_cnt openation
if(delay_cnt==DELAY_300us)
delay_300us_done<=#Tp 1'b1;
else
delay_cnt <=#Tp delay_cnt+1'b1;
//----------state machin operation
//凡是下个状态要延时的,本状态就应该把enclk=1.cnt=0
//凡是下个状态不延时的,本状态就应该把enclk=0.cnt=0
case(i_state)
`i_NOP:
begin
if(delay_300us_done==1'b1)
begin
i_state <=#Tp `i_PRE;
en_clk <=#Tp 1'b0; //不准备计数
clk_cnt <=#Tp 4'd0;
end
end
`i_PRE:
begin
i_state <=#Tp `i_tRP;
en_clk <=#Tp 1'b1; //准备计数
clk_cnt <=#Tp 4'd0;
end
`i_tRP:
begin
if(`endOf_tRP)
begin
i_state <=#Tp `i_AR;
en_clk <=#Tp 1'b0;
clk_cnt <=#Tp 4'd0;
end
end
`i_AR :
begin
i_state <=#Tp `i_tRFC;
en_clk <=#Tp 1'b1; //准备计数
clk_cnt <=#Tp 4'd0;
end
`i_tRFC:
begin
if(`endOf_tRFC)
begin
if(refresh_time==3'd7)
begin
i_state <=#Tp `i_MRS;
en_clk <=#Tp 1'b0;
clk_cnt <=#Tp 4'd0;
end
else
begin
i_state <=#Tp `i_AR;
en_clk <=#Tp 1'b0;
clk_cnt <=#Tp 4'd0;
refresh_time<=#Tp refresh_time+1'b1;
end
end
end
`i_MRS:
begin
i_state <=#Tp `i_tMRD;
en_clk <=#Tp 1'b1;
clk_cnt <=#Tp 4'd0;
end
`i_tMRD:
begin
if(`endOf_tMRD)
begin
i_state <=#Tp `i_ready;
en_clk <=#Tp 1'b0;
clk_cnt <=#Tp 4'd0;
end
end
`i_ready:
begin
i_state <=#Tp `i_ready;
init_done <=#Tp 1'b1;
end
endcase
end
end
//-----------test code--------------------------------------------------
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -