`timescale 1ns/1ns module sdram_test_tb; reg clk; reg rst; reg start_read; initial begin clk = 0; rst = 0; start_read = 0; #100 rst = 1; #1000 start_read = 1; #100000 $stop; end always #10 clk = !clk; reg [10:0] cnt; always @ (posedge clk or negedge start_read) if(!start_read) cnt else cnt wire r_req = (cnt == 10'd200); //写sdram申请 wire s_req = (cnt == 10'd600); //读sdram申请 // State parameters used in MAIN STATE MACHINE parameter IDLE =21'b0_0000_0000_0000_0000_0001, PRECHARGE =21'b0_0000_0000_0000_0000_0010, PRECHARGE_ACK =21'b0_0000_0000_0000_0000_0100, LOAD_MR =21'b0_0000_0000_0000_0000_1000, LOAD_MR_ACK =21'b0_0000_0000_0000_0001_0000, LOAD_R2 =21'b0_0000_0000_0000_0010_0000, LOAD_R2_ACK =21'b0_0000_0000_0000_0100_0000, LOAD_R1 =21'b0_0000_0000_0000_1000_0000, IDLE_WR =21'b0_0000_0000_0001_0000_0000, PAGE_WRITE =21'b0_0000_0000_0010_0000_0000, BURST_WRITE =21'b0_0000_0000_0100_0000_0000, BT_W =21'b0_0000_0000_1000_0000_0000, WAIT_ACK_W_T =21'b0_0000_0001_0000_0000_0000, PAGE_READ =21'b0_0000_0010_0000_0000_0000, BURST_READ =21'b0_0000_0100_0000_0000_0000, BT =21'b0_0000_1000_0000_0000_0000, LAST_DATA =21'b0_0001_0000_0000_0000_0000, CLOSE_PAGE_W =21'b0_0010_0000_0000_0000_0000, REFRESH_W =21'b0_0100_0000_0000_0000_0000, CLOSE_PAGE_R =21'b0_1000_0000_0000_0000_0000, REFRESH_R =21'b1_0000_0000_0000_0000_0000; parameter RCD='D3,CL='D3,BL='d223;//BL控制每行sdram中有效字数 reg s_enable,r_enable_1,r_enable_2; reg [20:0] STATE; reg [10:0] w_page; reg [7:0] Burst_cnt; reg [1:0] RCDCL_CNT; wire r_enable = r_enable_1|r_enable_2; //与写入sdram中的有效数据对齐 wire [31:0] datain = r_enable ? {20'd0,cnt}:32'dx; //需要写入到sdram中的数据 wire [31:0] dataout; //从sdram中读出的数据 reg [2:0] cmd; reg [20:0] addr; reg STATE12_reg,STATE16_reg,STATE8_reg,STATE19_reg; always @ (posedge clk) begin STATE12_reg STATE16_reg STATE8_reg STATE19_reg r_enable_2 end parameter NOP ='b000, READA ='b001, WRITEA ='b010, ARF ='b011, PRECHRG ='b100, LOAD_MODE ='b101, LOAD_REG1 ='b110, LOAD_REG2 ='b111; //generate the cmd to the sdr_sdram_controller always @ (STATE) case(STATE) PRECHARGE: cmd = PRECHRG; LOAD_MR: cmd = LOAD_MODE; LOAD_R2: cmd = LOAD_REG2; LOAD_R1: cmd = LOAD_REG1; PAGE_WRITE: cmd = WRITEA; BT_W: cmd = PRECHRG; CLOSE_PAGE_W: cmd = PRECHRG; CLOSE_PAGE_R: cmd = PRECHRG; PAGE_READ: cmd = READA; BT: cmd = PRECHRG; REFRESH_W: cmd = ARF; REFRESH_R: cmd = ARF; default: cmd = NOP; endcase //*****************************************************************************// //*****************************************************************************// always @ (posedge clk or negedge rst) if(!rst) w_page else if(STATE12_reg) w_page else if(STATE8_reg && (w_page=='d1))// w_page reg w_ba0; always @ (posedge clk or negedge rst) if(!rst) w_ba0 else if(STATE8_reg && (w_page=='d1))// w_ba0 wire [1:0] w_ba = {1'b0,w_ba0}; //****************************************************************************// //****************************************************************************// wire cmdack; reg [10:0] r_page; reg r_ba0; always @ (posedge clk or negedge rst) if(!rst) begin r_ba0 end else if(STATE[20] & cmdack) begin r_ba0 end always @ (posedge clk or negedge rst) if(!rst) begin r_page end else if(STATE16_reg) begin r_page end else if(STATE8_reg) begin r_page end wire [1:0] r_ba = {1'b0,r_ba0}; //********************************************************************************// //********************************************************************************// //the state machine always @(posedge clk or negedge rst) begin if(!rst) begin STATE s_enable r_enable_1 RCDCL_CNT Burst_cnt end else case(STATE) IDLE: if(start_read) STATE else STATE PRECHARGE: if(cmdack) STATE else STATE PRECHARGE_ACK: STATE LOAD_MR: if(cmdack) STATE else STATE LOAD_MR_ACK: STATE LOAD_R2: if(cmdack) STATE else STATE LOAD_R2_ACK: STATE LOAD_R1: if(cmdack) STATE else STATE //page write burst IDLE_WR: begin //9 if(r_req) begin STATE end else if( s_req && (w_ba0 != r_ba0)) begin STATE end else STATE end PAGE_WRITE: //10 if(cmdack) begin STATE Burst_cnt r_enable_1 end else STATE BURST_WRITE: begin if(Burst_cnt==(BL-2'd3)) STATE else STATE Burst_cnt end BT_W:begin if(cmdack) STATE else STATE r_enable_1 end WAIT_ACK_W_T:begin STATE end //CLOSE CURRENT PAGE CLOSE_PAGE_W:begin if(cmdack) STATE else STATE end REFRESH_W: begin if(cmdack) begin STATE end else STATE end //PAGE READ BURST TEST PAGE_READ:begin if(cmdack) STATE else STATE Burst_cnt RCDCL_CNT end BURST_READ:begin if(Burst_cnt==('d6)) s_enable else if(Burst_cnt==(BL-2'd3))//+RCD+CL STATE else STATE Burst_cnt end BT: if(cmdack) STATE else STATE LAST_DATA: STATE CLOSE_PAGE_R:begin if(cmdack) STATE else STATE if(RCDCL_CNT=='d2) s_enable else RCDCL_CNT end REFRESH_R:begin if(cmdack)begin STATE end else STATE end default: STATE endcase end //generate the addr to the sdr_sdram_controller always @ (STATE or w_page or r_page or r_ba or w_ba) case(STATE) PRECHARGE: addr = 'h1f0000; LOAD_MR: addr = 'h37; LOAD_R2: addr = 'h5F6; LOAD_R1: addr = 'h12F; //'h10f PAGE_WRITE: addr = {w_ba,w_page,8'b0};//PAGE_WRITE PAGE_READ: addr = {r_ba,r_page,8'b0}; BT_W: addr = {w_ba,19'b0}; CLOSE_PAGE_W: addr = {w_ba,19'b0}; CLOSE_PAGE_R: addr = {r_ba,19'b0}; BT: addr = {r_ba,19'b0}; default: addr = 'h0; endcase wire [10:0] sa; wire [1:0] ba; wire [31:0] dq; sdr_sdram sdr_sdram0( .CLK(clk), .RESET_N(rst), .ADDR(addr), .CMD(cmd), .CMDACK(cmdack), .DATAIN(datain), .DATAOUT(dataout), .SA(sa), .BA(ba), .CS_N(cs_n), .CKE(cke), .RAS_N(ras_n), .CAS_N(cas_n), .WE_N(we_n), .DQ(dq) ); mt48lc2m32b2 sdram1( .Dq (dq) , .Addr (sa) , .Ba (ba) , .Clk (clk) , .Cke (cke) , .Cs_n (cs_n) , .Ras_n (ras_n), .Cas_n (cas_n), .We_n (we_n) , .Dqm (4'b0) ); endmodule