www.pudn.com > multiprocessor.rar > sdram.v


//Legal Notice: (C)2007 Altera Corporation. All rights reserved.  Your 
//use of Altera Corporation's design tools, logic functions and other 
//software and tools, and its AMPP partner logic functions, and any 
//output files any of the foregoing (including device programming or 
//simulation files), and any associated documentation or information are 
//expressly subject to the terms and conditions of the Altera Program 
//License Subscription Agreement or other applicable license agreement, 
//including, without limitation, that your use is for the sole purpose 
//of programming logic devices manufactured by Altera and sold by Altera 
//or its authorized distributors.  Please refer to the applicable 
//agreement for further details. 
 
// synthesis translate_off 
`timescale 1ns / 1ps 
// synthesis translate_on 
 
// turn off superfluous verilog processor warnings  
// altera message_level Level1  
// altera message_off 10034 10035 10036 10037 10230 10240 10030  
 
module sdram_input_efifo_module ( 
                                  // inputs: 
                                   clk, 
                                   rd, 
                                   reset_n, 
                                   wr, 
                                   wr_data, 
 
                                  // outputs: 
                                   almost_empty, 
                                   almost_full, 
                                   empty, 
                                   full, 
                                   rd_data 
                                ) 
; 
 
  output           almost_empty; 
  output           almost_full; 
  output           empty; 
  output           full; 
  output  [ 40: 0] rd_data; 
  input            clk; 
  input            rd; 
  input            reset_n; 
  input            wr; 
  input   [ 40: 0] wr_data; 
 
  wire             almost_empty; 
  wire             almost_full; 
  wire             empty; 
  reg     [  1: 0] entries; 
  reg     [ 40: 0] entry_0; 
  reg     [ 40: 0] entry_1; 
  wire             full; 
  reg              rd_address; 
  reg     [ 40: 0] rd_data; 
  wire    [  1: 0] rdwr; 
  reg              wr_address; 
  assign rdwr = {rd, wr}; 
  assign full = entries == 2; 
  assign almost_full = entries >= 1; 
  assign empty = entries == 0; 
  assign almost_empty = entries <= 1; 
  always @(entry_0 or entry_1 or rd_address) 
    begin 
      case (rd_address) // synthesis parallel_case full_case 
       
          1'd0: begin 
              rd_data <= entry_0; 
          end // 1'd0  
       
          1'd1: begin 
              rd_data <= entry_1; 
          end // 1'd1  
       
          default: begin 
          end // default 
       
      endcase // rd_address 
    end 
 
 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
        begin 
          wr_address <= 0; 
          rd_address <= 0; 
          entries <= 0; 
        end 
      else  
        case (rdwr) // synthesis parallel_case full_case 
         
            2'd1: begin 
                // Write data 
                if (!full) 
                  begin 
                    entries <= entries + 1; 
                    wr_address <= (wr_address == 1) ? 0 : (wr_address + 1); 
                  end 
            end // 2'd1  
         
            2'd2: begin 
                // Read data 
                if (!empty) 
                  begin 
                    entries <= entries - 1; 
                    rd_address <= (rd_address == 1) ? 0 : (rd_address + 1); 
                  end 
            end // 2'd2  
         
            2'd3: begin 
                wr_address <= (wr_address == 1) ? 0 : (wr_address + 1); 
                rd_address <= (rd_address == 1) ? 0 : (rd_address + 1); 
            end // 2'd3  
         
            default: begin 
            end // default 
         
        endcase // rdwr 
    end 
 
 
  always @(posedge clk) 
    begin 
      //Write data 
      if (wr & !full) 
          case (wr_address) // synthesis parallel_case full_case 
           
              1'd0: begin 
                  entry_0 <= wr_data; 
              end // 1'd0  
           
              1'd1: begin 
                  entry_1 <= wr_data; 
              end // 1'd1  
           
              default: begin 
              end // default 
           
          endcase // wr_address 
    end 
 
 
 
endmodule 
 
 
 
// turn off superfluous verilog processor warnings  
// altera message_level Level1  
// altera message_off 10034 10035 10036 10037 10230 10240 10030  
 
module sdram ( 
               // inputs: 
                az_addr, 
                az_be_n, 
                az_cs, 
                az_data, 
                az_rd_n, 
                az_wr_n, 
                clk, 
                reset_n, 
 
               // outputs: 
                za_data, 
                za_valid, 
                za_waitrequest, 
                zs_addr, 
                zs_ba, 
                zs_cas_n, 
                zs_cke, 
                zs_cs_n, 
                zs_dq, 
                zs_dqm, 
                zs_ras_n, 
                zs_we_n 
             ) 
; 
 
  output  [ 15: 0] za_data; 
  output           za_valid; 
  output           za_waitrequest; 
  output  [ 11: 0] zs_addr; 
  output  [  1: 0] zs_ba; 
  output           zs_cas_n; 
  output           zs_cke; 
  output           zs_cs_n; 
  inout   [ 15: 0] zs_dq; 
  output  [  1: 0] zs_dqm; 
  output           zs_ras_n; 
  output           zs_we_n; 
  input   [ 21: 0] az_addr; 
  input   [  1: 0] az_be_n; 
  input            az_cs; 
  input   [ 15: 0] az_data; 
  input            az_rd_n; 
  input            az_wr_n; 
  input            clk; 
  input            reset_n; 
 
  wire    [ 23: 0] CODE; 
  reg              ack_refresh_request; 
  reg     [ 21: 0] active_addr; 
  wire    [  1: 0] active_bank; 
  reg              active_cs_n; 
  reg     [ 15: 0] active_data; 
  reg     [  1: 0] active_dqm; 
  reg              active_rnw; 
  wire             almost_empty; 
  wire             almost_full; 
  wire             bank_match; 
  wire    [  7: 0] cas_addr; 
  wire             clk_en; 
  wire    [  3: 0] cmd_all; 
  wire    [  2: 0] cmd_code; 
  wire             cs_n; 
  wire             csn_decode; 
  wire             csn_match; 
  wire    [ 21: 0] f_addr; 
  wire    [  1: 0] f_bank; 
  wire             f_cs_n; 
  wire    [ 15: 0] f_data; 
  wire    [  1: 0] f_dqm; 
  wire             f_empty; 
  reg              f_pop; 
  wire             f_rnw; 
  wire             f_select; 
  wire    [ 40: 0] fifo_read_data; 
  reg     [ 11: 0] i_addr; 
  reg     [  3: 0] i_cmd; 
  reg     [  2: 0] i_count; 
  reg     [  2: 0] i_next; 
  reg     [  2: 0] i_refs; 
  reg     [  2: 0] i_state; 
  reg              init_done; 
  reg     [ 11: 0] m_addr /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON"  */; 
  reg     [  1: 0] m_bank /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON"  */; 
  reg     [  3: 0] m_cmd /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON"  */; 
  reg     [  2: 0] m_count; 
  reg     [ 15: 0] m_data /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON ; FAST_OUTPUT_ENABLE_REGISTER=ON"  */; 
  reg     [  1: 0] m_dqm /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON"  */; 
  reg     [  8: 0] m_next; 
  reg     [  8: 0] m_state; 
  reg              oe /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_ENABLE_REGISTER=ON"  */; 
  wire             pending; 
  wire             rd_strobe; 
  reg     [  2: 0] rd_valid; 
  reg     [ 12: 0] refresh_counter; 
  reg              refresh_request; 
  wire             rnw_match; 
  wire             row_match; 
  wire    [ 23: 0] txt_code; 
  reg              za_cannotrefresh; 
  reg     [ 15: 0] za_data /* synthesis ALTERA_ATTRIBUTE = "FAST_INPUT_REGISTER=ON"  */; 
  reg              za_valid; 
  wire             za_waitrequest; 
  wire    [ 11: 0] zs_addr; 
  wire    [  1: 0] zs_ba; 
  wire             zs_cas_n; 
  wire             zs_cke; 
  wire             zs_cs_n; 
  wire    [ 15: 0] zs_dq; 
  wire    [  1: 0] zs_dqm; 
  wire             zs_ras_n; 
  wire             zs_we_n; 
  assign clk_en = 1; 
  //s1, which is an e_avalon_slave 
  assign {zs_cs_n, zs_ras_n, zs_cas_n, zs_we_n} = m_cmd; 
  assign zs_addr = m_addr; 
  assign zs_cke = clk_en; 
  assign zs_dq = oe?m_data:{16{1'bz}}; 
  assign zs_dqm = m_dqm; 
  assign zs_ba = m_bank; 
  assign f_select = f_pop & pending; 
  assign f_cs_n = 1'b0; 
  assign cs_n = f_select ? f_cs_n : active_cs_n; 
  assign csn_decode = cs_n; 
  assign {f_rnw, f_addr, f_dqm, f_data} = fifo_read_data; 
  sdram_input_efifo_module the_sdram_input_efifo_module 
    ( 
      .almost_empty (almost_empty), 
      .almost_full  (almost_full), 
      .clk          (clk), 
      .empty        (f_empty), 
      .full         (za_waitrequest), 
      .rd           (f_select), 
      .rd_data      (fifo_read_data), 
      .reset_n      (reset_n), 
      .wr           ((~az_wr_n | ~az_rd_n) & !za_waitrequest), 
      .wr_data      ({az_wr_n, az_addr, az_wr_n ? 2'b0 : az_be_n, az_data}) 
    ); 
 
  assign f_bank = {f_addr[21],f_addr[8]}; 
  // Refresh/init counter. 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          refresh_counter <= 5000; 
      else if (refresh_counter == 0) 
          refresh_counter <= 781; 
      else  
        refresh_counter <= refresh_counter - 1'b1; 
    end 
 
 
  // Refresh request signal. 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          refresh_request <= 0; 
      else if (1) 
          refresh_request <= ((refresh_counter == 0) | refresh_request) & ~ack_refresh_request & init_done; 
    end 
 
 
  // Generate an Interrupt if two ref_reqs occur before one ack_refresh_request 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          za_cannotrefresh <= 0; 
      else if (1) 
          za_cannotrefresh <= (refresh_counter == 0) & refresh_request; 
    end 
 
 
  // Initialization-done flag. 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          init_done <= 0; 
      else if (1) 
          init_done <= init_done | (i_state == 3'b101); 
    end 
 
 
  // **** Init FSM **** 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
        begin 
          i_state <= 3'b000; 
          i_next <= 3'b000; 
          i_cmd <= 4'b1111; 
          i_addr <= {12{1'b1}}; 
          i_count <= {3{1'b0}}; 
        end 
      else  
        begin 
          i_addr <= {12{1'b1}}; 
          case (i_state) // synthesis parallel_case full_case 
           
              3'b000: begin 
                  i_cmd <= 4'b1111; 
                  i_refs <= 3'b0; 
                  //Wait for refresh count-down after reset 
                  if (refresh_counter == 0) 
                      i_state <= 3'b001; 
              end // 3'b000  
           
              3'b001: begin 
                  i_state <= 3'b011; 
                  i_cmd <= {{1{1'b0}},3'h2}; 
                  i_count <= 0; 
                  i_next <= 3'b010; 
              end // 3'b001  
           
              3'b010: begin 
                  i_cmd <= {{1{1'b0}},3'h1}; 
                  i_refs <= i_refs + 1'b1; 
                  i_state <= 3'b011; 
                  i_count <= 3; 
                  // Count up init_refresh_commands 
                  if (i_refs == 3'h1) 
                      i_next <= 3'b111; 
                  else  
                    i_next <= 3'b010; 
              end // 3'b010  
           
              3'b011: begin 
                  i_cmd <= {{1{1'b0}},3'h7}; 
                  //WAIT til safe to Proceed... 
                  if (i_count > 1) 
                      i_count <= i_count - 1'b1; 
                  else  
                    i_state <= i_next; 
              end // 3'b011  
           
              3'b101: begin 
                  i_state <= 3'b101; 
              end // 3'b101  
           
              3'b111: begin 
                  i_state <= 3'b011; 
                  i_cmd <= {{1{1'b0}},3'h0}; 
                  i_addr <= {{2{1'b0}},1'b0,2'b00,3'h3,4'h0}; 
                  i_count <= 4; 
                  i_next <= 3'b101; 
              end // 3'b111  
           
              default: begin 
                  i_state <= 3'b000; 
              end // default 
           
          endcase // i_state 
        end 
    end 
 
 
  assign active_bank = {active_addr[21],active_addr[8]}; 
  assign csn_match = active_cs_n == f_cs_n; 
  assign rnw_match = active_rnw == f_rnw; 
  assign bank_match = active_bank == f_bank; 
  assign row_match = {active_addr[20 : 9]} == {f_addr[20 : 9]}; 
  assign pending = csn_match && rnw_match && bank_match && row_match && !f_empty; 
  assign cas_addr = f_select ? { {4{1'b0}},f_addr[7 : 0] } : { {4{1'b0}},active_addr[7 : 0] }; 
  // **** Main FSM **** 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
        begin 
          m_state <= 9'b000000001; 
          m_next <= 9'b000000001; 
          m_cmd <= 4'b1111; 
          m_bank <= 2'b00; 
          m_addr <= 12'b000000000000; 
          m_data <= 16'b0000000000000000; 
          m_dqm <= 2'b00; 
          m_count <= 3'b000; 
          ack_refresh_request <= 1'b0; 
          f_pop <= 1'b0; 
          oe <= 1'b0; 
        end 
      else  
        begin 
          f_pop <= 1'b0; 
          oe <= 1'b0; 
          case (m_state) // synthesis parallel_case full_case 
           
              9'b000000001: begin 
                  //Wait for init-fsm to be done... 
                  if (init_done) 
                    begin 
                      //Hold bus if another cycle ended to arf. 
                      if (refresh_request) 
                          m_cmd <= {{1{1'b0}},3'h7}; 
                      else  
                        m_cmd <= 4'b1111; 
                      ack_refresh_request <= 1'b0; 
                      //Wait for a read/write request. 
                      if (refresh_request) 
                        begin 
                          m_state <= 9'b001000000; 
                          m_next <= 9'b010000000; 
                          m_count <= 0; 
                          active_cs_n <= 1'b1; 
                        end 
                      else if (!f_empty) 
                        begin 
                          f_pop <= 1'b1; 
                          active_cs_n <= f_cs_n; 
                          active_rnw <= f_rnw; 
                          active_addr <= f_addr; 
                          active_data <= f_data; 
                          active_dqm <= f_dqm; 
                          m_state <= 9'b000000010; 
                        end 
                    end 
                  else  
                    begin 
                      m_addr <= i_addr; 
                      m_state <= 9'b000000001; 
                      m_next <= 9'b000000001; 
                      m_cmd <= i_cmd; 
                    end 
              end // 9'b000000001  
           
              9'b000000010: begin 
                  m_state <= 9'b000000100; 
                  m_cmd <= {csn_decode,3'h3}; 
                  m_bank <= active_bank; 
                  m_addr <= active_addr[20 : 9]; 
                  m_data <= active_data; 
                  m_dqm <= active_dqm; 
                  m_count <= 1; 
                  m_next <= active_rnw ? 9'b000001000 : 9'b000010000; 
              end // 9'b000000010  
           
              9'b000000100: begin 
                  // precharge all if arf, else precharge csn_decode 
                  if (m_next == 9'b010000000) 
                      m_cmd <= {{1{1'b0}},3'h7}; 
                  else  
                    m_cmd <= {csn_decode,3'h7}; 
                  //Count down til safe to Proceed... 
                  if (m_count > 1) 
                      m_count <= m_count - 1'b1; 
                  else  
                    m_state <= m_next; 
              end // 9'b000000100  
           
              9'b000001000: begin 
                  m_cmd <= {csn_decode,3'h5}; 
                  m_bank <= f_select ? f_bank : active_bank; 
                  m_dqm <= f_select ? f_dqm  : active_dqm; 
                  m_addr <= cas_addr; 
                  //Do we have a transaction pending? 
                  if (pending) 
                    begin 
                      //if we need to ARF, bail, else spin 
                      if (refresh_request) 
                        begin 
                          m_state <= 9'b000000100; 
                          m_next <= 9'b000000001; 
                          m_count <= 2; 
                        end 
                      else  
                        begin 
                          f_pop <= 1'b1; 
                          active_cs_n <= f_cs_n; 
                          active_rnw <= f_rnw; 
                          active_addr <= f_addr; 
                          active_data <= f_data; 
                          active_dqm <= f_dqm; 
                        end 
                    end 
                  else  
                    begin 
                      //correctly end RD spin cycle if fifo mt 
                      if (~pending & f_pop) 
                          m_cmd <= {csn_decode,3'h7}; 
                      m_state <= 9'b100000000; 
                    end 
              end // 9'b000001000  
           
              9'b000010000: begin 
                  m_cmd <= {csn_decode,3'h4}; 
                  oe <= 1'b1; 
                  m_data <= f_select ? f_data : active_data; 
                  m_dqm <= f_select ? f_dqm  : active_dqm; 
                  m_bank <= f_select ? f_bank : active_bank; 
                  m_addr <= cas_addr; 
                  //Do we have a transaction pending? 
                  if (pending) 
                    begin 
                      //if we need to ARF, bail, else spin 
                      if (refresh_request) 
                        begin 
                          m_state <= 9'b000000100; 
                          m_next <= 9'b000000001; 
                          m_count <= 1; 
                        end 
                      else  
                        begin 
                          f_pop <= 1'b1; 
                          active_cs_n <= f_cs_n; 
                          active_rnw <= f_rnw; 
                          active_addr <= f_addr; 
                          active_data <= f_data; 
                          active_dqm <= f_dqm; 
                        end 
                    end 
                  else  
                    begin 
                      //correctly end WR spin cycle if fifo empty 
                      if (~pending & f_pop) 
                        begin 
                          m_cmd <= {csn_decode,3'h7}; 
                          oe <= 1'b0; 
                        end 
                      m_state <= 9'b100000000; 
                    end 
              end // 9'b000010000  
           
              9'b000100000: begin 
                  m_cmd <= {csn_decode,3'h7}; 
                  //Count down til safe to Proceed... 
                  if (m_count > 1) 
                      m_count <= m_count - 1'b1; 
                  else  
                    begin 
                      m_state <= 9'b001000000; 
                      m_count <= 0; 
                    end 
              end // 9'b000100000  
           
              9'b001000000: begin 
                  m_state <= 9'b000000100; 
                  m_addr <= {12{1'b1}}; 
                  // precharge all if arf, else precharge csn_decode 
                  if (refresh_request) 
                      m_cmd <= {{1{1'b0}},3'h2}; 
                  else  
                    m_cmd <= {csn_decode,3'h2}; 
              end // 9'b001000000  
           
              9'b010000000: begin 
                  ack_refresh_request <= 1'b1; 
                  m_state <= 9'b000000100; 
                  m_cmd <= {{1{1'b0}},3'h1}; 
                  m_count <= 3; 
                  m_next <= 9'b000000001; 
              end // 9'b010000000  
           
              9'b100000000: begin 
                  m_cmd <= {csn_decode,3'h7}; 
                  //if we need to ARF, bail, else spin 
                  if (refresh_request) 
                    begin 
                      m_state <= 9'b000000100; 
                      m_next <= 9'b000000001; 
                      m_count <= 1; 
                    end 
                  else //wait for fifo to have contents 
                  if (!f_empty) 
                      //Are we 'pending' yet? 
                      if (csn_match && rnw_match && bank_match && row_match) 
                        begin 
                          m_state <= f_rnw ? 9'b000001000 : 9'b000010000; 
                          f_pop <= 1'b1; 
                          active_cs_n <= f_cs_n; 
                          active_rnw <= f_rnw; 
                          active_addr <= f_addr; 
                          active_data <= f_data; 
                          active_dqm <= f_dqm; 
                        end 
                      else  
                        begin 
                          m_state <= 9'b000100000; 
                          m_next <= 9'b000000001; 
                          m_count <= 1; 
                        end 
              end // 9'b100000000  
           
              // synthesis translate_off 
           
              default: begin 
                  m_state <= m_state; 
                  m_cmd <= 4'b1111; 
                  f_pop <= 1'b0; 
                  oe <= 1'b0; 
              end // default 
           
              // synthesis translate_on 
          endcase // m_state 
        end 
    end 
 
 
  assign rd_strobe = m_cmd[2 : 0] == 3'h5; 
  //Track RD Req's based on cas_latency w/shift reg 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          rd_valid <= {3{1'b0}}; 
      else  
        rd_valid <= (rd_valid << 1) | { {2{1'b0}}, rd_strobe }; 
    end 
 
 
  // Register dq data. 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          za_data <= 0; 
      else if (1) 
          za_data <= zs_dq; 
    end 
 
 
  // Delay za_valid to match registered data. 
  always @(posedge clk or negedge reset_n) 
    begin 
      if (reset_n == 0) 
          za_valid <= 0; 
      else if (1) 
          za_valid <= rd_valid[2]; 
    end 
 
 
  assign cmd_code = m_cmd[2 : 0]; 
  assign cmd_all = m_cmd; 
 
//synthesis translate_off 
//////////////// SIMULATION-ONLY CONTENTS 
  assign txt_code = (cmd_code == 3'h0)? 24'h4c4d52 : 
    (cmd_code == 3'h1)? 24'h415246 : 
    (cmd_code == 3'h2)? 24'h505245 : 
    (cmd_code == 3'h3)? 24'h414354 : 
    (cmd_code == 3'h4)? 24'h205752 : 
    (cmd_code == 3'h5)? 24'h205244 : 
    (cmd_code == 3'h6)? 24'h425354 : 
    (cmd_code == 3'h7)? 24'h4e4f50 : 
    24'h424144; 
 
  assign CODE = &(cmd_all|4'h7) ? 24'h494e48 : txt_code; 
 
//////////////// END SIMULATION-ONLY CONTENTS 
 
//synthesis translate_on 
 
endmodule