📄 main_fsm.v
字号:
/*------------------------------------------------------
注意点:针对本sdram控制器
对于页模式的读burst_len>=3
对于页模式的写burst_len>=2
--------------------------------------------------------*/
`timescale 1ns/100ps
`include "sdr_par.v"
module main_fsm(
//input
clk,
rst_n,
read_req,
write_req,
burst_len,
refresh_req,
init_done,
//output
read_ack,
write_ack,
refresh_ack,
r_data_valid,
w_data_valid,
c_state
);
//----------------input and output io declare-----------------------
input clk;
input rst_n;
input read_req;
input write_req;
input[8:0] burst_len;
input refresh_req;
input init_done;
//此信号给refresh.v模块
output reg refresh_ack;
//给user模块
output reg read_ack;
output reg write_ack;
output reg r_data_valid;
output reg w_data_valid;
//给sig物理层模块
output reg[3:0] c_state;
//----------------test port declare--------------------------------
//----------------parameter declare---------------------------------
parameter tCK = 20;
parameter tRP = 40; //充电命令发出后,tRP延时后才能发下个命令,手册上给最小20ns
parameter tRFC = 80; //刷新命令发出后,延时tRFC后才能发下个命令,手册上给最小63ns
parameter Tp = 2;
//把参数转换成对应的时钟数
parameter NUM_CLK_tRP = tRP /tCK-1; //1
parameter NUM_CLK_tRFC = tRFC/tCK-1; //3
//state machine declare
/*
parameter c_IDLE = 4'b0000;
parameter c_AR = 4'b0001;
parameter c_tRFC = 4'b0010;
parameter c_RW_AR = 4'b0011;
parameter c_RW_tRFC = 4'b0100;
parameter c_ACTIVE = 4'b0101;
parameter c_tRCD = 4'b0110;
parameter c_READ = 4'b0111;
parameter c_RD_DATA = 4'b1000;
parameter c_R_PRE = 4'b1001;
parameter c_R_tRP = 4'b1010;
parameter c_WRITE = 4'b1011;
parameter c_WR_DATA = 4'b1100;
parameter c_W_PRE = 4'b1101;
parameter c_W_tRP = 4'b1110;
*/
//-------------internal variable declare---------------------------------
reg en_m_clk;
reg[8:0] clk_m_cnt;
reg[8:0] keep_burst_len; //用于保存burst_len
//-----------main code--------------------------------------------------
always@(posedge clk)
begin
if(!rst_n)
begin
//the signal below is active high
//init output port
refresh_ack <=#Tp 1'b0;
read_ack <=#Tp 1'b0;
write_ack <=#Tp 1'b0;
r_data_valid <=#Tp 1'b0;
w_data_valid <=#Tp 1'b0;
c_state <=#Tp `c_IDLE;
//init reg
en_m_clk <=#Tp 1'b0;
clk_m_cnt <=#Tp 9'd0;
keep_burst_len <=#Tp 9'd0;
end
else
begin
//for timing delay
if(en_m_clk)
clk_m_cnt <=#Tp clk_m_cnt+1'b1;
else
clk_m_cnt <=#Tp 9'd0;
//for state machine handle
case(c_state)
`c_IDLE:
begin
if(init_done && refresh_req) //refersh req
begin
c_state <=#Tp `c_AR;
refresh_ack <=#Tp 1'b1; //valid signal
en_m_clk <=#Tp 1'b0;
clk_m_cnt <=#Tp 9'd0;
end
//read or write req
else if(init_done && (read_req|write_req))
begin
c_state <=#Tp `c_RW_AR;
//sample the burst_len signal
keep_burst_len <=#Tp burst_len;
end
end
`c_AR:
begin
//refresh_ack值保持一个周期的有效时间
refresh_ack <=#Tp 1'b0; //invalid signal
en_m_clk <=#Tp 1'b1; //prepare for delay
clk_m_cnt <=#Tp 9'd0;
c_state <=#Tp `c_tRFC;
end
`c_tRFC:
begin
if(clk_m_cnt == NUM_CLK_tRFC) //if end of tRF delay
begin
en_m_clk <=#Tp 1'b0; //clear
clk_m_cnt <=#Tp 9'd0;
c_state <=#Tp `c_IDLE;
end
end
`c_RW_AR:
begin
c_state <=#Tp `c_RW_tRFC;
en_m_clk <=#Tp 1'b1; //prepare for delay
clk_m_cnt <=#Tp 9'd0;
end
`c_RW_tRFC:
begin
if(clk_m_cnt == NUM_CLK_tRFC) //if end of tRF delay
begin
en_m_clk <=#Tp 1'b0; //clear
clk_m_cnt <=#Tp 9'd0;
c_state <=#Tp `c_ACTIVE;
end
end
`c_ACTIVE:
begin
c_state <=#Tp `c_tRCD;
end
`c_tRCD:
begin
if(read_req)
begin
c_state <=#Tp `c_READ;
end
else if(write_req)
begin
c_state <=#Tp `c_WRITE;
w_data_valid<=#Tp 1'b1; //通知user可以改变数据了
end
end
//------------------cl=2-----read control-----------------------------
`c_READ:
begin
en_m_clk <=#Tp 1'b1; //prepare for delay
clk_m_cnt <=#Tp 9'd0;
c_state <=#Tp `c_RD_DATA;
end
`c_RD_DATA:
begin
if(clk_m_cnt==9'd1)
begin
r_data_valid <=#Tp 1'b1;
end
if( clk_m_cnt==(keep_burst_len-2))
begin
c_state <=#Tp `c_R_PRE;
en_m_clk <=#Tp 1'b0; //clear
clk_m_cnt <=#Tp 9'd0;
end
end
`c_R_PRE:
begin
c_state <=#Tp `c_R_tRP;
en_m_clk <=#Tp 1'b1;
clk_m_cnt <=#Tp 9'd0;
end
`c_R_tRP:
begin
if(clk_m_cnt== 9'd1)
begin
r_data_valid <=#Tp 1'b0;
read_ack <=#Tp 1'b1;
end
if(clk_m_cnt== (NUM_CLK_tRP+1) )
begin
en_m_clk <=#Tp 1'b0;
clk_m_cnt <=#Tp 9'd0;
read_ack <=#Tp 1'b0;
c_state <=#Tp `c_IDLE;
end
end
//---------------------------------write control-----------------------------
`c_WRITE:
begin
c_state <=#Tp `c_WR_DATA;
en_m_clk <=#Tp 1'b1; //prepare for delay
clk_m_cnt <=#Tp 9'd0;
end
`c_WR_DATA:
begin
if(clk_m_cnt==(keep_burst_len-2))
begin
en_m_clk <=#Tp 1'b0; //clear
clk_m_cnt <=#Tp 9'd0;
w_data_valid<=#Tp 1'b0; //invalid
c_state <=#Tp `c_W_PRE;
end
end
`c_W_PRE: //----------to terminate the busrt transmit
begin
en_m_clk <=#Tp 1'b1; //prepare for delay
clk_m_cnt <=#Tp 9'd0;
write_ack <=#Tp 1'b1; //产生写应答信号
c_state <=#Tp `c_W_tRP;
end
`c_W_tRP:
begin
write_ack <=#Tp 1'b0; //清除写应答信号
if(clk_m_cnt==NUM_CLK_tRP)
begin
en_m_clk <=#Tp 1'b0; //prepare for delay
clk_m_cnt <=#Tp 9'd0;
c_state <=#Tp `c_IDLE;
end
end
default:
begin
c_state <=#Tp `c_IDLE;
end
endcase
end
end
//-----------test code--------------------------------------------------
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -