写模块跟着视频看了一个多星期,一开始始终有点弄不清楚,现在记录一下理解的过程。
阅读文档信息:
首先阅读文档信息,了解SDRAM写过程的状态转换和时序图
SDRAM整体状态流程如图所示:
在SDRAM整体系统中,若要进入写模块,则需要从idle状态首先激活一行(row_acttive),再进入写状态(write),发送precharge命令跳出写状态。
WRITEA 状态不使用,因为当处于 WRITEA 状态时,它会自动的进入到 Precharge 状态。想要继续进行写操作就要先再次激活行,也就是说 WRITEA 比在 WRITE 状态的工作效率要低很多。
SDRAM写模块时序图如图所示:
观察时序图可知,在发送active命令时同时发送A0-A12,BANK信息,其中A0-A12指定了行信息,也就是说在ACT命令(激活状态)下,确定了要写入数据的行(SDRAM的数据是一行一行的写),BANK命令确定了要写入数据的SDRAM的块。也就是说在ACT命令下已经确定了bank和row;经过tRCD(至少20ns)时间后,再能发送write命令,发送write命令的同时也发送col命令(col命令也通过A0-A9发送,此时A10为低电平),也同时发送bank命令和数据。设置突发长度为4,等待4个周期的时间写入数据,才可以进行precharge命令退出写模式。
SDRAM写模块状态如图所示(写模块内部状态转移,与SDRAM整体的状态无关):
dle,w_req状态承接上下部分,接收到来自顶层模块的写触发信号(w_trig)后,由idle状态到w_req,此时w_req状态向顶层模块发送req信号,接收到写使能(w_en )信号后进入到act状态,此时也接收到row地址和bank地址信息。由时序图可知经过20ns后进入write状态。在write状态下,当数据写完或者刷新时间到的时候或者指定的行数据写完的时候,需要跳出write状态,此时进入pre状态。在pre状态下,数据写完进入idle状态;当刷新请求来的时候要进行刷新,在顶层模块的设计下刷新结束后会进入仲裁模块,此时需要重新发送写请求,接收到写使能;在指定的一行写完后需要重新激活,此时不需要外部的写使能信号再传输进来。
写模块代码如下:
其中burst_cnt用来计数突发长度,write->pre状态,break_cnt用来计数从pre->act状态(至少20ns)
module sdram_wirte(
input sclk ,
input srst ,
//communicate with top
input w_en ,
output wire w_req ,
output reg flag_w_end ,
//
input ref_req ,
input w_trig ,
//write interface
output reg [3:0] w_cmd ,
output reg [11:0] w_addr ,
output wire [1:0] bank_addr,
output reg [15:0] w_data
);
//==========================================================
//======= define parameter and internal signal ========
//==========================================================
//define state
localparam s_idle = 5'b00001;
localparam s_req = 5'b00010;
localparam s_act = 5'b00100;
localparam s_wr = 5'b01000;
localparam s_pre = 5'b10000;
//
localparam cmd_nop = 5'b0111;
localparam cmd_pre = 5'b0010;
localparam cmd_ref = 5'b0001;
localparam cmd_act = 5'b0011;
localparam cmd_wr = 5'b0100;
reg flag_wr;
reg[4:0] state;
reg flag_act_end;
reg flag_pre_end;
reg sd_row_end;
reg[1:0] burst_cnt;
reg[1:0] burst_cnt_t;
reg wr_data_end;
reg[3:0] act_cnt;
reg[3:0] break_cnt;
reg[6:0] col_cnt;
reg[11:0] row_addr;
wire[8:0] col_addr;
//==========================================================
//==================== main code ====================
//========