Figure 1uses an 8Mx8, 125-MHz SDRAM, but this technique works with any SDRAM.

Figure 2a), the data bus is inactive during the initial portion of the cycle (when the row and column addresses are presented), so there's no problem with using the data bus to carry address data. A precharge command ends the burst and prepares the RAM for the next access.

Figure 2b). Normally, the first byte of write data is presented to the SDRAM with the Write command, along with the starting column address for that burst. By asserting the DQM (data-mask) signal, the SDRAM ignores the data lines during this phase, thus allowing them to be used for the column address.

Note that the DQM signal does not prevent the internal column address from incrementing, however. Thus, the write-column address presented with the Write command must be one less than the desired burst starting address. For FIFO designs, this requirement is trivial because you can initialize the write-address column counter to –1 rather than 0. The column-address counter in the SDRAM wraps around at the end of the column, so this approach works even at the beginning of a column.

download a simplified version of a FIFO controller that uses this technique, described in the Verilog language. The listing omits some of the details, such as SDRAM refresh/init cycles, and FIFO flags, to highlight the portions relevant to this design. This controller uses a simple eight-state finite-state machine to generate the SDRAM control signals and uses a pair of row/column counters to keep track of the FIFO put/get pointers. The special initialization and incrementing of the write row and column pointers satisfies the requirement that the write column start off one behind the desired write address. The code occupies 35% of a small Xilinx SpartanXL-S10 device, and runs at 50 MHz. For the sake of example, all of the outputs are combinatorial, but a true high-speed design should use registered I/O.

10 because this line has special meaning during some SDRAM commands. You can also use this technique with double-data-rate SDRAMs.

 

SDRAM interface slashes pin count

 

SDRAM interface slashes pin count

 

;*********************************************************************************
; di2659.txt
;
; LISTING 1 - FIFO CONTROLLER
;
; "SDRAM interface slashes pin count," EDN, March 29, 2001, pg 132
; http://www.ednmag.com/ednmag/reg/2001/03292001/designideas.htm#07di4
;*********************************************************************************

`timescale 1 ns / 1 ns

/*
** Minimal-pin SDRAM controller with FIFO address counters.  This 
** has a simple do_write/wr_ok, do_read/rd_ok handshake for data input & 
** output.  The 'rst_fifo' signal syncronously resets the fifo
**
** Author: Tim Hellman, M&M Consulting
*/
module sdctl(clk, reset_,

        rst_fifo, do_write, do_read, wr_data_in,   /* Fifo I/O */
        wr_ok, rd_ok, rd_data_out,

        sd_ras_, sd_cas_, sd_we_, sd_dqm, sd_bank,  /* SDRAM signals */
        sd_addr_hi, sd_data
        );

 input clk, reset_, do_write, do_read, rst_fifo;
 input [7:0] wr_data_in;
 
 output wr_ok, rd_ok, sd_ras_, sd_cas_, sd_we_, sd_dqm;
 output [7:0] rd_data_out;
 output [1:0] sd_bank;
 output [11:8] sd_addr_hi;

 inout [7:0] sd_data;

 /*
 ** States
 */
 parameter StIdle = 0, StActive = 1, StRdWr = 2, StData1 = 3,
       StData2 = 4, StData3 = 5, StRdPrech = 6, StWrPrech = 7;

 reg [2:0] State;
 reg [13:0] RdRow, WrRow;
 reg [8:2] RdCol, WrCol;
 reg sd_data_ena, doing_write;

 always @(posedge clk or negedge reset_)
   if (!reset_) begin
     RdRow <= 0;  WrRow <= 0; RdCol <= 0; WrCol <= 7'h7f;
     sd_data_ena <= 0; State <= StIdle; doing_write <= 0;
   end
   else begin

     /*
     ** State machine.  Once kicked off, run through all states
     */
     if (State == StIdle && (do_write | do_read)) begin
        doing_write <= #1 do_write;
        State <= #1 State + 1;
     end
     else if (State != StIdle) State <= #1 State + 1;

     /*
     ** Read/write counters (note that write col counter starts 
     ** one behind read).  The Write row also increments when 
     ** WrCol == '7e (because WrCol is always one behind)
     */
     if (rst_fifo) {RdRow,RdCol} <= #1 0;
     else if (State == StWrPrech && !doing_write) 
                  {RdRow,RdCol} <= #1 {RdRow,RdCol} + 1;

     if (rst_fifo) WrCol <= #1 7'h7f;
     else if (State == StWrPrech && doing_write) WrCol <= #1 WrCol + 1;

     if (rst_fifo) WrRow <= #1 0;
     else if (State == StWrPrech && doing_write && WrCol == 7'h7e) 
                WrRow <= #1 WrRow + 1;

     if (State == StIdle && (do_read | do_write)) sd_data_ena <= #1 1;
     else if (doing_write && (State == StRdPrech) 
          || !doing_write && (State == StRdWr))   sd_data_ena <= #1 0;

   end

   /*
   ** Generate the SDRAM 'command' bits (combinatorially)
   */
   reg [2:0] SdCmd;
   always @(State or doing_write) begin
     case (State) 
       StActive: SdCmd = 3;
       StRdWr: SdCmd = doing_write ? 4 : 5;
       StRdPrech: SdCmd = doing_write ? 7 : 2;
       StWrPrech: SdCmd = doing_write ? 2 : 7;
       default: SdCmd = 7;  // NOP
     endcase
   end
   assign {sd_ras_, sd_cas_, sd_we_} = SdCmd;

   /*
   ** Data output is either address or data 
   */
   wire [8:0] ColAddr  = doing_write ? {WrCol, 2'b11} : {RdCol, 2'b00};
   wire [13:0] RowAddr = doing_write ? WrRow : RdRow;

   assign wr_ok = (State >= StData1 && State <= StRdPrech) &  doing_write;
   assign rd_ok = (State >= StData2 && State <= StWrPrech) & !doing_write;

   /* Upper bits of column. address must equal 0 */
   wire [11:0] MuxAddr = (State == StActive) ? RowAddr : {3'b0,ColAddr};

   assign sd_bank = RowAddr[13:12];
   assign sd_addr_hi = MuxAddr[11:8];
   wire [7:0] DataOut = (State == StActive || State == StRdWr) ?
             MuxAddr[7:0] : wr_data_in;

   assign sd_data = sd_data_ena ? DataOut : 'hz;
   assign rd_data_out = sd_data;
 
   assign sd_dqm = doing_write ? (State == StRdWr | State == StWrPrech) :
                                 (State == StRdPrech);

endmodule

 

相关文章:

  • 2022-12-23
  • 2022-01-10
  • 2022-01-18
  • 2021-06-19
  • 2021-06-14
  • 2021-05-01
  • 2021-07-31
猜你喜欢
  • 2022-12-23
  • 2021-12-03
  • 2021-07-31
  • 2022-01-04
  • 2021-06-18
  • 2021-08-30
  • 2022-03-04
相关资源
相似解决方案