项目可以拓展的地方:
1、接口为AXI
2、接口为AXI与AXI DMA 交互
2、优化读写时序,使得SDRAM输出效率最大;
总结:
项目不足:没有进行效率的优化,无地址映射,无外接交互接口,功能单一;
注意:读写模块和自刷新模块的跳转时候数据的输出与输入是否有效进入FIFO中(建议把FIFO中的数据看一遍,不能只看物理模型的端口数据),
总体框图:

实现功能:读写256个数据
步骤:
1、给写入信号,FIFO中数据满256后进行一次读操作,
2、读信号,当读FIFO中能够储存数据大于256个就进行读,这里其实有个BUG:就是当我写模块没有进行数据写入时,也会进行数据的读取,这里其实可以给写模块一个计数器,写一次加一,读模块读一次减一,这个计数器在同一个时钟域下工作;
3:读FIFO的输出信号有个ready信号,为高时告诉主机我FIFO里存储了256个数据,这时可以发出中断,或者标志寄存器置1;
写操作:

读操作:

测试我只放我认为重要的图片
测试:
读FIFO;216us的时候读FIFO数据不连续,是sdram进入自刷新模式,注意输出数据的处理怎样才能保持连续;


最后说说自己的测试点:
1、连续写,写读写读,写读同时写;
翻啊翻,啊卧槽啊,又出现bug了,受不了了
写的时候自刷新144-147没写进去,看看读是不是为0就知道了;

果然出现BUG了

解决它:
原因:写状态的时候,进入自刷新之前需要进入ARBIT状态,如黄线这时state还写状态,发出写使能,只需要修改下写使能代码即可;
bug图:

代码修改前:

修改后:

正确图:


