首页 > 代码库 > Sdram控制器
Sdram控制器
/* desctription: this module implement the sdr_sdram timing. the author:lufy yin(wuqingjianke) */
`timescale 1ns/1ps
module sdram_io #(parameter DataWidth = 16, AddrWidth = 12, ColAddrWidth = 8, Clock_Frequecy = 125000000) ( input clk, input rst_n, input mode_valid, input[AddrWidth-1:0] mode, input autofresh, input[ColAddrWidth:0] burst_len, input wr, input rd, input[1:0] bankaddr, input[AddrWidth-1:0] rowaddr, input[ColAddrWidth-1:0] coladdr, input[DataWidth-1:0] wr_data, output reg wr_data_req, output reg rd_data_valid, output reg[DataWidth-1:0] rd_data, output reg wr_ack, output reg rd_ack, output reg fresh_ack, output reg init_done, //sdram IO output reg sdr_clk, output reg sdr_cke, output reg[1:0] sdr_BA, output reg[AddrWidth-1:0] sdr_A, output [1:0] sdr_dqm, output sdr_ncs, output sdr_nras, output sdr_ncas, output sdr_nwe, inout[DataWidth-1 : 0] sdr_D );
localparam Time100us = Clock_Frequecy/100000;
localparam NOP = 4‘b0111; localparam PRECHARGE = 4‘b0010; localparam AUTO_FRESH = 4‘b0001; localparam LMR = 4‘b0000; localparam ACT = 4‘b0011; localparam WRI = 4‘b0100; localparam REA = 4‘b0101;
localparam tINIT = 17; //2*tRFC+tRP localparam tFRESH = 21; localparam tMRD = 3; localparam tRP = 3; //Precharge time tRP+1 localparam tRFC = 7; //AutoFresh time tRFC+1 localparam tRCD = 3; //active time tRCD+1 localparam tWR = 3; //write recover time tWR+1
localparam sdr_idle = 4‘d0, sdr_init = 4‘d1, sdr_lmr = 4‘d2, sdr_ctrl = 4‘d3, sdr_fresh = 4‘d4, sdr_write = 4‘d5, sdr_read = 4‘d6;
reg[3:0] sdr_state; reg[DataWidth-1:0] databuf; reg tri_en; reg[3:0] sdr_cmd;
reg[AddrWidth-1:0] modebuf; reg[23:0] timecnt; reg[ColAddrWidth : 0] cmd_cnt;
wire[ColAddrWidth : 0] wr_time; wire[ColAddrWidth : 0] rd_time; reg[7:0] tCL; wire[7:0] tdataout; wire[ColAddrWidth:0] tdataover;
reg data_out_en;
assign sdr_dqm = 2‘b00; assign sdr_D = tri_en ? databuf : ‘hz; assign sdr_ncs = sdr_cmd[3]; assign sdr_nras = sdr_cmd[2]; assign sdr_ncas = sdr_cmd[1]; assign sdr_nwe = sdr_cmd[0]; assign wr_time = tRCD + burst_len + tRP + tWR; assign rd_time = tRCD + burst_len+tCL+tRP; //tRCD + rdatanum+tRP+tCL+2; assign tdataout = tRCD + tCL; assign tdataover = tRCD + burst_len + tCL;
always@(posedge clk or negedge rst_n) begin if(~rst_n) modebuf <= 0; else if(mode_valid) modebuf <= mode; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) tCL <= 8‘d0; else if(mode_valid) tCL <= {6‘d0,mode[5:4]}; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) timecnt <= 24‘d0; else if(init_done) timecnt <= 24‘d0; else timecnt <= timecnt + 24‘d1; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) init_done <= 1‘b0; else if(timecnt==Time100us) init_done <= 1‘b1; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) sdr_cke <= 1‘b0; else if(timecnt==Time100us-10) sdr_cke <= 1‘b1; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) cmd_cnt <= 0; else case(sdr_state) sdr_init: begin if(cmd_cnt==tINIT) cmd_cnt <= 0; else cmd_cnt <= cmd_cnt + 1; end sdr_lmr: begin if(cmd_cnt==tMRD) cmd_cnt <= 0; else cmd_cnt <= cmd_cnt + 1; end sdr_fresh: begin if(cmd_cnt==tFRESH) cmd_cnt <= 0; else cmd_cnt <= cmd_cnt + 1; end sdr_write: begin if(cmd_cnt==wr_time) cmd_cnt <= 0; else cmd_cnt <= cmd_cnt + 1; end sdr_read: begin if (cmd_cnt == rd_time) cmd_cnt <= 0; else cmd_cnt <= cmd_cnt + 1; end default: cmd_cnt <= 0; endcase end always@(posedge clk or negedge rst_n) begin if(~rst_n) sdr_state <= sdr_idle; else case(sdr_state) sdr_idle: begin if(init_done) sdr_state <= sdr_init; end sdr_init: begin if(cmd_cnt==tINIT) sdr_state <= sdr_lmr; end sdr_lmr: begin if(cmd_cnt==tMRD) sdr_state <= sdr_ctrl; end sdr_ctrl: begin if(autofresh) sdr_state <= sdr_fresh; else if(wr) sdr_state <= sdr_write; else if(rd) sdr_state <= sdr_read; end sdr_fresh: begin if(cmd_cnt==tFRESH) sdr_state <= sdr_ctrl; end sdr_write: begin if(cmd_cnt==wr_time) sdr_state <= sdr_ctrl; end sdr_read: begin if(cmd_cnt==rd_time) sdr_state <= sdr_ctrl; end default:sdr_state <= sdr_idle; endcase end
always@(posedge clk or negedge rst_n) begin if(~rst_n) sdr_cmd <= NOP; else case(sdr_state) sdr_idle: sdr_cmd <= NOP; sdr_init: begin if(cmd_cnt==0) sdr_cmd <= PRECHARGE; else if(cmd_cnt==tRP) sdr_cmd <= AUTO_FRESH; else if(cmd_cnt==tRP+tRFC) sdr_cmd <= AUTO_FRESH; else sdr_cmd <= NOP; end sdr_lmr: begin if(cmd_cnt==0) sdr_cmd <= LMR; else sdr_cmd <= NOP; end sdr_ctrl: sdr_cmd <= NOP; sdr_fresh: begin if(cmd_cnt==0) sdr_cmd <= PRECHARGE; else if(cmd_cnt==tRP) sdr_cmd <= AUTO_FRESH; else if(cmd_cnt==tRP+tRFC) sdr_cmd <= AUTO_FRESH; else sdr_cmd <= NOP; end sdr_write: begin if(cmd_cnt==0) sdr_cmd <= ACT; else if(cmd_cnt>=tRCD && cmd_cnt<tRCD+burst_len) sdr_cmd <= WRI; else if(cmd_cnt==tRCD+burst_len+tWR) sdr_cmd <= PRECHARGE; else //if(cmd_cnt==tRCD+burst_len) sdr_cmd <= NOP; end sdr_read: begin if(cmd_cnt==0) sdr_cmd <= ACT; else if(cmd_cnt>=tRCD && cmd_cnt<tRCD+burst_len) sdr_cmd <= REA; else if(cmd_cnt==tRCD+burst_len) sdr_cmd <= PRECHARGE; else sdr_cmd <= NOP; end default:sdr_cmd <= NOP; endcase end
always@(posedge clk or negedge rst_n) begin if(~rst_n) sdr_BA <= 2‘b00; else if(sdr_state==sdr_write || sdr_state==sdr_read) sdr_BA <= bankaddr; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) sdr_A <= 0; else case(sdr_state) sdr_init: sdr_A[10] <= 1‘b1; sdr_lmr: sdr_A <= modebuf; sdr_fresh: sdr_A[10] <= 1‘b1; sdr_write: begin if(cmd_cnt==0) sdr_A <= rowaddr; else if(cmd_cnt==tRCD) sdr_A <= {4‘b0000,coladdr}; else if(cmd_cnt>tRCD && cmd_cnt <tRCD + burst_len) sdr_A <= sdr_A + 1; end sdr_read: begin if(cmd_cnt==0) sdr_A <= rowaddr; else if(cmd_cnt==tRCD) sdr_A <= {4‘b0000,coladdr}; else if(cmd_cnt>tRCD && cmd_cnt < tRCD + burst_len) sdr_A <= sdr_A + 1; end default:sdr_A <= 0; endcase end
always@(posedge clk or negedge rst_n) begin if(~rst_n) rd_data <= 0; else rd_data <= sdr_D; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) tri_en <= 1‘b0; else if(sdr_state==sdr_write) // begin // if(cmd_cnt>= tRCD && cmd_cnt < tRCD + burst_len) tri_en <= 1‘b1; // end else tri_en <= 1‘b0; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) data_out_en <= 1‘b0; else if(sdr_state==sdr_read) begin if(cmd_cnt>= tdataout && cmd_cnt <tdataover) //if(cmd_cnt>tdataout && cmd_cnt <= tdataover) data_out_en <= 1‘b1; else data_out_en <= 1‘b0; end else data_out_en <= 1‘b0; end always@(posedge clk or negedge rst_n) begin if(~rst_n) rd_data_valid <= 1‘b0; else rd_data_valid <= data_out_en; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) databuf <= 0; else if(sdr_state==sdr_write) begin if(cmd_cnt>= tRCD && cmd_cnt < tRCD + burst_len) databuf <= wr_data; end end
always@(posedge clk or negedge rst_n) begin if(~rst_n) wr_ack <= 1‘b0; else if(sdr_state==sdr_write) begin if(cmd_cnt==wr_time-1) wr_ack <= 1‘b1; else wr_ack <= 1‘b0; end else wr_ack <= 1‘b0; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) rd_ack <= 1‘b0; else if(sdr_state==sdr_read) begin if(cmd_cnt==rd_time-1) rd_ack <= 1‘b1; else rd_ack <= 1‘b0; end end
always@(posedge clk or negedge rst_n) begin if(~rst_n) fresh_ack <= 1‘b0; else if(sdr_state==sdr_fresh) begin if(cmd_cnt==tFRESH-1) fresh_ack <= 1‘b1; else fresh_ack <= 1‘b0; end else fresh_ack <= 1‘b0; end
always@(posedge clk or negedge rst_n) begin if(~rst_n) wr_data_req <= 1‘b0; else if(sdr_state==sdr_write) begin if(cmd_cnt>=tRCD-2 && cmd_cnt<tRCD+burst_len-2) wr_data_req <= 1‘b1; else wr_data_req <= 1‘b0; end end
endmodule
Sdram控制器