首页 > 代码库 > 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控制器