上代码:
`timescale 1ns/1nsmodule 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;reg wfifo_wr_clk;
reg wfifo_wr_en;
reg [15:0] wfifo_wr_data;reg rfifo_rd_clk;
reg rfifo_rd_en;wire [15:0] rfifo_rd_data;
wire rd_ready;initial beginsclk<=1;wfifo_wr_clk=1;rfifo_rd_clk=1;s_rstn<=0;#100;s_rstn<=1;
end
always #10 sclk=~sclk;always #15 wfifo_wr_clk=~wfifo_wr_clk;always #15 rfifo_rd_clk=~rfifo_rd_clk;initial begin//wr_trig=0;wfifo_wr_data=0;wfifo_wr_en=0;rfifo_rd_en=0;//#(10026*20)#(10040*20) wfifo_wr_en=1;#(30*300) wfifo_wr_en=0;rfifo_rd_en=1;#(30*300) wfifo_wr_en=1;rfifo_rd_en=0;//#(300*300) wfifo_wr_en=0;
endalways @(posedge wfifo_wr_clk)if(wfifo_wr_en)wfifo_wr_data<=wfifo_wr_data+1'b1;
initial beginend
/*
initial beginrd_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 ),.wfifo_wr_clk(wfifo_wr_clk),.wfifo_wr_en(wfifo_wr_en),.wfifo_wr_data(wfifo_wr_data),.rfifo_rd_clk(rfifo_rd_clk),.rfifo_rd_en(rfifo_rd_en),.rfifo_rd_data(rfifo_rd_data),.rd_ready(rd_ready));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_interfaceoutput 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 wfifo_wr_clk,input wfifo_wr_en,input [15:0] wfifo_wr_data,input rfifo_rd_clk,input rfifo_rd_en,output wire [15:0] rfifo_rd_data,output wire rd_ready);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 [11: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;
wire [15:0] rd_data;wire wr_trig;
wire rd_trig;
wire [15:0] rfifo_wr_data;
wire [15:0] wfifo_rd_data;reg write_end_r2,write_end_r1;//ZHONGCAI
always@(posedge sclk or negedge s_rstn) beginif(~s_rstn)state<=IDLE;elsestate<=next_state;
endalways @(*) begincase (state) IDLE:beginif(flag_init_end)next_state=ARBIT;elsenext_state=IDLE;endARBIT:beginif(ref_req)next_state=AREF;else if (write_req) beginnext_state=WRITEDATA;endelse if(rd_req) beginnext_state=READDATA;endelsenext_state=ARBIT;endAREF:beginif(flag_aref_end)next_state=ARBIT;elsenext_state=AREF;endWRITEDATA:begin//back_write_r=0;if(write_end_r2)next_state=ARBIT;else beginnext_state=WRITEDATA;endendREADDATA:beginif(rd_end)next_state=ARBIT;else next_state=READDATA;enddefault:next_state=IDLE;endcase
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn){write_end_r2,write_end_r1}<='b0;else begin{write_end_r2,write_end_r1}<={write_end_r1,write_end};endend//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 @(*) begincase (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;endARBIT:beginsdram_addr = 12'd0;{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= NOP; endAREF:begin{sdram_cs_n_r,sdram_ras_n_r,sdram_cas_n_r,sdram_we_n_r}= ref_cmd;sdram_addr=ref_addr;endWRITEDATA: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;endREADDATA: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;enddefault:begin endendcase
end
assign sdram_dq=(state==WRITEDATA)?sdram_dq1:'hzzzz;//assign rd_data=(state==READDATA || state==IDLE)?sdram_dq:'b0;
assign rd_data=sdram_dq;
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) beginif(~s_rstn)ref_en<='b0;else if(state ==AREF)ref_en<='b1;else ref_en<='b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)wr_en<='b0;else if(state==WRITEDATA && write_end)wr_en<='b0;else if(state==WRITEDATA && next_state==WRITEDATA)wr_en<='b1;elsewr_en<='b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)rd_en<='b0;else if(state==READDATA && ref_req && rd_end)beginrd_en<='b0;endelse if(state==READDATA)beginrd_en<='b1;endelse beginrd_en<='b0;end
endsdram_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),.wfifo_rd_data(wfifo_rd_data),.wfifo_rd_en(wfifo_rd_en)
);sdram_read sdram_read_inst(.sclk(sclk),.s_rstn(s_rstn),.rd_trig(rd_trig),//.rd_trig(1'b0),.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),.rfifo_wr_data(rfifo_wr_data),.rfifo_wr_en(rfifo_wr_en)
);sdram_auto_write_read #(.data_width(16),.data_depth(512),.addr_width(9),.read_width(16),.WFIFO_RD_CNT(256),.RFIFO_WR_CNT(256)
)sdram_auto_write_read_inst1
(. s_rstn(s_rstn),//wfifo//write.wfifo_wr_clk(wfifo_wr_clk),.wfifo_wr_en(wfifo_wr_en),.wfifo_wr_data(wfifo_wr_data),//read.wfifo_rd_clk(sclk),.wfifo_rd_en(wfifo_rd_en),.wfifo_rd_data(wfifo_rd_data),.wfifo_out_full_w(),.wfifo_out_empty_w(),.wfifo_out_wrfifo_rd_cnt(),//写fifo,能最少读256个计数标志.wfifo_out_rdfifo_wr_cnt(), //读fifo,能最少写256个计数标志.wr_trig(wr_trig),//rdfifo //write.rfifo_wr_clk(sclk),.rfifo_wr_en(rfifo_wr_en),.rfifo_wr_data(rfifo_wr_data),////read.rfifo_rd_clk(rfifo_rd_clk),.rfifo_rd_en(rfifo_rd_en),.rfifo_rd_data(rfifo_rd_data),.rfifo_out_full_w(),.rfifo_out_empty_w(),.rfifo_out_wrfifo_rd_cnt(),//写fifo,能最少读256个计数标志.rfifo_out_rdfifo_wr_cnt(), //读fifo,能最少写256个计数标志.rd_trig(rd_trig), //告诉主机我写入了256个数据可以进行读取了.rd_ready(rd_ready)
);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) beginif(~s_rstn)cnt_200us<='b0;else if(~flag_200us)cnt_200us<=cnt_200us+1'b1;else if(flag_200us)cnt_200us<=cnt_200us;
endalways @(posedge sclk or negedge s_rstn) beginif(~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;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)cmd_reg<=NOP;//else if(flag_200us && ~flag_init_end) beginelse if(flag_200us) begincase(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;endcaseend
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_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) beginif(~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;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)flag_ref<='b0;else if(flag_aref_end)flag_ref<=1'b0;else if(ref_en)flag_ref<=1'b1;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)cmd_cnt<='b0;else if(flag_ref)cmd_cnt<=cmd_cnt+1'b1;else cmd_cnt<='b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)aref_cmd<=cmd_nop;else if (flag_ref)begincase(cmd_cnt)1:aref_cmd<=cmd_pre;2:aref_cmd<=cmd_aref;7:aref_cmd<=cmd_aref;default:aref_cmd<=cmd_nop;endcaseendelse beginaref_cmd<=cmd_nop;end
endreg 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) beginif(~s_rstn)ref_req_r<='b0;else if(ref_req_r) beginif(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 beginref_req_r<='b0;end
end
assign ref_req=ref_req_r;endmodule
//假设FIFO深度不是2的n次幂,但要满足时4的倍数
//这里设计为深度28,利用格雷码的对称性,则格雷码转换的时候需要加32-28=4个地址
//module async_fifo #(parameter data_width = 16,parameter data_depth = 28,parameter addr_width = 5,parameter read_width = 16,parameter WFIFO_RD_CNT = 256 ,parameter RFIFO_WR_CNT = 256
)
(input s_rstn,//writeinput wr_clk,input wr_en,input [data_width-1:0] wr_data,//readinput rd_clk,input rd_en,output reg [read_width-1:0] rd_data,output wire out_full_w,output wire out_empty_w,output reg out_wrfifo_rd_cnt,//写fifo,能读出256个计数标志output reg out_rdfifo_wr_cnt //读fifo,能写进256个计数标志);reg [addr_width:0] wr_address;
reg [addr_width:0] rd_address;
reg [addr_width:0] gray_wr_address;
reg [addr_width:0] gray_rd_address;
reg [addr_width:0] g2b_r2w;
reg [addr_width:0] g2b_w2r;reg [addr_width:0] async_w2r_r2,async_w2r_r1;
reg [addr_width:0] async_r2w_r2,async_r2w_r1;always @(posedge rd_clk or negedge s_rstn) beginif(~s_rstn) beginrd_address<='d0;endelse if (rd_en && ~out_empty_w) beginif(rd_address=='d511)rd_address<='d0;else rd_address<=rd_address+1'b1;end
end
always @(posedge wr_clk or negedge s_rstn) beginif(~s_rstn) beginwr_address<='d0;endelse if (wr_en && ~out_full_w) beginif(wr_address=='d511)wr_address<='d0;else wr_address<=wr_address+1'b1;end
end
always @(posedge wr_clk ) begingray_wr_address<=(wr_address) ^ ((wr_address)>>1);
end
always @(posedge rd_clk) begingray_rd_address<=(rd_address) ^ ((rd_address)>>1);
endalways @(posedge rd_clk or negedge s_rstn) beginif(~s_rstn) begin{async_w2r_r2,async_w2r_r1}<='b0;endelse begin{async_w2r_r2,async_w2r_r1}<={async_w2r_r1,gray_wr_address};end
endalways @(posedge wr_clk or negedge s_rstn) beginif(~s_rstn) begin{async_r2w_r2,async_r2w_r1}<='b0;endelse begin{async_r2w_r2,async_r2w_r1}<={async_r2w_r1,gray_rd_address};end
end//full and empty signal sheng chengassign out_empty_w=(async_w2r_r2==gray_rd_address);integer i;
always @(*) beginfor(i=0;i<=addr_width;i=i+1) g2b_r2w[i]=^(async_r2w_r2>>i);
endinteger j;
always @(*) beginfor(j=0;j<=addr_width;j=j+1) g2b_w2r[j]=^(async_w2r_r2>>j);
endassign out_full_w=((g2b_r2w+'d510)==wr_address)||((g2b_r2w-'d510)==wr_address);reg [data_width-1:0] register1 [data_depth-1:0];always @(posedge rd_clk) beginif (rd_en && ~out_empty_w) beginif(rd_address[addr_width]==1) //判断高位是否为1,为一直接截取就可以,为0则要减去相应的数值rd_data<=register1[rd_address[addr_width-1:0]];//直接截取低位就可以else beginrd_data<=register1[rd_address[addr_width-1:0]-'d0];endend
endalways @(posedge wr_clk ) beginif (wr_en && ~out_full_w) beginif(wr_address[addr_width])register1[wr_address[addr_width-1:0]]<=wr_data;else beginregister1[wr_address[addr_width-1:0]-'d0]<=wr_data;endend
end//g2b_r2w
//g2b_w2ralways @(posedge rd_clk or negedge s_rstn) beginif(~s_rstn)out_wrfifo_rd_cnt<=1'b0;else if(~g2b_w2r[addr_width] & rd_address[addr_width])out_wrfifo_rd_cnt<=((g2b_w2r+{addr_width{1'b1}}-rd_address)>=WFIFO_RD_CNT)?1'b1:1'b0;elseout_wrfifo_rd_cnt<=((g2b_w2r-rd_address)>=WFIFO_RD_CNT)?1'b1:1'b0;
endalways @(posedge wr_clk or negedge s_rstn) beginif(~s_rstn)out_rdfifo_wr_cnt<=1'b1;else if(~wr_address[addr_width] & g2b_r2w[addr_width])out_rdfifo_wr_cnt<=((data_depth-(wr_address+{addr_width{1'b1}}-g2b_r2w))>=RFIFO_WR_CNT)?1'b1:1'b0;elseout_rdfifo_wr_cnt<=((data_depth-(wr_address-g2b_r2w))>=RFIFO_WR_CNT)?1'b1:1'b0;
endendmodule
module sdram_write(input sclk,input s_rstn,input wr_trig,input wr_en,output reg write_req,output reg write_end,input aref_req,output reg [3:0] write_cmd,output reg [12:0] wr_addr,output wire [1:0] bank_addr,output wire [15:0] wr_data,input [15:0] wfifo_rd_data,output wire wfifo_rd_en
);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;parameter WROW_ADDR_END = 937 ;
parameter WCOL_MADDR_END = 256 ;always @(posedge sclk or negedge s_rstn) beginif(~s_rstn)state<=S_IDLE;elsestate<=next_state;
endalways @(*) begincase (state)S_IDLE:beginif(wr_trig)next_state=S_REQ;elsenext_state=S_IDLE;endS_REQ:beginif(wr_en)next_state=S_ACTIVE;elsenext_state<=S_REQ;endS_ACTIVE:beginif(state==S_ACTIVE && write_cmd==cmd_active)next_state=S_WRITE_S;elsenext_state=S_ACTIVE;endS_WRITE_S:beginif(col_addr== (WCOL_MADDR_END-'d4)&&burst_cnt_r==2'd2)next_state=S_PER; else if(aref_req_r && burst_cnt_r==2'd2)next_state=S_PER;elsenext_state=state;endS_PER:beginif(flag_data_end_r && write_cmd==cmd_precharge)next_state=S_IDLE;else if(aref_req_r && write_cmd==cmd_precharge)next_state=S_REQ;else if(row_end_r && write_cmd==cmd_precharge)next_state=S_ACTIVE;else next_state=S_PER;enddefault:next_state=S_IDLE;endcase
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)flag_act_end_r<='b0;else if(state==S_ACTIVE && write_cmd==cmd_active)flag_act_end_r<='b1;elseflag_act_end_r<='b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)flag_data_end_r<='b0;else if(state==S_WRITE_S && col_addr== (WCOL_MADDR_END-'d4) && burst_cnt_r=='d2)flag_data_end_r<='b1;else if(state==S_IDLE)flag_data_end_r<='b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)row_end_r<='b0;else if(state==S_WRITE_S && col_addr== (WCOL_MADDR_END-'d4) && burst_cnt_r=='d2)beginrow_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;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)aref_req_r<='b0;else if(aref_req && wr_en)beginaref_req_r<=1'b1;endelse if(write_cmd==cmd_precharge && state==S_PER && aref_req_r==1'b1)aref_req_r<=1'b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)row_addr<='b0;//else if(flag_data_end_r )beginelse if(row_end_r && row_addr==(WROW_ADDR_END-'d1)) beginrow_addr<='b0;endelse if(row_end_r)beginrow_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) beginif(~s_rstn)col_addr<='b0;else if(state==S_WRITE_S && wr_addr[9:0]==(WCOL_MADDR_END-'d4)&& burst_cnt_r=='d2)col_addr<=1'b0;else if(state==S_WRITE_S && burst_cnt_r=='d2)begincol_addr<=col_addr+'d4;endendalways @(posedge sclk or negedge s_rstn) beginif(!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;elseburst_cnt_r<='b0;
end//always @(*) begin// case(state)
always @(posedge sclk or negedge s_rstn) beginif(~s_rstn)wr_addr<=13'b0_0000_0000_0000;else case(state)S_IDLE:beginwr_addr<=13'b0_0000_0000_0000;endS_REQ:beginwr_addr<='b0_0000_0000_0000;endS_ACTIVE:beginif(write_cmd==cmd_active)wr_addr<=13'b0_0000_0000_0000;elsewr_addr<=row_addr;endS_WRITE_S:begin/*if(burst_cnt_r=='b11)wr_addr<={3'b000,col_addr};else beginwr_addr<=13'b0_0000_0000_0000;end*/wr_addr<={3'b000,col_addr};endS_PER:beginwr_addr<=13'b0_0100_0000_0000;enddefault:wr_addr<=13'b0_0000_0000_0000;endcase
endassign bank_addr='b00;wire write_end_w;
assign write_end_w=(state==S_PER)&&(flag_data_end_r ||aref_req_r);
always@(posedge sclk ) write_end<=write_end_w;always @(posedge sclk or negedge s_rstn) beginif(~s_rstn)write_cmd<=cmd_nop;else case(state)S_IDLE:beginwrite_cmd<=cmd_nop;endS_REQ:beginwrite_cmd<=cmd_nop;endS_ACTIVE:beginif(write_cmd!=cmd_active)write_cmd<=cmd_active; elsewrite_cmd<=cmd_nop;endS_WRITE_S:beginif(burst_cnt_r=='d3 || flag_act_end_r)write_cmd<=cmd_write;else beginwrite_cmd<=cmd_nop;endendS_PER:beginif(write_cmd==cmd_precharge)write_cmd<=cmd_nop;elsewrite_cmd<=cmd_precharge;enddefault:write_cmd<=cmd_nop;endcase
endreg write_req_r;always @(posedge sclk or negedge s_rstn) beginif(~s_rstn) beginwrite_req_r<=1'b0;write_req <=1'b0;endelse if (state==S_REQ)begin//write_req <=write_req_r;write_req <=1'b1;write_req_r=1'b1;endelse begin//write_req <=write_req_r;write_req <=1'b0;write_req_r=1'b0; end
end
/*
always @(posedge sclk or negedge s_rstn) beginif(~s_rstn)wr_data<='b0;else if(state==S_WRITE_S ||next_state==S_WRITE_S)wr_data<=wfifo_rd_data;elsewr_data<=wr_data;
end*///assign wr_data=(state==S_WRITE_S)?wfifo_rd_data:'b0;
assign wr_data=wfifo_rd_data;
/*
always @(posedge sclk or negedge s_rstn) beginif(~s_rstn)wfifo_rd_en<=1'b0;else if(state==S_WRITE_S)wfifo_rd_en<=1'b1;
end*/assign wfifo_rd_en=(state==S_WRITE_S)?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,output [15:0] rfifo_wr_data,output wire rfifo_wr_en
);
parameter RROW_ADDR_END =937;
parameter RCOL_ADDR_END =256;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) beginif(~s_rstn)current_state<=S_IDLE;elsecurrent_state<=next_state;
endalways @(posedge sclk or negedge s_rstn) beginif(~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
endalways @(*) begincase(current_state)S_IDLE:beginif(rd_trig)next_state=S_REQ;elsenext_state=S_IDLE;endS_REQ:beginif(rd_en)next_state=S_ACTIVE;elsenext_state=S_REQ;endS_ACTIVE:beginif(rd_cmd==cmd_active)next_state=S_READ;elsenext_state=S_ACTIVE;endS_READ:beginif((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 beginnext_state=S_READ;endend///S_PRECHARGE:beginif(flag_read_end_r)next_state=S_IDLE;else if(aref_req && rd_cmd==cmd_precharge)begin next_state=S_REQ;endelse if(flag_row_end_r) beginnext_state=S_ACTIVE;endelse beginnext_state=S_IDLE;endenddefault:next_state=S_IDLE;endcase
endassign 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 @(*) begincase(current_state)S_IDLE:beginrd_cmd=cmd_nop;//rd_addr='b0;endS_REQ:beginrd_cmd=cmd_nop;//rd_addr='b0; endS_ACTIVE:begin//rd_addr='b0; if(rd_cmd==cmd_active)rd_cmd=cmd_nop;else beginrd_cmd=cmd_active;endendS_READ:beginif(burst_cnt_r=='b0)rd_cmd=cmd_read;else beginrd_cmd=cmd_nop;endend///S_PRECHARGE:beginif(rd_cmd==cmd_precharge)rd_cmd=cmd_nop;else beginrd_cmd=cmd_precharge;endenddefault:rd_cmd=cmd_nop;endcase
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn)burst_cnt_r<='b0;else if(current_state==S_READ) beginif(burst_cnt_r=='d3)burst_cnt_r<='b0;elseburst_cnt_r<=burst_cnt_r+1'b1;end
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn) beginflag_read_end_r<='b0;end//else if(col_cnt_r=='b1 && col_address=='d508 && burst_cnt_r=='d0)begin//else if(col_cnt_r=='b1 && col_address==(RCOL_ADDR_END-'d4) && burst_cnt_r=='d0)beginelse if( col_address==(RCOL_ADDR_END-'d4) && burst_cnt_r=='d0)beginflag_read_end_r<='b1;endelse if(rd_cmd==cmd_precharge && flag_read_end_r==1'b1)flag_read_end_r<='b0;
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn) begincol_cnt_r<='b0;endelse if(flag_read_end_r)col_cnt_r<='b0;else if(flag_row_end_r)col_cnt_r<='b1;else begincol_cnt_r<=col_cnt_r; end
endalways @(posedge sclk or negedge s_rstn) beginif(~s_rstn) beginflag_row_end_r<='b0;endelse if(col_address=='d508 && burst_cnt_r=='d3)beginflag_row_end_r<='b1;endelse if(rd_cmd==cmd_precharge && flag_row_end_r==1'b1)flag_row_end_r<='b0;elseflag_row_end_r<=flag_row_end_r;
endalways @(*) begincase(current_state)S_IDLE:beginrd_addr<='b0;endS_REQ:beginrd_addr<='b0;endS_ACTIVE:beginrd_addr<=row_address;endS_READ:beginrd_addr<={3'b0,col_address};end///S_PRECHARGE:begin rd_addr<='b0100_0000_0000;enddefault:rd_addr<='b0000_0000_0000;endcase
end//reg [8:0] col_address;
//reg [11:0] row_address;
always @(posedge sclk or negedge s_rstn) beginif (~s_rstn) begincol_address<='d0; endelse if((col_address=='d508 ||col_address==RCOL_ADDR_END-'d4)&& 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;
endalways @(posedge sclk or negedge s_rstn) beginif (~s_rstn) beginrow_address<='d0; endelse if(row_address==(RROW_ADDR_END-1'd1) &¤t_state == S_PRECHARGE && flag_row_end_r)row_address<='d0;else if(current_state == S_PRECHARGE && (flag_row_end_r||flag_read_end_r))row_address<=row_address+'d1;else beginrow_address<=row_address;endendreg [7:0] rfifo_wr_en_cnt;
//rfifo_wr_en
wire rfifo_wr_en_w;
reg rfifo_wr_en_r,rfifo_wr_en_r1;/*
always @(posedge sclk or negedge s_rstn) beginif (~s_rstn) beginrfifo_wr_en_r<='d0; endelse if(current_state == S_PRECHARGE && rd_cmd==cmd_precharge)rfifo_wr_en_r<='d0;else if(current_state == S_READ && burst_cnt_r==1'b1)rfifo_wr_en_r<='d1;else beginrfifo_wr_en_r<=rfifo_wr_en;end
end*/
assign rfifo_wr_en_w=(current_state == S_READ)?1'b1:1'b0;always @(posedge sclk or negedge s_rstn) beginif(~s_rstn){rfifo_wr_en_r1,rfifo_wr_en_r}<='b0; else begin{rfifo_wr_en_r1,rfifo_wr_en_r}<={rfifo_wr_en_r,rfifo_wr_en_w};end
endassign rfifo_wr_en=rfifo_wr_en_r1;assign rfifo_wr_data=rd_data;endmodule















