OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [xilinx/] [s3adsp1800/] [rtl/] [verilog/] [xilinx_s3adsp_ddr2/] [s3adsp_ddr2_controller_0.v] - Rev 733

Go to most recent revision | Compare with Previous | Blame | View Log

//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2005, 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
//   ____  ____
//  /   /\/   /
// /___/  \  /   Vendor		    : Xilinx
// \   \   \/    Version            : 3.6.1
//  \   \        Application	    : MIG
//  /   /        Filename	    : s3adsp_ddr2_controller_0.v
// /___/   /\    Date Last Modified : $Date: 2010/11/26 18:25:41 $
// \   \  /  \   Date Created	    : Mon May 2 2005
//  \___\/\___\
// Device	: Spartan-3/3A/3A-DSP
// Design Name	: DDR2 SDRAM
// Purpose	: This is main controller block. This includes the following
//                features:
//                - The controller state machine that controls the
//                initialization process upon power up, as well as the
//                read, write, and refresh commands.
//                - Accepts and decodes the user commands.
//                - Generates the address and Bank address and control signals
//                   to the memory    
//                - Generates control signals for other modules.
//*****************************************************************************
`timescale 1ns/100ps
`include "s3adsp_ddr2_parameters_0.v"
 
module s3adsp_ddr2_controller_0
  (
   input                           clk/* synthesis syn_keep=1 */,
   input                           rst0,
   input                           rst180,
   input [((`ROW_ADDRESS 
	    + `COLUMN_ADDRESS)-1):0] address,
   input [`BANK_ADDRESS-1:0]       bank_address,
   input [2:0]                     command_register,
   input                           burst_done,
   output                          ddr_rasb_cntrl,
   output                          ddr_casb_cntrl,
   output [`BANK_ADDRESS-1:0]      ddr_ba_cntrl,
   output [`ROW_ADDRESS-1:0]       ddr_address_cntrl,
   output                          ddr_csb_cntrl,
   output                          dqs_enable,
   output                          dqs_reset /* synthesis syn_keep=1 */,
   output                          rst_dqs_div_int,
   output                          cmd_ack,
   output                          init,
   output			   ddr_web_cntrl,
   output                          ddr_cke_cntrl,
   output reg                      write_enable,
   output reg                      rst_calib,
   output reg                      ddr_odt_cntrl,
   output reg                      ar_done,
   input                           wait_200us,
   output                          auto_ref_req,
   output reg                      read_fifo_rden // Read Enable signal for read fifo(to data_read module)
   );
 
   localparam IDLE		      = 4'b0000;
   localparam PRECHARGE		      = 4'b0001;
   localparam AUTO_REFRESH	      = 4'b0010;
   localparam ACTIVE		      = 4'b0011;
   localparam FIRST_WRITE	      = 4'b0100;
   localparam WRITE_WAIT	      = 4'b0101;
   localparam BURST_WRITE	      = 4'b0110;
   localparam PRECHARGE_AFTER_WRITE   = 4'b0111;
   localparam PRECHARGE_AFTER_WRITE_2 = 4'b1000;
   localparam READ_WAIT		      = 4'b1001;
   localparam BURST_READ	      = 4'b1010;
   localparam ACTIVE_WAIT	      = 4'b1011;
 
   localparam INIT_IDLE	         = 2'b00;
   localparam INIT_PRECHARGE	 = 2'b01;
   localparam INIT_LOAD_MODE_REG = 2'b10;
   localparam INIT_AUTO_REFRESH  = 2'b11;
 
   parameter COL_WIDTH          = `COLUMN_ADDRESS;
   parameter ROW_WIDTH          = `ROW_ADDRESS;
 
 
   reg [3:0]                     current_state;
   reg [3:0]                     next_state;
   reg [1:0]                     init_current_state;
   reg [1:0]                     init_next_state;
   reg [((`ROW_ADDRESS           
	  + `COLUMN_ADDRESS)-1):0] address_reg;
   reg                           auto_ref;
   reg                           auto_ref1;
   reg                           autoref_value;
   reg                           auto_ref_detect1;
   reg [(`MAX_REF_WIDTH-1):0]    autoref_count;
   reg                           auto_ref_issued;
   reg [`BANK_ADDRESS-1:0]       ba_address_reg1;
   reg [`BANK_ADDRESS-1:0]       ba_address_reg2;
   reg [2:0]                     burst_length;
   reg [2:0]                     cas_count;
   reg [4:0]                     ras_count; 
 
   reg [`ROW_ADDRESS-1:0]        column_address_reg;
   reg [`ROW_ADDRESS-1:0]        column_address_reg1;
   reg [2:0]                     wr;
   reg                           ddr_rasb2;
   reg                           ddr_casb2;
   reg                           ddr_web2;
   reg [`BANK_ADDRESS-1:0]       ddr_ba1;
   reg [`ROW_ADDRESS-1:0]        ddr_address1;
   reg [3:0]                     init_count;
   reg                           init_done;
   reg                           init_done_r1;
   reg                           init_memory;
   reg                           init_mem;
   reg [6:0]                     init_pre_count;
   reg [7:0]                     dll_rst_count;
   reg [(`MAX_REF_WIDTH-1):0]    ref_freq_cnt;
   reg                           read_cmd1;
   reg                           read_cmd2;
   reg                           read_cmd3;
   reg [2:0]                     rcd_count;
   reg [7:0]                     rfc_counter_value;
   reg [7:0]                     rfc_count;
   reg                           rfc_count_reg;
   reg                           ar_done_reg;
   reg                           rdburst_end_1;
   reg                           rdburst_end_2;
   reg [`ROW_ADDRESS-1:0]        row_address_reg;
   reg                           rst_dqs_div_r;
   reg                           rst_dqs_div_r1; //For Reg Dimm
   reg [2:0]                     wrburst_end_cnt;
   reg                           wrburst_end_1;
   reg                           wrburst_end_2;
   reg                           wrburst_end_3;
   reg [2:0]                     wr_count;
   reg                           write_cmd1;
   reg                           write_cmd2;
   reg                           write_cmd3;
   reg [2:0]                     dqs_div_cascount;
   reg [2:0]                     dqs_div_rdburstcount;
   reg                           dqs_enable1;
   reg                           dqs_enable2;
   reg                           dqs_enable3;
   reg                           dqs_reset1_clk0;
   reg                           dqs_reset2_clk0;
   reg                           dqs_reset3_clk0;
   reg                           dqs_enable_int;
   reg                           dqs_reset_int;
   reg                           rst180_r;
   reg                           rst0_r;
   reg                           ddr_odt2;
   reg                           go_to_active;
   reg                           accept_cmd_in;
   reg  			 odt_deassert;
   reg [2:0]                     rp_count;
   reg                           auto_ref_wait;
   reg                           auto_ref_wait1;
   reg                           auto_ref_wait2;
   reg [7:0]                     count6;
 
 
   wire [`ROW_ADDRESS - 1:0]     lmr;
   wire [`ROW_ADDRESS - 1:0]     emr;
   wire [`ROW_ADDRESS - 1:0]     lmr_dll_rst;
   wire [`ROW_ADDRESS - 1:0]     lmr_dll_set;
   wire [`ROW_ADDRESS-1:0]       column_address;
 
   wire                          write_cmd_in;
   wire                          read_cmd_in;
   wire                          init_cmd_in;
   wire                          wrburst_end;
   wire [`ROW_ADDRESS-1:0]       row_address;
   wire                          rdburst_end;
   wire                          init_done_value;
   wire                          ddr_rasb1;
   wire                          ddr_casb1;
   wire                          ddr_web1;
   wire                          ack_reg;
   wire                          ack_o;
   wire                          auto_ref_issued_p;
   wire                          ar_done_p;
   wire                          go_to_active_value;
   wire                          ddr_odt1;
   wire                          rst_dqs_div_int1;
   wire [2:0]                    burst_cnt_max;
 
 
   // Input : COMMAND REGISTER FORMAT
   //          000  - NOP
   //          010  - Initialize memory
   //          100  - Write Request
   //          110  - Read request
 
   // Input : Address format
   //   row address  = address((`ROW_ADDRESS+ `COLUMN_ADDRESS) -1 : `COLUMN_ADDRESS)
   //   column addres = address( `COLUMN_ADDRESS-1 : 0)
 
   assign    ddr_csb_cntrl       = 1'b0;
   assign    row_address         = address_reg[((`ROW_ADDRESS +
                                                 `COLUMN_ADDRESS)-1):
                                               `COLUMN_ADDRESS];
   assign    init                = init_done;
   assign    ddr_rasb_cntrl      = ddr_rasb2;
   assign    ddr_casb_cntrl      = ddr_casb2;
   assign    ddr_web_cntrl       = ddr_web2;
   assign    ddr_address_cntrl   = ddr_address1;
   assign    ddr_ba_cntrl        = ddr_ba1;
   assign    rst_dqs_div_int     = rst_dqs_div_int1;
   assign    emr                 = `EXT_LOAD_MODE_REGISTER;
   assign    lmr                 = `LOAD_MODE_REGISTER;
   assign    lmr_dll_rst         = {lmr[`ROW_ADDRESS - 1 : 9],1'b1,lmr[7:0]};
   assign    lmr_dll_set         = {lmr[`ROW_ADDRESS - 1 : 9],1'b0,lmr[7:0]};
   assign    ddr_cke_cntrl       = ~wait_200us;
 
// turn off auto-precharge when issuing read/write commands (A10 = 0)
// mapping the column  address for linear addressing.
  generate
    if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
      assign column_address = {address_reg[COL_WIDTH-1:10], 1'b0,
                             address_reg[9:0]};
    end else begin
      if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
        assign column_address = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
                               address_reg[COL_WIDTH-1:10], 1'b0,
                               address_reg[9:0]};
      end else begin: gen_ddr_addr_col_2
        assign column_address = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
                               address_reg[COL_WIDTH-1:0]};
      end
    end
  endgenerate
 
   always @ (negedge clk)
     rst180_r <= rst180;
 
   always @ (posedge clk)
     rst0_r <= rst0;
 
//******************************************************************************
// Register user address 
//******************************************************************************
 
   always @ (negedge clk) begin
      row_address_reg    <= row_address;
      column_address_reg <= column_address;
      ba_address_reg1    <= bank_address;
      ba_address_reg2    <= ba_address_reg1;
      address_reg        <= address;
   end
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         burst_length <= 3'b000;
         wr           <= 3'd0;
      end
      else begin
         burst_length  <= lmr[2:0];
         wr            <= `TWR_COUNT_VALUE;
      end
   end
 
   always @( negedge clk ) begin
      if ( rst180_r )
        accept_cmd_in <= 1'b0;
      else if ( current_state == IDLE && ((rp_count == 3'd0 && rfc_count_reg &&
                                           !auto_ref_wait && !auto_ref_issued)))
        accept_cmd_in <= 1'b1;
      else
        accept_cmd_in <= 1'b0;
   end
 
 
//******************************************************************************
// Commands from user.
//******************************************************************************
   assign init_cmd_in       = (command_register == 3'b010);
   assign write_cmd_in      = (command_register == 3'b100 &&
                               accept_cmd_in == 1'b1) ;
   assign read_cmd_in       = (command_register == 3'b110 &&
                               accept_cmd_in == 1'b1) ;
 
//******************************************************************************
// write_cmd1 is asserted when user issued write command and the controller s/m 
// is in idle state and AUTO_REF is not asserted.
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         write_cmd1  <= 1'b0;
         write_cmd2  <= 1'b0;
         write_cmd3  <= 1'b0;
      end
      else begin
         if (accept_cmd_in)
           write_cmd1 <= write_cmd_in;
         write_cmd2 <= write_cmd1;
         write_cmd3 <= write_cmd2;
      end
   end
 
//******************************************************************************
// read_cmd1 is asserted when user issued read command and the controller s/m 
// is in idle state and AUTO_REF is not asserted.
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         read_cmd1      <= 1'b0;
         read_cmd2      <= 1'b0;
         read_cmd3      <= 1'b0;
      end
      else begin
         if (accept_cmd_in)
           read_cmd1       <= read_cmd_in;
         read_cmd2       <= read_cmd1;
         read_cmd3       <= read_cmd2;
      end
   end
 
//******************************************************************************
// ras_count- Active to Precharge time
// Controller is giving tras violation when user issues a single read command for 
// BL=4 and tRAS is more then 42ns.It uses a fixed clk count of 7 clocks which is 
// 7*6(@166) = 42ns. Addded ras_count counter which will take care of tras timeout. 
// RAS_COUNT_VALUE parameter is used to load the counter and it depends on the 
// selected memory and frequency
//******************************************************************************
   always @( negedge clk ) begin
      if ( rst180_r )
	ras_count <= 5'd0;
      else if ( current_state == ACTIVE )
	ras_count <= `RAS_COUNT_VALUE-1;
      else if ( ras_count != 5'b00000 )
	ras_count <= ras_count - 1'b1;
   end
//******************************************************************************
// rfc_count
// An executable command can be issued only after Trfc period after a AUTOREFRESH 
// command is issued. rfc_count_value is set in the parameter file depending on 
// the memory device speed grade and the selected frequency.For example for 5B 
// speed grade, trfc= 75 at 133Mhz, rfc_counter_value = 8'b00001010. 
// ( Trfc/clk_period= 75/7.5= 10)
//******************************************************************************
 
   always @( negedge clk ) begin
      if (rst180_r == 1'b1)
        rfc_count <= 8'd0;
      else if(current_state == AUTO_REFRESH)
	rfc_count <= rfc_counter_value;
      else if(rfc_count != 8'd0)
	rfc_count <= rfc_count - 1'b1;
   end
 
//******************************************************************************
// rp_count
// An executable command can be issued only after Trp period after a PRECHARGE 
// command is issued. 
//******************************************************************************
 
   always @( negedge clk ) begin
     if ( rst180_r )
       rp_count <= 3'b000;
     else if ( current_state == PRECHARGE )
       rp_count <= `RP_COUNT_VALUE; 
     else if ( rp_count != 3'b000 )
       rp_count <= rp_count - 1'b1;
   end
//******************************************************************************
// rcd_count
// ACTIVE to READ/WRITE delay - Minimum interval between ACTIVE and READ/WRITE command. 
//******************************************************************************
 
   always @( negedge clk ) begin
      if ( rst180_r )
        rcd_count <= 3'b000;
      else if ( current_state == ACTIVE )
        rcd_count <= 3'b001; 
      else if ( rcd_count != 3'b000 )
        rcd_count <= rcd_count - 1'b1;
   end
 
 
//******************************************************************************
// WR Counter a PRECHARGE command can be applied only after 3 cycles after a 
// WRITE command has finished executing
//******************************************************************************
 
   always @(negedge clk) begin
      if (rst180_r)
        wr_count <= 3'b000;
      else
        if (dqs_enable_int)
          wr_count <=  wr ;
        else if (wr_count != 3'b000)
          wr_count <= wr_count - 3'b001;
   end
 
//******************************************************************************
// autoref_count - This counter is used to issue AUTO REFRESH command to 
// the memory for every 7.8125us.
// (Auto Refresh Request is raised for every 7.7 us to allow for termination 
// of any ongoing bus transfer).For example at 166MHz frequency
// autoref_count = refresh_time_period/clock_period =  7.7us/6.02ns = 1279
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1)  begin
         rfc_counter_value <= `RFC_COUNT_VALUE;
         ref_freq_cnt      <= `MAX_REF_CNT;
	 autoref_value     <= 1'b0;
      end
      else begin
         rfc_counter_value <= `RFC_COUNT_VALUE;
         ref_freq_cnt      <= `MAX_REF_CNT;
         autoref_value   <= (autoref_count == ref_freq_cnt);
      end
   end
 
   always @(negedge clk) begin
      if(rst180_r)
        autoref_count <= `MAX_REF_WIDTH'b0;
      else if(autoref_value)
        autoref_count <= `MAX_REF_WIDTH'b0;
      else
        autoref_count <= autoref_count + 1'b1;
   end
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         auto_ref_detect1   <= 1'b0;
         auto_ref1          <= 1'b0;
      end
      else begin
         auto_ref_detect1   <= autoref_value && init_done;
         auto_ref1          <= auto_ref_detect1;
      end
   end
 
   assign ar_done_p = (ar_done_reg == 1'b1) ? 1'b1 : 1'b0;
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         auto_ref_wait <= 1'b0;
         ar_done  <= 1'b0;
         auto_ref_issued <= 1'b0;
      end
      else begin
         if (auto_ref1 && !auto_ref_wait)
           auto_ref_wait <= 1'b1;
         else if (auto_ref_issued_p)
           auto_ref_wait <= 1'b0;
         else
           auto_ref_wait <= auto_ref_wait;
 
         ar_done         <= ar_done_p;
         auto_ref_issued <= auto_ref_issued_p;
      end
   end
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         auto_ref_wait1 <= 1'b0;
         auto_ref_wait2 <= 1'b0;
         auto_ref       <= 1'b0;
      end
      else begin
         if (auto_ref_issued_p) begin
            auto_ref_wait1 <= 1'b0;
            auto_ref_wait2 <= 1'b0;
            auto_ref       <= 1'b0;
         end
         else begin
            auto_ref_wait1  <= auto_ref_wait;
            auto_ref_wait2  <= auto_ref_wait1;
            auto_ref        <= auto_ref_wait2;
         end
      end
   end
 
   assign auto_ref_req = auto_ref_wait;
   assign auto_ref_issued_p = (current_state == AUTO_REFRESH);
 
//******************************************************************************
// Common counter for the Initialization sequence
//******************************************************************************
   always @(negedge clk) begin
      if(rst180_r)
        count6 <= 8'd0;
      else if(init_current_state == INIT_AUTO_REFRESH || init_current_state ==
              INIT_PRECHARGE || init_current_state == INIT_LOAD_MODE_REG)
        count6 <= `RFC_COUNT_VALUE; 
      else if(count6 != 8'd0)
        count6 <= count6 - 1'b1;
      else
        count6 <= 8'd0;
   end
 
//******************************************************************************
// While doing consecutive READs or WRITEs, the burst_cnt_max value determines
// when the next READ or WRITE command should be issued. burst_cnt_max shows the
// number of clock cycles for each burst. 
// e.g burst_cnt_max = 2 for a burst length of 4
//                   = 4 for a burst length of 8
//******************************************************************************
   assign burst_cnt_max = (burst_length == 3'b010) ? 3'b010 :
                          (burst_length == 3'b011) ? 3'b100 :
                          3'b000;
 
   always @( negedge clk) begin
      if(rst180_r)
        cas_count <= 3'b000;
      else if(current_state == BURST_READ)
        cas_count <= burst_cnt_max - 1'b1;
      else if(cas_count != 3'b000)
        cas_count <= cas_count - 1'b1;
   end
 
 
   always @( negedge clk ) begin
      if(rst180_r)
        wrburst_end_cnt <= 3'b000;
      else if((current_state == FIRST_WRITE) || (current_state == BURST_WRITE))
        wrburst_end_cnt <= burst_cnt_max;
      else if(wrburst_end_cnt != 3'b000)
        wrburst_end_cnt <= wrburst_end_cnt - 1'b1;
   end
 
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) 
        rdburst_end_1 <= 1'b0;
      else begin
         rdburst_end_2 <= rdburst_end_1;
         if (burst_done == 1'b1) 
           rdburst_end_1 <= 1'b1;
         else
           rdburst_end_1 <= 1'b0;
      end
   end
 
   assign rdburst_end   = rdburst_end_1 || rdburst_end_2 ;
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) 
        wrburst_end_1 <= 1'b0;
      else begin
         wrburst_end_2  <= wrburst_end_1;
         wrburst_end_3  <= wrburst_end_2;
         if  (burst_done == 1'b1)  
           wrburst_end_1 <= 1'b1;
         else
           wrburst_end_1 <= 1'b0;
      end
   end
 
   assign wrburst_end = wrburst_end_1 || wrburst_end_2 || wrburst_end_3;
 
//******************************************************************************
// dqs_enable and dqs_reset signals are used to generate DQS signal during write
// data.
//******************************************************************************
 
 
 
   assign dqs_enable     = dqs_enable2;
   assign dqs_reset      = dqs_reset2_clk0;
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         dqs_enable_int <= 1'b0;
         dqs_reset_int  <= 1'b0;
      end
      else begin
         dqs_enable_int <= ((current_state == FIRST_WRITE) ||
                            (current_state == BURST_WRITE) ||
                            (wrburst_end_cnt != 3'b000));
         dqs_reset_int  <= (current_state == FIRST_WRITE);
      end
   end
 
   always @ (posedge clk) begin
      if (rst0_r == 1'b1) begin
         dqs_enable1     <= 1'b0;
         dqs_enable2     <= 1'b0;
         dqs_enable3     <= 1'b0;
         dqs_reset1_clk0 <= 1'b0;
         dqs_reset2_clk0 <= 1'b0;
         dqs_reset3_clk0 <= 1'b0;
      end
      else begin
         dqs_enable1     <= dqs_enable_int;
         dqs_enable2     <= dqs_enable1;
         dqs_enable3     <= dqs_enable2;
         dqs_reset1_clk0 <= dqs_reset_int;
         dqs_reset2_clk0 <= dqs_reset1_clk0;
         dqs_reset3_clk0 <= dqs_reset2_clk0;
      end
   end
 
//******************************************************************************
//Write Enable signal to the datapath
//******************************************************************************
 
 
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1)
         write_enable <= 1'b0;
      else if(wrburst_end_cnt != 3'b000)
         write_enable <= 1'b1;
      else
         write_enable <= 1'b0;
   end
 
   assign cmd_ack = ack_reg;
 
   FD ack_reg_inst1
     (
      .Q (ack_reg),
      .D (ack_o),
      .C (~clk)
      );
 
 
   assign ack_o = ((write_cmd_in == 1'b1) || (write_cmd1 == 1'b1) ||
                   (read_cmd_in == 1'b1) || (read_cmd1 == 1'b1));
 
//******************************************************************************
//  init_done will be asserted when initialization sequence is complete
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         init_memory <= 1'b0;
         init_done   <= 1'b0;
         init_done_r1   <= 1'b0;
      end
      else begin
         init_memory <= init_mem;
         init_done   <= init_done_value && (init_count == 4'b1011);
         init_done_r1   <= init_done;
      end
   end
 
   //synthesis translate_off 
   always @ (negedge clk) begin
      if (rst180_r == 1'b0)
        if (init_done == 1'b1 && init_done_r1 == 1'b0)
	  $display ("INITIALIZATION_DONE");
   end 
   //synthesis translate_on
 
   always @ (negedge clk) begin
      if (init_cmd_in) 
         init_pre_count <= 7'b101_0000;
      else 
         init_pre_count <= init_pre_count - 7'h1;
   end
 
   always @( negedge clk ) begin
      if ( rst180_r )
        init_mem <= 1'b0;
      else if ( init_cmd_in )
        init_mem <= 1'b1;
      else if ( (init_count == 4'b1011) && (count6 == 8'd0 ))
        init_mem <= 1'b0;
      else
        init_mem <= init_mem;
   end
 
 always @( negedge clk ) begin
      if ( rst180_r )
        init_count  <= 4'b0;
      else if (((init_current_state == INIT_PRECHARGE) || 
		(init_current_state == INIT_LOAD_MODE_REG)
                || (init_current_state == INIT_AUTO_REFRESH))
	       && init_memory == 1'b1)
        init_count    <= init_count + 1'b1;
      else
        init_count    <= init_count;
   end
 
   assign init_done_value =  (dll_rst_count == 8'b0000_0001) ;
 
 
//Counter to count 200 clock cycles When DLL reset is issued during 
//initialization.
 
   always @( negedge clk ) begin
     if( rst180_r )
       dll_rst_count  <= 8'd0;
     else if(init_count == 4'b0100)
       dll_rst_count  <= 8'd200;
     else if(dll_rst_count != 8'b0000_0001)
       dll_rst_count    <= dll_rst_count - 8'b0000_0001;
     else
       dll_rst_count    <= dll_rst_count;
   end
 
 
 
   assign go_to_active_value =((write_cmd_in == 1'b1) && (accept_cmd_in == 1'b1))
          || ((read_cmd_in == 1'b1) && (accept_cmd_in == 1'b1))
          ? 1'b1 : 1'b0;
 
   always @ (negedge clk) begin
     if (rst180_r == 1'b1) 
       go_to_active <= 1'b0;
     else 
       go_to_active <= go_to_active_value;
   end
 
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         rfc_count_reg   <= 1'b0;
         ar_done_reg     <= 1'b0;
      end
      else begin
         if(rfc_count == 8'd2) 
           ar_done_reg <= 1'b1;
         else
           ar_done_reg <= 1'b0;
         if(ar_done_reg == 1'b1)
           rfc_count_reg <= 1'b1;
         else if(init_done == 1'b1 && init_mem == 1'b0 &&
                 rfc_count == 8'd0)
           rfc_count_reg <= 1'b1;
         else if (auto_ref_issued  == 1'b1)
           rfc_count_reg <= 1'b0;
         else
           rfc_count_reg <= rfc_count_reg;
      end
   end
 
 
 
//******************************************************************************
// Initialization state machine
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) 
         init_current_state    <= INIT_IDLE;
      else 
         init_current_state    <= init_next_state;
   end
 
   always @ (*) begin
      if (rst180_r == 1'b1)
        init_next_state = INIT_IDLE;
      else begin
         case (init_current_state)
           INIT_IDLE : begin
              if (init_memory == 1'b1) begin
                 case (init_count)
                   4'b0000 : begin
                      if(init_pre_count == 7'b000_0001)
                        init_next_state = INIT_PRECHARGE;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0001 : begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0010 : begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0011 : begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0100 : begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;                      
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0101 : begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_PRECHARGE;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0110 : begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_AUTO_REFRESH;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b0111: begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_AUTO_REFRESH;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b1000: begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;
                      else
                        init_next_state = INIT_IDLE;
                   end
                   4'b1001: begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;
                      else
                        init_next_state = init_current_state;
                   end
                   4'b1010: begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_LOAD_MODE_REG;
                      else
                        init_next_state = init_current_state;
                   end
                   4'b1011: begin
                      if (count6 == 8'd0)
                        init_next_state = INIT_IDLE;
                      else
                        init_next_state = init_current_state;
                   end
                   default :
                     init_next_state = INIT_IDLE;
                 endcase
              end
              else
                init_next_state = INIT_IDLE;
           end
           INIT_PRECHARGE :
             init_next_state = INIT_IDLE;
 
           INIT_LOAD_MODE_REG :
             init_next_state = INIT_IDLE;
 
           INIT_AUTO_REFRESH :
             init_next_state = INIT_IDLE;
 
           default :
             init_next_state = INIT_IDLE;
         endcase
      end
   end
 
//******************************************************************************
// Main state machine
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) 
        current_state    <= IDLE;
      else 
        current_state    <= next_state;
   end
 
 
   always @ (*) begin
      if (rst180_r == 1'b1)
        next_state = IDLE;
      else begin
         case (current_state)
           IDLE : begin
              if(~init_mem) begin
                 if ( auto_ref == 1'b1  && rfc_count_reg == 1'b1 
                      && rp_count == 3'd0 )
                   next_state = AUTO_REFRESH;
                 else if (go_to_active == 1'b1)
                   next_state = ACTIVE;
                 else
                   next_state = IDLE;
              end
              else
                next_state = IDLE;
           end
 
           PRECHARGE :
             next_state = IDLE;
 
           AUTO_REFRESH :
             next_state = IDLE;
 
           ACTIVE :
             next_state = ACTIVE_WAIT;
 
           ACTIVE_WAIT : begin
              if(rcd_count == 3'b000  && write_cmd1)
                next_state = FIRST_WRITE;
              else if (rcd_count == 3'b000 && read_cmd3)
                next_state = BURST_READ;
              else
                next_state = ACTIVE_WAIT;
           end
 
           FIRST_WRITE : begin
              next_state = WRITE_WAIT;
           end
 
           WRITE_WAIT : begin
              case(wrburst_end)
                1'b1 :
                  next_state = PRECHARGE_AFTER_WRITE;
                1'b0 : begin
                   if (wrburst_end_cnt == 3'b010)
                     next_state = BURST_WRITE;
                   else
                     next_state = WRITE_WAIT;
                end
                default :
                  next_state = WRITE_WAIT;
              endcase
           end
           BURST_WRITE : begin
              next_state = WRITE_WAIT;
           end
           PRECHARGE_AFTER_WRITE : begin
              next_state = PRECHARGE_AFTER_WRITE_2;
           end
           PRECHARGE_AFTER_WRITE_2 : begin
              if(wr_count == 3'd0 && ras_count == 5'd0)   
                next_state = PRECHARGE;
              else
                next_state = PRECHARGE_AFTER_WRITE_2;
           end
           READ_WAIT : begin
              case(rdburst_end)
                1'b1 :
                  next_state = PRECHARGE_AFTER_WRITE;
                1'b0 : begin
                   if (cas_count == 3'b001)
                     next_state = BURST_READ;
                   else
                     next_state = READ_WAIT;
                end
                default :
                  next_state = READ_WAIT;
              endcase
           end
           BURST_READ : begin
              next_state = READ_WAIT;
           end
           default :
             next_state = IDLE;
         endcase
      end
   end
 
//******************************************************************************
// Address generation logic
//******************************************************************************
   always @( negedge clk ) begin
      if(rst180_r)
        ddr_address1 <= {`ROW_ADDRESS{1'b0}};
      else if(init_mem)
        case ( init_count )
          4'b0000, 4'b0101 : ddr_address1 <= {`ROW_ADDRESS{1'b0}} |
                                             12'h400;
          4'b0001 : ddr_address1 <= {`ROW_ADDRESS{1'b0}}; 
          4'b0010 : ddr_address1 <= {`ROW_ADDRESS{1'b0}}; 
          4'b0011 : ddr_address1 <= emr; 
          4'b0100 : ddr_address1 <= lmr_dll_rst;
          4'b1000 : ddr_address1 <= lmr_dll_set; 
          4'b1001 : ddr_address1 <= emr | 12'h380; 
          4'b1010 : ddr_address1 <= emr & 12'hc7f;
          default : ddr_address1 <= {`ROW_ADDRESS{1'b0}};
        endcase
      else if ( current_state == PRECHARGE ||
		init_current_state == INIT_PRECHARGE )
        ddr_address1 <= {`ROW_ADDRESS{1'b0}} | 12'h400;
      else if ( current_state == ACTIVE )
        ddr_address1 <= row_address_reg;
      else if ( current_state == BURST_WRITE || current_state == FIRST_WRITE ||
                current_state == BURST_READ )
        ddr_address1 <= column_address_reg1;
      else
        ddr_address1 <= `ROW_ADDRESS'b0;
   end
 
   always @( negedge clk ) begin
      if ( rst180_r )
        ddr_ba1 <= {{`BANK_ADDRESS-1{1'b0}},1'b0};
      else if ( init_mem )
        case ( init_count )
          4'b0001 : ddr_ba1 <= (`BANK_ADDRESS'b10);
          4'b0010 : ddr_ba1 <= (`BANK_ADDRESS'b11);
          4'b0011 , 4'b1001 , 4'b1010 : ddr_ba1 <= (`BANK_ADDRESS'b01);
          default : ddr_ba1 <= {{`BANK_ADDRESS-1{1'b0}},1'b0};
        endcase
      else if ( current_state == ACTIVE || current_state == FIRST_WRITE ||
                current_state == BURST_WRITE || current_state == BURST_READ)
        ddr_ba1 <= ba_address_reg2;
      else
        ddr_ba1 <= `BANK_ADDRESS'b0;
   end
 
 
   always @( negedge clk ) begin
      if ( rst180_r )
        odt_deassert <= 1'b0;
      else if (wrburst_end_3) 
        odt_deassert <= 1'b1;
      else if(!write_cmd3)
        odt_deassert <= 1'b0;
      else
        odt_deassert <= odt_deassert;
   end
 
   assign ddr_odt1 = ( write_cmd3 == 1'b1  && (emr[6]|emr[2]) && !odt_deassert )
			? 1'b1 : 1'b0;  
 
//******************************************************************************
//  Register column address
//******************************************************************************
   always @ (negedge clk) 
      column_address_reg1 <= column_address_reg;
 
//******************************************************************************
//Pipeline stages for ddr_address and ddr_ba
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) begin
         ddr_odt2  <= 1'b0;
         ddr_rasb2 <= 1'b1;
         ddr_casb2 <= 1'b1;
         ddr_web2  <= 1'b1;
      end
      else begin
         ddr_odt2  <= ddr_odt1;
         ddr_rasb2 <= ddr_rasb1;
         ddr_casb2 <= ddr_casb1;
         ddr_web2  <= ddr_web1;
      end
   end
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1) 
        ddr_odt_cntrl   <= 1'b0;
      else 
        ddr_odt_cntrl   <= ddr_odt2;
   end
 
//******************************************************************************
// Control signals to the Memory
//******************************************************************************
 
   assign ddr_rasb1 = ~((current_state == ACTIVE) || 
			(current_state == PRECHARGE) ||
			(current_state == AUTO_REFRESH) || 
			(init_current_state ==  INIT_PRECHARGE) || 
			(init_current_state == INIT_AUTO_REFRESH)  ||
			(init_current_state == INIT_LOAD_MODE_REG));
 
   assign ddr_casb1 = ~((current_state == BURST_READ) || 
			(current_state == BURST_WRITE)
                        || (current_state == FIRST_WRITE) ||
                        (current_state == AUTO_REFRESH) ||
                        (init_current_state == INIT_AUTO_REFRESH) ||
                        (init_current_state == INIT_LOAD_MODE_REG));
 
   assign ddr_web1  = ~((current_state == BURST_WRITE) || 
			(current_state == FIRST_WRITE) || 
			(current_state == PRECHARGE) ||
			(init_current_state == INIT_PRECHARGE) || 
                        (init_current_state == INIT_LOAD_MODE_REG));
 
//******************************************************************************
// Register CONTROL SIGNALS outputs
//******************************************************************************
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1)
        dqs_div_cascount <= 3'b0;
      else if ((ddr_rasb2 == 1'b1) && (ddr_casb2 == 1'b0) && (ddr_web2 == 1'b1))
	dqs_div_cascount <= burst_cnt_max ;
      else if (dqs_div_cascount != 3'b000)
	dqs_div_cascount <= dqs_div_cascount - 1'b1;
      else
	dqs_div_cascount <= dqs_div_cascount;
   end
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1)
        dqs_div_rdburstcount <= 3'b000;
      else begin
         if ((dqs_div_cascount == 3'b001) && (burst_length== 3'b010))
           dqs_div_rdburstcount <= 3'b010;
         else if ((dqs_div_cascount == 3'b011) && (burst_length== 3'b011))
           dqs_div_rdburstcount <= 3'b100;
         else begin
            if (dqs_div_rdburstcount != 3'b000)
              dqs_div_rdburstcount <= dqs_div_rdburstcount - 1'b1;
            else
              dqs_div_rdburstcount <= dqs_div_rdburstcount;
         end
      end
   end
 
   always @ (negedge clk) begin
      if (rst180_r == 1'b1)
        rst_dqs_div_r <= 1'b0;
      else begin
         if (dqs_div_cascount == 3'b001  && burst_length == 3'b010)
           rst_dqs_div_r <= 1'b1;
         else if (dqs_div_cascount == 3'b011  && burst_length == 3'b011)
           rst_dqs_div_r <= 1'b1;
         else if (dqs_div_rdburstcount == 3'b001 && dqs_div_cascount == 3'b000)
           rst_dqs_div_r <= 1'b0;
         else
           rst_dqs_div_r <= rst_dqs_div_r;
      end
   end // always @ (negedge clk)
 
   always @ (negedge clk) 
     rst_dqs_div_r1 <= rst_dqs_div_r;
 
   always @( negedge clk ) begin
      if(dqs_div_cascount != 3'b0 || dqs_div_rdburstcount != 3'b0 )
        rst_calib <= 1'b1;
      else
        rst_calib <= 1'b0;
   end
 
   (* IOB = "FORCE" *) FD  rst_iob_out
	    (
	     .Q(rst_dqs_div_int1),
	          .D(rst_dqs_div_r),
	     .C(clk)
	     )/* synthesis syn_useioff = 1 */;
 
 
//Read fifo read enable logic, this signal is same as rst_dqs_div_int signal for RDIMM 
//and one clock ahead of rst_dqs_div_int for component or UDIMM OR SODIMM. 
 
   always @(negedge clk)  
     read_fifo_rden <= rst_dqs_div_r1;
 
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.