SDRAM controller read and write 读写模块

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
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值