SDRAM controller read模块
1、看下读SDRAM执行的的大体过程:
再次回顾以下SDRAM命令:注意NOTE部分(重要)!
回顾读相关时序:(不懂可以查看数据手册)
1、读数据有效延迟
2、读相关操作
a、连续进行Burst读
b、sigle读
读时序图:
写时序图:
记录一下调试过程:
写模块:
1、行地址为Z,报错;猜测原因应该是在给激活命令的时候ROW地址没和它在一个周期,具体时序可以查看手册;
2、在写数据过程中自刷新时间到进行自刷新,但是在208750ns的时候报错,bank0没有进行预充电,说明在自刷新之前,即写过程结束的时候没有进行预充电就跳转到了自刷新模块;
为了不改变原有的逻辑可以将标志打拍处理;代码如下:
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn) begin
write_req_r<=1'b0;
write_req <=1'b0;
end
else if (state==S_REQ)begin
write_req <=write_req_r;
write_req_r=1'b1;
end
else begin
write_req <=write_req_r;
write_req_r=1'b0;
end
end
结果如下:
3、接下来看到一行结束后并不能行地址没有改变;如图所示白色标注的两行在产生结束标志后没有行地址仍然为0;
读模块:
读进入自刷新状态:讲讲什么会出现这种状态。首先在读模块中退出读状态,进入预充电状态,看时序图由于DQ输出会有CAS_Latency的延迟,所以仿真信息才会又预充电指令后又两个数据输出;这个是在初始化模式寄存器进行配置的;
进入换行状态:读完第一行读第二行,precharge 和 active
结束状态:读完第二行结束
代码如下:这个代码写数据有点点问题,相信你只要理解了就会知道我在写数据给出的测试图哪个有问题,不建议阅读写数据代码,比较乱;
读代码进行了精简很好理解。多读几遍理解理解状态机。这是精华;
`timescale 1ns/1ns
module tb_sdram_top();
reg sclk;
reg s_rstn;
reg rd_trig;
wire sdram_clk;
wire sdram_cke;
wire sdram_cs_n;
wire sdram_cas_n;
wire sdram_ras_n;
wire sdram_we_n;
wire [1:0] sdram_bank;
wire [11:0] sdram_addr;
wire [1:0] sdram_dqm;
wire [15:0] sdram_dq;
reg wr_trig;
initial begin
sclk<=1;
s_rstn<=0;
#100;
s_rstn<=1;
end
always #10 sclk=~sclk;
initial begin
wr_trig=0;
#(10026*20) wr_trig=1;
#40 wr_trig=0;
#(10*20) wr_trig=1;
#(100*20) wr_trig=0;
end
initial begin
rd_trig=0;
#(12363*20) rd_trig=1;
#(10*20) rd_trig=0;
end
sdram_top sdram_top_inst1(
.sclk (sclk),
.s_rstn (s_rstn),
.sdram_clk (sdram_clk ),
.sdram_cke (sdram_cke ),
.sdram_cs_n (sdram_cs_n ),
.sdram_cas_n (sdram_cas_n ),
.sdram_ras_n (sdram_ras_n ),
.sdram_we_n (sdram_we_n ),
.sdram_bank (sdram_bank ),
.sdram_addr (sdram_addr ),
.sdram_dqm (sdram_dqm ),
.sdram_dq (sdram_dq ),
.wr_trig (wr_trig ),
.rd_trig (rd_trig )
);
sdram_model_plus sdram_model_plus_inst(
.Dq(sdram_dq),
.Addr(sdram_addr),
.Ba(sdram_bank),
.Clk(sdram_clk),
.Cke(sdram_cke ),
.Cs_n(sdram_cs_n ),
.Ras_n(sdram_ras_n ),
.Cas_n(sdram_cas_n ),
.We_n(sdram_we_n ),
.Dqm(sdram_dqm ),
.Debug(1'b1)
);
endmodule
module sdram_top(
input sclk,
input s_rstn,
//sdram_interface
output wire sdram_clk,
output wire sdram_cke,
output wire sdram_cs_n,
output wire sdram_cas_n,
output wire sdram_ras_n,
output wire sdram_we_n,
output reg [1:0] sdram_bank,
output reg [11:0] sdram_addr,
output wire [1:0] sdram_dqm,
inout reg [15:0] sdram_dq,
input wr_trig,
input rd_trig
);
localparam NOP=4'b0111;
localparam IDLE=5'b0_0001;
localparam ARBIT=5'b0_0010;
localparam AREF=5'b0_0100;
localparam WRITEDATA=5'b0_1000;
localparam READDATA=5'b1_0000;
zhoong cai shua xin mo kuai
reg [4:0] state,next_state;
wire ref_req;
reg ref_en;
wire flag_aref_end;
wire [3:0] ref_cmd;
wire [11:0] ref_addr;
wire flag_init_end;
wire [3:0] init_cmd;
wire [12:0] init_addr;
wire [3:0] write_cmd;
wire [12:0] wr_addr;
wire [1:0] wr_bank_addr;
wire [15:0]wr_data;
wire write_req;
wire write_end;
reg wr_en;
assign sdram_dqm=2'b00;
assign sdram_clk=~sclk;
assign sdram_cke=1;
//read
reg rd_en;
wire rd_req;
wire rd_end;
reg aref_req;
wire [3:0] rd_cmd;
wire [11:0] rd_addr;
wire [1:0] rd_bank_addr;
reg [15:0] rd_data;
//ZHONGCAI
always@(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
state<=IDLE;
else
state<=next_state;
end
always @(*) begin
case (state)
IDLE:begin
if(flag_init_end)
next_state=ARBIT;
else
next_state=IDLE;
end
ARBIT:begin
if(ref_req)
next_state=AREF;
else if (write_req) begin
next_state=WRITEDATA;
end
else if(rd_req) begin
next_state=READDATA;
end
else
next_state=ARBIT;
end
AREF:begin
if(flag_aref_end)
next_state=ARBIT;
else
next_state=AREF;
end
WRITEDATA:begin
//back_write_r=0;
if(write_end)
next_state=ARBIT;
else begin
next_state=WRITEDATA;
end
end
READDATA:begin
if(rd_end)
next_state=ARBIT;
else
next_state=READDATA;
end
default:next_state=IDLE;
endcase
end
//assign {sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n}= (state==IDLE)?init_cmd:ref_addr;
//assign {sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n}= init_cmd;
//assign sdram_addr=(state==IDLE)?init_addr:ref_addr;
//assign sdram_addr=init_addr;
reg sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r;
reg sdram_dq_en;
reg [15:0]sdram_dq1;
always @(*) begin
case (state)
IDLE:begin
{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= init_cmd;
sdram_addr=init_addr;
end
ARBIT:begin
sdram_addr = 12'd0;
{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= NOP;
end
AREF:begin
{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= ref_cmd;
sdram_addr=ref_addr;
end
WRITEDATA:begin
{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= write_cmd;
sdram_addr=wr_addr[11:0];
sdram_bank=rd_bank_addr;
sdram_dq1=wr_data;
end
READDATA:begin
{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= rd_cmd;
sdram_addr=rd_addr;
sdram_bank=rd_bank_addr;
rd_data=sdram_dq;
end
default:begin
end
endcase
end
assign sdram_dq=(state==WRITEDATA)?sdram_dq1:'hzzzz;
assign {sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n}={sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r};
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
ref_en<='b0;
else if(state ==AREF)
ref_en<='b1;
else
ref_en<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
wr_en<='b0;
else if(state==WRITEDATA && ref_req && write_end)
wr_en<='b0;
else if(state==WRITEDATA)
wr_en<='b1;
else
wr_en<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
rd_en<='b0;
else if(state==READDATA && ref_req && rd_end)begin
rd_en<='b0;
end
else if(state==READDATA)begin
rd_en<='b1;
end
end
sdram_init sdram_init_inst(
.sclk(sclk),
.s_rstn(s_rstn),
.cmd_reg(init_cmd),
.sdram_addr(init_addr),
.flag_init_end(flag_init_end)
);
sdram_aref sdram_aref_inst(
.sclk(sclk),
.s_rstn(s_rstn),
.ref_en(ref_en),
.ref_req(ref_req),
.flag_aref_end(flag_aref_end),
.aref_cmd(ref_cmd),
.sdram_addr(ref_addr),
.flag_init_end(flag_init_end)
);
sdram_write sdram_write_inst(
.sclk(sclk),
.s_rstn(s_rstn),
.wr_trig(wr_trig),
.wr_en(wr_en),
.write_req(write_req),
.write_end(write_end),
.aref_req(ref_req),
.write_cmd(write_cmd),
.wr_addr(wr_addr[11:0]),
.bank_addr(wr_bank_addr),
.wr_data(wr_data)
);
sdram_read sdram_read_inst(
.sclk(sclk),
.s_rstn(s_rstn),
.rd_trig(rd_trig),
.rd_en(rd_en),
.rd_req(rd_req),
.rd_end(rd_end),
.aref_req(ref_req),
.rd_cmd(rd_cmd),
.rd_addr(rd_addr),
.bank_addr(rd_bank_addr),
.rd_data(rd_data)
);
endmodule
module sdram_aref(
input sclk,
input s_rstn,
input ref_en,
output wire ref_req,
output wire flag_aref_end,
output reg [3:0] aref_cmd,
output wire [12:0] sdram_addr,
input flag_init_end
);
localparam DELAY_78US=390;
reg [3:0] cmd_cnt;
reg [9:0] ref_cnt;
reg flag_ref;
localparam cmd_aref=4'b0001;
localparam cmd_nop=4'b0111;
localparam cmd_pre=4'b0010;
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
ref_cnt<='b0;
else if(ref_cnt==DELAY_78US-1)
ref_cnt<='b0;
else if(flag_init_end)
ref_cnt<=ref_cnt+1'b1;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
flag_ref<='b0;
else if(flag_aref_end)
flag_ref<=1'b0;
else if(ref_en)
flag_ref<=1'b1;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
cmd_cnt<='b0;
else if(flag_ref)
cmd_cnt<=cmd_cnt+1'b1;
else
cmd_cnt<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
aref_cmd<=cmd_nop;
else if (flag_ref)begin
case(cmd_cnt)
1:aref_cmd<=cmd_pre;
2:aref_cmd<=cmd_aref;
7:aref_cmd<=cmd_aref;
default:aref_cmd<=cmd_nop;
endcase
end
else begin
aref_cmd<=cmd_nop;
end
end
reg ref_req_r;
assign sdram_addr=13'b0_0100_0000_0000;
//assign ref_req=(ref_cnt==DELAY_78US-1)?1'b1:'b0;
assign flag_aref_end=(cmd_cnt>='d9)?1'b1:1'b0;
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
ref_req_r<='b0;
else if(ref_req_r) begin
if(ref_en)
ref_req_r<='b0;
else
ref_req_r<=ref_req_r;
end
else if(ref_cnt==DELAY_78US-1)
ref_req_r<='b1;
else begin
ref_req_r<='b0;
end
end
assign ref_req=ref_req_r;
endmodule
module sdram_init (
input wire sclk,
input wire s_rstn,
output reg [3:0] cmd_reg,
output wire [12:0]sdram_addr,
output wire flag_init_end
);
//cs ras cas we
localparam DELAY_200US=10000;
localparam NOP=4'b0111;
localparam PREC=4'b0010;
localparam AREF=4'b0001;
localparam modset=4'b0000;
//localparam active=4'b1000;
reg [13:0] cnt_200us;
wire flag_200us;
reg [3:0] cnt_cmd;
//200us����
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
cnt_200us<='b0;
else if(~flag_200us)
cnt_200us<=cnt_200us+1'b1;
else if(flag_200us)
cnt_200us<=cnt_200us;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
cnt_cmd<='b0;
else if(flag_200us & ~flag_init_end)
cnt_cmd<=cnt_cmd+1'b1;
//else if(flag_init_end)
// cnt_cmd<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
cmd_reg<=NOP;
//else if(flag_200us && ~flag_init_end) begin
else if(flag_200us) begin
case(cnt_cmd)
'd0:cmd_reg<=PREC;//cmd_reg<=NOP;
'd1:cmd_reg<=AREF;
'd2:cmd_reg<=NOP;
'd5:cmd_reg<=AREF;
'd6:cmd_reg<=NOP;
'd10:cmd_reg<=modset;
//'d10:cmd_reg<=NOP;
//'d11:cmd_reg<=active;
default:cmd_reg<=NOP;
endcase
end
end
assign sdram_addr=(cmd_reg==modset)?13'b0_0000_0011_0010:13'b0_0100_0000_0000;
assign flag_init_end=(cnt_cmd>='d12)?1'b1:1'b0;
assign flag_200us=(cnt_200us>=DELAY_200US)?1'b1:1'b0;
endmodule
module sdram_read(
input sclk,
input s_rstn,
input rd_trig,
input rd_en,
output wire rd_req,
output wire rd_end,
input aref_req,
output reg [3:0] rd_cmd,
output reg [11:0] rd_addr,
output wire [1:0] bank_addr,
input [15:0] rd_data
);
reg [1:0] burst_cnt_r;
reg [4:0] current_state,next_state;
localparam S_IDLE=5'b01000;
localparam S_REQ =5'b1_0000;
localparam S_ACTIVE =5'b00001;
localparam S_READ =5'b00010;
localparam S_PRECHARGE =5'b00100;
//localparam S_ACTIVE =4'b1000;
//localparam S_ACTIVE =4'b0001;
localparam cmd_active=4'b0011;
localparam cmd_nop =4'b0111;
localparam cmd_read =4'b0101;
localparam cmd_precharge=4'b0010;
localparam cmd_autorefresh=4'b0001;
reg flag_row_end_r;
reg flag_read_end_r;
reg [8:0] col_address;
reg [11:0] row_address;
reg [1:0] col_cnt_r;
reg flag_row_end_r_r,flag_row_end_r_r1,flag_row_end_r_r2;
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
current_state<=S_IDLE;
else
current_state<=next_state;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
{flag_row_end_r_r,flag_row_end_r_r1,flag_row_end_r_r2}<='b0;
else begin
{flag_row_end_r_r2,flag_row_end_r_r1,flag_row_end_r_r}<={flag_row_end_r_r1,flag_row_end_r_r,flag_row_end_r};
end
end
always @(*) begin
case(current_state)
S_IDLE:begin
if(rd_trig)
next_state=S_REQ;
else
next_state=S_IDLE;
end
S_REQ:begin
if(rd_en)
next_state=S_ACTIVE;
else
next_state=S_REQ;
end
S_ACTIVE:begin
if(rd_cmd==cmd_active)
next_state=S_READ;
else
next_state=S_ACTIVE;
end
S_READ:begin
if((flag_read_end_r||flag_row_end_r_r)&& burst_cnt_r=='d3)
next_state=S_PRECHARGE;
else if(aref_req && burst_cnt_r=='d3)
next_state=S_PRECHARGE;
else begin
next_state=S_READ;
end
end
///
S_PRECHARGE:begin
if(flag_read_end_r)
next_state=S_IDLE;
else if(aref_req)begin
next_state=S_REQ;
end
else if(flag_row_end_r) begin
next_state=S_ACTIVE;
end
else begin
next_state=S_IDLE;
end
end
default:next_state=S_IDLE;
endcase
end
assign rd_req=(current_state==S_REQ);
assign rd_end=(current_state==S_PRECHARGE && ((aref_req==1'b1)||( rd_cmd==cmd_precharge && flag_read_end_r)));
assign bank_addr='b00;
// output reg [3:0] rd_cmd,
// output reg [11:0] rd_addr,
always @(*) begin
case(current_state)
S_IDLE:begin
rd_cmd=cmd_nop;
//rd_addr='b0;
end
S_REQ:begin
rd_cmd=cmd_nop;
//rd_addr='b0;
end
S_ACTIVE:begin
//rd_addr='b0;
if(rd_cmd==cmd_active)
rd_cmd=cmd_nop;
else begin
rd_cmd=cmd_active;
end
end
S_READ:begin
if(burst_cnt_r=='b0)
rd_cmd=cmd_read;
else begin
rd_cmd=cmd_nop;
end
end
///
S_PRECHARGE:begin
if(rd_cmd==cmd_precharge)
rd_cmd=cmd_nop;
else begin
rd_cmd=cmd_precharge;
end
end
default:rd_cmd=cmd_nop;
endcase
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
burst_cnt_r<='b0;
else if(current_state==S_READ) begin
if(burst_cnt_r=='d3)
burst_cnt_r<='b0;
else
burst_cnt_r<=burst_cnt_r+1'b1;
end
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn) begin
flag_read_end_r<='b0;
end
else if(col_cnt_r=='b1 && col_address=='d508 && burst_cnt_r=='d2)begin
flag_read_end_r<='b1;
end
else if(rd_cmd==cmd_precharge && flag_read_end_r==1'b1)
flag_read_end_r<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn) begin
col_cnt_r<='b0;
end
else if(flag_read_end_r)
col_cnt_r<='b0;
else if(flag_row_end_r)
col_cnt_r<='b1;
else begin
col_cnt_r<=col_cnt_r;
end
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn) begin
flag_row_end_r<='b0;
end
else if(col_address=='d508 && burst_cnt_r=='d3)begin
flag_row_end_r<='b1;
end
else if(rd_cmd==cmd_precharge && flag_row_end_r==1'b1)
flag_row_end_r<='b0;
end
always @(*) begin
case(current_state)
S_IDLE:begin
rd_addr<='b0;
end
S_REQ:begin
rd_addr<='b0;
end
S_ACTIVE:begin
//if(rd_addr==row_address)
// rd_addr<='b0;
//else
rd_addr<=row_address;
end
S_READ:begin
rd_addr<={3'b0,col_address};
end
///
S_PRECHARGE:begin
rd_addr<='b0100_0000_0000;
end
default:rd_addr<='b0000_0000_0000;
endcase
end
//reg [8:0] col_address;
//reg [11:0] row_address;
always @(posedge sclk or negedge s_rstn) begin
if (~s_rstn) begin
col_address<='d0;
end
else if(col_address=='d508 && current_state == S_READ && burst_cnt_r=='d1)
col_address<='d0;
else if(current_state == S_READ && burst_cnt_r=='d1)
col_address<=col_address+4'd4;
end
always @(posedge sclk or negedge s_rstn) begin
if (~s_rstn) begin
row_address<='d0;
end
else if(current_state == S_PRECHARGE && flag_row_end_r)
row_address=row_address+'d1;
end
endmodule
module sdram_write(
input sclk,
input s_rstn,
input wr_trig,
input wr_en,
output reg write_req,
output wire write_end,
input aref_req,
output reg [3:0] write_cmd,
output reg [12:0] wr_addr,
output wire [1:0] bank_addr,
output reg [15:0] wr_data
);
localparam cmd_active=4'b0011;
localparam cmd_nop =4'b0111;
localparam cmd_write =4'b0100;
localparam cmd_precharge=4'b0010;
localparam cmd_autorefresh=4'b0001;
//这里可以使用cmd_cnt计数,同初始化和自动刷新模块相似
//也可以使用状态机进行读时序操作,建议状态机,因为读操作
//可以转到其他操作状态,状态机就显得更加方便
localparam S_IDLE=5'b0_0001;
localparam S_REQ =5'b0_0010;
localparam S_ACTIVE =5'b0_0100;
localparam S_WRITE_S=5'b0_1000;
localparam S_PER = 5'b1_0000;
reg [4:0] state,next_state;
reg aref_req_r;
reg flag_act_end_r;
reg flag_data_end_r;
reg row_end_r;
reg [1:0] burst_cnt_r;
reg [12:0] row_addr;
reg [8:0] col_addr;
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
state<=S_IDLE;
else
state<=next_state;
end
always @(*) begin
case (state)
S_IDLE:begin
if(wr_trig)
next_state=S_REQ;
else
next_state=S_IDLE;
end
S_REQ:begin
if(wr_en)
next_state=S_ACTIVE;
else
next_state<=S_REQ;
end
S_ACTIVE:begin
if(state==S_ACTIVE && write_cmd==cmd_active)
next_state=S_WRITE_S;
else
next_state=S_ACTIVE;
end
S_WRITE_S:begin
//if(flag_data_end_r || row_end_r)
if(col_addr== 9'd508&&burst_cnt_r==2'd2)
next_state=S_PER;
else if(aref_req_r && burst_cnt_r==2'd2)
next_state=S_PER;
else
next_state=state;
end
S_PER:begin
if(flag_data_end_r)
next_state=S_IDLE;
else if(aref_req_r)
next_state=S_REQ;
else if(row_end_r)
next_state=S_ACTIVE;
else
next_state=S_IDLE;
end
default:next_state=S_IDLE;
endcase
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
flag_act_end_r<='b0;
else if(state==S_ACTIVE && write_cmd==cmd_active)
flag_act_end_r<='b1;
else
flag_act_end_r<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
flag_data_end_r<='b0;
else if(state==S_WRITE_S && row_addr==13'b1 && col_addr== 9'd508 && burst_cnt_r=='d3)
flag_data_end_r<='b1;
else if(state==S_IDLE)
flag_data_end_r<='b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
row_end_r<='b0;
else if(state==S_WRITE_S && col_addr== 9'd508 && burst_cnt_r=='d2)begin
row_end_r<=1'b1;
end
//else if(row_end_r==1'b1 && write_cmd==cmd_active )
else if(row_end_r)
row_end_r<=1'b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
aref_req_r<='b0;
else if(aref_req)begin
aref_req_r<=1'b1;
end
else if(state==S_PER && aref_req_r==1'b1)
aref_req_r<=1'b0;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
row_addr<='b0;
else if(row_end_r)begin
row_addr<=row_addr+'b1;
end
// end
// else if(state==S_ACTIVE && row_end_r=='b0 &&write_cmd==cmd_nop)
// row_addr<=row_addr+'d1;
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
col_addr<='b0;
else if(state==S_WRITE_S && wr_addr[9:0]=='d508&& burst_cnt_r=='d2)
col_addr<=1'b0;
else if(state==S_WRITE_S && burst_cnt_r=='d2)begin
col_addr<=col_addr+'d4;
end
end
always @(posedge sclk or negedge s_rstn) begin
if(!s_rstn)
burst_cnt_r<='d2;
else if(state==S_WRITE_S && burst_cnt_r=='d3)
burst_cnt_r<='d0;
else if(state==S_WRITE_S && flag_act_end_r)
burst_cnt_r<='d0;
else if(state==S_WRITE_S)
burst_cnt_r<=burst_cnt_r+1'b1;
else
burst_cnt_r<='b0;
end
//always @(*) begin
// case(state)
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
wr_addr<=13'b0_0000_0000_0000;
else case(state)
S_IDLE:begin
wr_addr<=13'b0_0000_0000_0000;
end
S_REQ:begin
wr_addr<='b0_0000_0000_0000;
end
S_ACTIVE:begin
if(write_cmd==cmd_active)
wr_addr<=13'b0_0000_0000_0000;
else
wr_addr<=row_addr;
end
S_WRITE_S:begin
/*if(burst_cnt_r=='b11)
wr_addr<={3'b000,col_addr};
else begin
wr_addr<=13'b0_0000_0000_0000;
end*/
wr_addr<={3'b000,col_addr};
end
S_PER:begin
wr_addr<=13'b0_0100_0000_0000;
end
default:wr_addr<=13'b0_0000_0000_0000;
endcase
end
assign bank_addr='b00;
assign write_end=(state==S_PER)&&(flag_data_end_r ||aref_req_r);
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
write_cmd<=cmd_nop;
else case(state)
S_IDLE:begin
write_cmd<=cmd_nop;
end
S_REQ:begin
write_cmd<=cmd_nop;
end
S_ACTIVE:begin
if(write_cmd!=cmd_active)
write_cmd<=cmd_active;
else
write_cmd<=cmd_nop;
end
S_WRITE_S:begin
if(burst_cnt_r=='d3 || flag_act_end_r)
write_cmd<=cmd_write;
else begin
write_cmd<=cmd_nop;
end
end
S_PER:begin
write_cmd<=cmd_precharge;
end
default:write_cmd<=cmd_nop;
endcase
end
reg write_req_r;
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn) begin
write_req_r<=1'b0;
write_req <=1'b0;
end
else if (state==S_REQ)begin
write_req <=write_req_r;
//write_req <=1'b1;
write_req_r=1'b1;
end
else begin
write_req <=write_req_r;
//write_req <=1'b0;
write_req_r=1'b0;
end
end
always @(posedge sclk or negedge s_rstn) begin
if(~s_rstn)
wr_data<='b0;
else if(state==S_WRITE_S)
wr_data<=wr_data+1;
else
wr_data<=wr_data;
end
endmodule