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

Subversion Repositories ddr2_sdram

[/] [ddr2_sdram/] [trunk/] [ipcore_dir/] [DDR2_Ram_Core/] [user_design/] [rtl/] [DDR2_Ram_Core_controller_0.vhd] - Rev 2

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           : DDR2_Ram_Core_controller_0.vhd
-- /___/   /\    Date Last Modified : $Date: 2010/11/26 18:25:42 $
-- \   \  /  \   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.
--*****************************************************************************
 
library ieee;
library UNISIM;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use UNISIM.VCOMPONENTS.all;
use work.DDR2_Ram_Core_parameters_0.all;
 
entity DDR2_Ram_Core_controller_0 is
  generic
    (
     COL_WIDTH : integer := COLUMN_ADDRESS;
     ROW_WIDTH : integer := ROW_ADDRESS
    );
  port(
    clk               : in  std_logic;
    rst0              : in  std_logic;
    rst180            : in  std_logic;
    address           : in  std_logic_vector(((ROW_ADDRESS + COLUMN_ADDRESS)-1)
                                            downto 0);
    bank_addr         : in  std_logic_vector((BANK_ADDRESS-1) downto 0);
    command_register  : in  std_logic_vector(2 downto 0);
    burst_done        : in  std_logic;
    ddr_rasb_cntrl    : out std_logic;
    ddr_casb_cntrl    : out std_logic;
    ddr_web_cntrl     : out std_logic;
    ddr_ba_cntrl      : out std_logic_vector((BANK_ADDRESS-1) downto 0);
    ddr_address_cntrl : out std_logic_vector((ROW_ADDRESS-1) downto 0);
    ddr_cke_cntrl     : out std_logic;
    ddr_csb_cntrl     : out std_logic;
    ddr_odt_cntrl     : out std_logic;
    dqs_enable        : out std_logic;
    dqs_reset         : out std_logic;
    write_enable      : out std_logic;
    rst_calib         : out std_logic;
    rst_dqs_div_int   : out std_logic;
    cmd_ack           : out std_logic;
    init              : out std_logic;
    ar_done           : out std_logic;
    wait_200us        : in  std_logic;
    auto_ref_req      : out std_logic;
    read_fifo_rden    : out std_logic -- Read Enable signal for read fifo(to data_read)
    );
end DDR2_Ram_Core_controller_0;
 
 
architecture arc of DDR2_Ram_Core_controller_0 is
 
  type s_m is (IDLE, PRECHARGE, AUTO_REFRESH, ACTIVE,
               FIRST_WRITE, WRITE_WAIT, BURST_WRITE,
               PRECHARGE_AFTER_WRITE, PRECHARGE_AFTER_WRITE_2, READ_WAIT,
               BURST_READ, ACTIVE_WAIT);
 
  type s_m1 is (INIT_IDLE, INIT_PRECHARGE,
                INIT_AUTO_REFRESH, INIT_LOAD_MODE_REG);
  signal next_state, current_state           : s_m;
  signal init_next_state, init_current_state : s_m1;
 
  signal ack_reg              : std_logic;
  signal ack_o                : std_logic;
  signal auto_ref             : std_logic;
  signal auto_ref1            : std_logic;
  signal autoref_value        : std_logic;
  signal auto_ref_detect1     : std_logic;
  signal autoref_count        : std_logic_vector((MAX_REF_WIDTH-1) downto 0);
  signal ar_done_p            : std_logic;
  signal auto_ref_issued      : std_logic;
  signal auto_ref_issued_p    : std_logic;
  signal ba_address_reg1      : std_logic_vector((BANK_ADDRESS-1) downto 0);
  signal ba_address_reg2      : std_logic_vector((BANK_ADDRESS-1) downto 0);
  signal burst_length         : std_logic_vector(2 downto 0);
  signal burst_cnt_max        : std_logic_vector(2 downto 0);
  signal cas_count            : std_logic_vector(2 downto 0);
  signal ras_count           : std_logic_vector(4 downto 0); 
  signal column_address_reg   : std_logic_vector((ROW_ADDRESS-1) downto 0);
  signal ddr_rasb1            : std_logic;
  signal ddr_casb1            : std_logic;
  signal ddr_web1             : std_logic;
  signal ddr_ba1              : std_logic_vector((BANK_ADDRESS-1) downto 0);
  signal ddr_address1         : std_logic_vector((ROW_ADDRESS-1) downto 0);
  signal dqs_enable_out       : std_logic;
  signal dqs_reset_out        : std_logic;
  signal dll_rst_count        : std_logic_vector(7 downto 0);
  signal init_count           : std_logic_vector(3 downto 0);
  signal init_done            : std_logic;
  signal init_done_r1         : std_logic;
  signal init_done_dis        : std_logic;
  signal init_done_value      : std_logic;
  signal init_memory          : std_logic;
  signal init_mem             : std_logic;
  signal init_cmd_in    : std_logic;
  signal init_pre_count       : std_logic_vector(6 downto 0);
  signal ref_freq_cnt         : std_logic_vector((MAX_REF_WIDTH-1) downto 0);
  signal read_cmd_in             : std_logic;
  signal read_cmd1            : std_logic;
  signal read_cmd2            : std_logic;
  signal read_cmd3            : std_logic;
  signal rcd_count           : std_logic_vector(2 downto 0);
  signal rp_cnt_value         : std_logic_vector(2 downto 0);
  signal rfc_count_reg        : std_logic;
  signal ar_done_reg          : std_logic;
  signal rdburst_end_1        : std_logic;
  signal rdburst_end_2        : std_logic;
  signal rdburst_end          : std_logic;
  signal rp_count             : std_logic_vector(2 downto 0);
  signal rfc_count            : std_logic_vector(7 downto 0);
  signal row_address_reg      : std_logic_vector((ROW_ADDRESS-1) downto 0);
  signal column_address1      : std_logic_vector((ROW_ADDRESS -1) downto 0);
  signal rst_dqs_div_r        : std_logic;
  signal rst_dqs_div_r1       : std_logic;
  signal wrburst_end_cnt      : std_logic_vector(2 downto 0);
  signal wrburst_end          : std_logic;
  signal wrburst_end_1        : std_logic;
  signal wrburst_end_2        : std_logic;
  signal wrburst_end_3        : std_logic;
  signal wr_count             : std_logic_vector(2 downto 0);
  signal write_enable_out     : std_logic;
  signal write_cmd_in         : std_logic;
  signal write_cmd2           : std_logic;
  signal write_cmd3           : std_logic;
  signal write_cmd1           : std_logic;
  signal go_to_active_value   : std_logic;
  signal go_to_active         : std_logic;
  signal dqs_div_cascount     : std_logic_vector(2 downto 0);
  signal dqs_div_rdburstcount : std_logic_vector(2 downto 0);
  signal dqs_enable1          : std_logic;
  signal dqs_enable2          : std_logic;
  signal dqs_enable3          : std_logic;
  signal dqs_reset1_clk0      : std_logic;
  signal dqs_reset2_clk0      : std_logic;
  signal dqs_reset3_clk0      : std_logic;
  signal dqs_enable_int       : std_logic;
  signal dqs_reset_int        : std_logic;
  signal rst180_r             : std_logic;
  signal rst0_r               : std_logic;
  signal emr                  : std_logic_vector(ROW_ADDRESS - 1 downto 0);
  signal lmr                  : std_logic_vector(ROW_ADDRESS - 1 downto 0);
  signal lmr_dll_rst          : std_logic_vector(ROW_ADDRESS - 1 downto 0);
  signal lmr_dll_set          : std_logic_vector(ROW_ADDRESS - 1 downto 0);
  signal ddr_odt1             : std_logic;
  signal ddr_odt2             : std_logic;
  signal rst_dqs_div_int1     : std_logic;
  signal accept_cmd_in        : std_logic;
  signal dqs_enable_i         : std_logic;
  signal auto_ref_wait        : std_logic;
  signal auto_ref_wait1       : std_logic;
  signal auto_ref_wait2       : std_logic;
  signal address_reg          : std_logic_vector(((ROW_ADDRESS +
                                                   COLUMN_ADDRESS)-1) downto 0);
  signal ddr_rasb2            : std_logic;
  signal ddr_casb2            : std_logic;
  signal ddr_web2             : std_logic;
  signal count6               : std_logic_vector(7 downto 0);
  signal clk180               : std_logic;
  signal odt_deassert         : std_logic;
 
 
  constant addr_const1 : std_logic_vector(14 downto 0) := "000010000000000";
  constant addr_const2 : std_logic_vector(14 downto 0) := "000001110000000";  --380
  constant addr_const3 : std_logic_vector(14 downto 0) := "000110001111111";  --C7F
  constant ba_const1   : std_logic_vector(2 downto 0)  := "010";
  constant ba_const2   : std_logic_vector(2 downto 0)  := "011";
  constant ba_const3   : std_logic_vector(2 downto 0)  := "001";
 
  attribute iob                        : string;
  attribute syn_useioff                : boolean;
  attribute syn_preserve               : boolean;
  attribute syn_keep                   : boolean;
 
  attribute iob of rst_iob_out                 : label is "FORCE";
  attribute syn_useioff of rst_iob_out         : label is true;
  attribute syn_preserve of lmr_dll_rst        : signal is true;
  attribute syn_preserve of lmr_dll_set        : signal is true;
  attribute syn_preserve of ba_address_reg1    : signal is true;
  attribute syn_preserve of ba_address_reg2    : signal is true;
  attribute syn_preserve of column_address_reg : signal is true;
  attribute syn_preserve of row_address_reg    : signal is true;
 
begin
 
  clk180      <= not clk;
  emr         <= EXT_LOAD_MODE_REGISTER;
  lmr         <= LOAD_MODE_REGISTER;
  lmr_dll_rst <= lmr(ROW_ADDRESS - 1 downto 9) & '1' & lmr(7 downto 0);
  lmr_dll_set <= lmr(ROW_ADDRESS - 1 downto 9) & '0' & lmr(7 downto 0);
 
 
-- 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 downto COLUMN_ADDRESS)
-- column address = address(COLUMN_ADDRESS-1 downto 0)
 
  ddr_csb_cntrl     <= '0';
  ddr_cke_cntrl     <= not wait_200us;
  init              <= init_done;
  ddr_rasb_cntrl    <= ddr_rasb2;
  ddr_casb_cntrl    <= ddr_casb2;
  ddr_web_cntrl     <= ddr_web2;
  rst_dqs_div_int   <= rst_dqs_div_int1;
  ddr_address_cntrl <= ddr_address1;
  ddr_ba_cntrl      <= ddr_ba1;
 
  -- turn off auto-precharge when issuing read/write commands (A10 = 0)
  -- mapping the column address for linear addressing.
  gen_ddr_addr_col_0: if (COL_WIDTH = ROW_WIDTH-1) generate
    column_address1 <= (address_reg(COL_WIDTH-1 downto 10) & '0' &
                        address_reg(9 downto 0));
  end generate;
 
  gen_ddr_addr_col_1: if ((COL_WIDTH > 10) and
                          not(COL_WIDTH = ROW_WIDTH-1)) generate
    column_address1(ROW_WIDTH-1 downto COL_WIDTH+1) <= (others => '0');
    column_address1(COL_WIDTH downto 0) <=
      (address_reg(COL_WIDTH-1 downto 10) & '0' & address_reg(9 downto 0));
  end generate;
 
  gen_ddr_addr_col_2: if (not((COL_WIDTH > 10) or
                              (COL_WIDTH = ROW_WIDTH-1))) generate
    column_address1(ROW_WIDTH-1 downto COL_WIDTH+1) <= (others => '0');
    column_address1(COL_WIDTH downto 0) <=
      ('0' & address_reg(COL_WIDTH-1 downto 0));
  end generate;
 
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      rst180_r <= rst180;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '1' then
      rst0_r <= rst0;
    end if;
  end process;
 
--******************************************************************************
-- Register user address
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      row_address_reg    <= address_reg(((ROW_ADDRESS + COLUMN_ADDRESS)-1) downto
                                        COLUMN_ADDRESS);
      column_address_reg <= column_address1;
      ba_address_reg1    <= bank_addr;
      ba_address_reg2    <= ba_address_reg1;
      address_reg        <= address;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        burst_length <= "000";
      else
        burst_length <= lmr(2 downto 0);
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if (clk'event and clk = '0') then
      if rst180_r = '1' then
        accept_cmd_in <= '0';
      elsif (current_state = IDLE and (rp_count = "000"  and (rfc_count_reg and
                                        not(auto_ref_wait) and
                                        not(auto_ref_issued)) = '1')) then
        accept_cmd_in <= '1';
      else
        accept_cmd_in <= '0';
      end if;
    end if;
  end process;
--******************************************************************************
-- Commands from user.
--******************************************************************************
  init_cmd_in       <= '1' when (command_register = "010") else '0';
  write_cmd_in      <= '1' when (command_register = "100" and
                                 accept_cmd_in = '1') else '0';
  read_cmd_in       <= '1' when (command_register = "110" and
                                 accept_cmd_in = '1') else '0';
 
--******************************************************************************
-- write_cmd1 is asserted when user issued write command and the controller s/m
-- is in idle state and AUTO_REF is not asserted.
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        write_cmd1   <= '0';
        write_cmd2   <= '0';
        write_cmd3   <= '0';
      else
        if (accept_cmd_in = '1') then
          write_cmd1 <= write_cmd_in;
        end if;
        write_cmd2   <= write_cmd1;
        write_cmd3   <= write_cmd2;
      end if;
    end if;
  end process;
 
--******************************************************************************
-- read_cmd1 is asserted when user issued read command and the controller s/m
-- is in idle state and AUTO_REF is not asserted.
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        read_cmd1   <= '0';
        read_cmd2   <= '0';
        read_cmd3   <= '0';
      else
        if (accept_cmd_in = '1') then
          read_cmd1 <= read_cmd_in;
        end if;
        read_cmd2   <= read_cmd1;
        read_cmd3   <= read_cmd2;
      end if;
    end if;
  end process;
 
--******************************************************************************
-- 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
--******************************************************************************
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        ras_count <= "00000";
      elsif(current_state = ACTIVE) then
        ras_count <= RAS_COUNT_VALUE - '1';
      elsif(ras_count /= "00000") then
        ras_count <= ras_count - '1';
      end if;
    end if;
  end process;
--******************************************************************************
-- 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, at 133Mhz, rfc_counter_value = 8'b00001001.
-- ( Trfc/clk_period= 75/7.5= 10)
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        rfc_count <= "00000000";
      elsif(current_state = AUTO_REFRESH) then
        rfc_count <= RFC_COUNT_VALUE;
      elsif(rfc_count /= "00000000") then
        rfc_count <= rfc_count - '1';
      end if;
    end if;
  end process;
 
--******************************************************************************
-- rp_count
-- An executable command can be issued only after Trp period after a PRECHARGE
-- command is issued. 
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        rp_count <= "000";
      elsif(current_state = PRECHARGE) then
        rp_count <= RP_COUNT_VALUE;
      elsif(rp_count /= "000") then
        rp_count <= rp_count - '1';
      end if;
    end if;
  end process;
 
 
 
--******************************************************************************
-- rcd_count
-- ACTIVE to READ/WRITE delay - Minimum interval between ACTIVE and READ/WRITE command. 
--******************************************************************************
 
  process(clk)
  begin
    if (clk'event and clk = '0') then
      if (rst180_r = '1') then
        rcd_count <= "000";
      elsif (current_state = ACTIVE) then
        rcd_count <= "001";
      elsif (rcd_count /= "000") then
        rcd_count <= rcd_count - '1';
      end if;
    end if;
  end process;
 
--******************************************************************************
-- WR Counter
-- a PRECHARGE command can be applied only after 2 cycles after a WRITE command
-- has finished executing
--******************************************************************************
 
  process (clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        wr_count   <= "000";
      else
        if (dqs_enable_int = '1') then
          wr_count <= TWR_COUNT_VALUE;
        elsif (wr_count /= "000") then
          wr_count <= wr_count - "001";
        end if;
      end if;
    end if;
  end process;
 
--******************************************************************************
-- 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
--******************************************************************************
 
  ref_freq_cnt <= MAX_REF_CNT;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        autoref_value <= '0';
      elsif (autoref_count = ref_freq_cnt) then
        autoref_value <= '1';
      else
        autoref_value <= '0';
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        autoref_count <= (others => '0');
      elsif (autoref_value = '1') then
        autoref_count <= (others => '0');
      else
        autoref_count <= autoref_count + '1';
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        auto_ref_detect1 <= '0';
        auto_ref1        <= '0';
      else
        auto_ref_detect1 <= autoref_value and init_done;
        auto_ref1        <= auto_ref_detect1;
      end if;
    end if;
  end process;
 
  ar_done_p <= '1' when ar_done_reg = '1' else '0';
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        auto_ref_wait   <= '0';
        ar_done         <= '0';
        auto_ref_issued <= '0';
      else
        if (auto_ref1 = '1' and auto_ref_wait = '0') then
          auto_ref_wait <= '1';
        elsif (auto_ref_issued = '1') then
          auto_ref_wait <= '0';
        else
          auto_ref_wait <= auto_ref_wait;
        end if;
        ar_done         <= ar_done_p;
        auto_ref_issued <= auto_ref_issued_p;
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        auto_ref_wait1   <= '0';
        auto_ref_wait2   <= '0';
        auto_ref         <= '0';
      else
        if (auto_ref_issued_p = '1') then
          auto_ref_wait1 <= '0';
          auto_ref_wait2 <= '0';
          auto_ref       <= '0';
        else
          auto_ref_wait1 <= auto_ref_wait;
          auto_ref_wait2 <= auto_ref_wait1;
          auto_ref       <= auto_ref_wait2;
        end if;
      end if;
    end if;
  end process;
 
  auto_ref_req      <= auto_ref_wait;
  auto_ref_issued_p <= '1' when (current_state = AUTO_REFRESH) else '0';
 
--******************************************************************************
-- Common counter for the Initialization sequence
--******************************************************************************
 
  process(clk)
  begin
    if (clk'event and clk = '0') then
      if (rst180_r = '1') then
        count6 <= "00000000";
      elsif(init_current_state = INIT_AUTO_REFRESH or init_current_state
            = INIT_PRECHARGE or init_current_state = INIT_LOAD_MODE_REG) then
        count6 <= RFC_COUNT_VALUE; 
      elsif(count6 /= "00000000") then
        count6 <= count6 - '1';
      else
        count6 <= "00000000";
      end if;
    end if;
  end process;
 
--******************************************************************************
-- 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
--******************************************************************************
 
  burst_cnt_max <= "010" when burst_length = "010" else
                   "100" when burst_length = "011" else
                   "000";
 
 
  process(clk)
  begin
    if (clk'event and clk = '0') then
      if (rst180_r = '1') then
        cas_count <= "000";
      elsif(current_state = BURST_READ) then
        cas_count <= burst_cnt_max - '1';
      elsif(cas_count /= "000") then
        cas_count <= cas_count - '1';
      end if;
    end if;
  end process;
 
 
  process(clk)
  begin
    if (clk'event and clk = '0') then
      if (rst180_r = '1') then
        wrburst_end_cnt <= "000";
      elsif ((current_state = FIRST_WRITE) or (current_state = BURST_WRITE)) then
        wrburst_end_cnt <= burst_cnt_max;
      elsif (wrburst_end_cnt /= "000") then
        wrburst_end_cnt <= wrburst_end_cnt - '1';
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        rdburst_end_1   <= '0';
      else
        if(burst_done = '1') then
          rdburst_end_1 <= '1';
        else
          rdburst_end_1 <= '0';
        end if;
        rdburst_end_2   <= rdburst_end_1;
      end if;
    end if;
  end process;
 
  rdburst_end <= rdburst_end_1 or rdburst_end_2;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        wrburst_end_1   <= '0';
      else
        if (burst_done = '1') then
          wrburst_end_1 <= '1';
        else
          wrburst_end_1 <= '0';
        end if;
        wrburst_end_2   <= wrburst_end_1;
        wrburst_end_3   <= wrburst_end_2;
      end if;
    end if;
  end process;
 
  wrburst_end <= wrburst_end_1 or wrburst_end_2 or wrburst_end_3;
 
--******************************************************************************
-- dqs_enable and dqs_reset signals are used to generate DQS signal during write
-- data.
--******************************************************************************
  dqs_enable_out <= '1' when ((current_state = FIRST_WRITE) or
                              (current_state = BURST_WRITE) or
                              (WRburst_end_cnt /= "000")) else '0';
  dqs_reset_out  <= '1' when current_state = FIRST_WRITE  else '0';
  dqs_enable     <= dqs_enable_i;
 
    dqs_enable_i   <= dqs_enable2;
  dqs_reset      <= dqs_reset2_clk0;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        dqs_enable_int <= '0';
        dqs_reset_int  <= '0';
      else
        dqs_enable_int <= dqs_enable_out;
        dqs_reset_int  <= dqs_reset_out;
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '1' then
      if rst0_r = '1' then
        dqs_enable1     <= '0';
        dqs_enable2     <= '0';
        dqs_enable3     <= '0';
        dqs_reset1_clk0 <= '0';
        dqs_reset2_clk0 <= '0';
        dqs_reset3_clk0 <= '0';
      else
        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 if;
    end if;
  end process;
 
--******************************************************************************
--Write Enable signal to the datapath
--******************************************************************************
 
  write_enable_out <= '1' when (wrburst_end_cnt /= "000")else '0';
  cmd_ack          <= ack_reg;
  ack_o            <= '1' when ((write_cmd_in = '1') or (write_cmd1 = '1') or
                                (read_cmd_in = '1') or (read_cmd1 = '1')) else '0';
 
 
  process(clk)
  begin
   if clk'event and clk = '0' then
    if rst180_r = '1' then
     write_enable <= '0';
    else
     write_enable <= write_enable_out;
    end if;
   end if;
  end process;
 
 
  ACK_REG_INST1 : FD
    port map (
      Q => ack_reg,
      D => ack_o,
      C => clk180
      );
 
--******************************************************************************
-- init_done will be asserted when initialization sequence is complete
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        init_memory  <= '0';
        init_done    <= '0';
        init_done_r1 <= '0';
      else
        init_memory  <= init_mem;
        init_done_r1 <= init_done;
        if ((init_done_value = '1')and (init_count = "1011")) then
          init_done  <= '1';
        else
          init_done  <= '0';
        end if;
      end if;
    end if;
  end process;
 
  init_done_dis <= '1' when ( init_done = '1' and init_done_r1 = '0') else
                   '0';
 
  process(clk)
  begin
    if(clk'event and clk = '0') then
      if rst180_r = '0' then
        --synthesis translate_off
        assert (init_done_dis = '0') report "INITIALIZATION_DONE" severity note;
        --synthesis translate_on
      end if;
    end if;
  end process;
 
  process (clk)
  begin
    if clk'event and clk = '0' then
      if init_cmd_in = '1' or rst180_r = '1' then
        init_pre_count <= "1010000";
      else
        init_pre_count <= init_pre_count - "0000001";
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        init_mem <= '0';
      elsif (init_cmd_in = '1') then
        init_mem <= '1';
      elsif ((init_count = "1011") and (count6 = "00000000")) then
        init_mem <= '0';
      else
        init_mem <= init_mem;
      end if;
    end if;
  end process;
 
-- Counter for Memory Initialization sequence
 
 
 process(clk)
  begin
    if(clk'event and clk = '0') then
      if rst180_r = '1' then
        init_count <= "0000";
      elsif(((init_current_state = INIT_PRECHARGE) or 
		(init_current_state = INIT_LOAD_MODE_REG) or
		(init_current_state = INIT_AUTO_REFRESH)) and init_memory = '1') then
        init_count <= init_count + '1';
      else
        init_count <= init_count;
      end if;
    end if;
  end process;
 
 
  init_done_value     <= '1' when ((init_count = "1011") and
                               (dll_rst_count = "00000001")) else '0';
 
-- Counter to count 200 clock cycles When DLL reset is issued during initialization.
 
 
 process(clk)
  begin
    if(clk'event and clk = '0') then
      if rst180_r = '1' then
        dll_rst_count <= "00000000";
      elsif(init_count = "0100") then
        dll_rst_count <= "11001000";
      elsif(dll_rst_count /= "00000001") then
        dll_rst_count <= dll_rst_count - '1';
      else
        dll_rst_count <= dll_rst_count;
      end if;
    end if;
  end process;
 
 
  go_to_active_value  <= '1' when ((write_cmd_in = '1') and (accept_cmd_in = '1'))
                         or ((read_cmd_in = '1') and (accept_cmd_in = '1'))
                         else '0';
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        go_to_active <= '0';
      else
        go_to_active <= go_to_active_value;
      end if;
    end if;
  end process;
 
--******************************************************************************
-- Register counter values
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        ar_done_reg   <= '0';
        rfc_count_reg <= '0';
      else
        if(rfc_count = "00000010") then   
          ar_done_reg <= '1';
        else
          ar_done_reg <= '0';
        end if;
        if(ar_done_reg = '1') then
          rfc_count_reg <= '1';
        elsif (init_done = '1' and init_mem = '0' and rfc_count = "00000000")
        then
          rfc_count_reg <= '1';
        elsif (auto_ref_issued = '1') then
          rfc_count_reg <= '0';
        else
          rfc_count_reg <= rfc_count_reg;
        end if;
      end if;
    end if;
  end process;
 
--******************************************************************************
-- Initialization state machine
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        init_current_state <= INIT_IDLE;
      else
        init_current_state <= init_next_state;
      end if;
    end if;
  end process;
 
  process (rst180_r, init_count, init_current_state, init_memory, count6,
           init_pre_count)
  begin
    if rst180_r = '1' then
      init_next_state             <= INIT_IDLE;
    else
      case init_current_state is
        when INIT_IDLE    =>
          if init_memory = '1' then
            case init_count is
              when "0000" =>
                if(init_pre_count = "0000001") then
                  init_next_state <= INIT_PRECHARGE;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0001" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0010" =>
                -- for reseting DLL in Base Mode register
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0011" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;  -- For EMR
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0100" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;  -- For EMR
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0101" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_PRECHARGE;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0110" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_AUTO_REFRESH;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "0111" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_AUTO_REFRESH;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "1000" =>
                -- to deactivate the rst DLL bit in the LMR
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "1001" =>
                -- to set OCD to default in EMR
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "1010" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_LOAD_MODE_REG;  --  OCD exit in EMR
                else
                  init_next_state <= INIT_IDLE;
                end if;
              when "1011" =>
                if (count6 = "00000000") then
                  init_next_state <= INIT_IDLE;
                else
                  init_next_state <= init_current_state;
                end if;
              when others =>
                init_next_state   <= INIT_IDLE;
            end case;
          else
            init_next_state <= INIT_IDLE;
          end if;
        when INIT_PRECHARGE =>
          init_next_state <= INIT_IDLE;
        when INIT_LOAD_MODE_REG =>
          init_next_state <= INIT_IDLE;
        when INIT_AUTO_REFRESH =>
          init_next_state <= INIT_IDLE;
        when others =>
          init_next_state <= INIT_IDLE;
      end case;
    end if;
  end process;
 
--******************************************************************************
-- MAIN state machine
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        current_state <= IDLE;
      else
        current_state <= next_state;
      end if;
    end if;
  end process;
 
  process (rst180_r, cas_count, wr_count,
           go_to_active, write_cmd1, read_cmd3, current_state,
           wrburst_end, wrburst_end_cnt,
           rdburst_end, init_memory,rcd_count, ras_count,
           auto_ref, rfc_count_reg, rp_count)
  begin
    if rst180_r = '1' then
      next_state         <= IDLE;
    else
      case current_state is
 
        when IDLE =>
          if (init_memory = '0') then
            if(auto_ref = '1' and rfc_count_reg = '1' and rp_count = "000") then
              next_state <= AUTO_REFRESH;  -- normal Refresh in the IDLE state
            elsif go_to_active = '1' then
              next_state <= ACTIVE;
            else
              next_state <= IDLE;
            end if;
          else
            next_state   <= IDLE;
          end if;
 
        when PRECHARGE =>
          next_state <= IDLE;
 
        when AUTO_REFRESH =>
          next_state <= IDLE;
 
        when ACTIVE =>
          next_state <= ACTIVE_WAIT;
 
        when ACTIVE_WAIT =>
          if (rcd_count = "000" and write_cmd1 = '1') then
            next_state <= FIRST_WRITE;
          elsif (rcd_count = "000" and read_cmd3 = '1') then
            next_state <= BURST_READ;
          else
            next_state <= ACTIVE_WAIT;
          end if;
 
        when FIRST_WRITE =>
          next_state <= WRITE_WAIT;
 
        when WRITE_WAIT =>
          case wrburst_end is
            when '1' =>
              next_state <= PRECHARGE_AFTER_WRITE;
            when '0' =>
              if wrburst_end_cnt = "010" then
                next_state <= BURST_WRITE;
              else
                next_state <= WRITE_WAIT;
              end if;
            when others =>
              next_state   <= WRITE_WAIT;
          end case;
 
        when BURST_WRITE =>
          next_state <= WRITE_WAIT;
 
        when PRECHARGE_AFTER_WRITE =>
          next_state <= PRECHARGE_AFTER_WRITE_2;
 
        when PRECHARGE_AFTER_WRITE_2 =>
          if(wr_count = "00" and ras_count = "00000") then   
            next_state <= PRECHARGE;
          else
            next_state <= PRECHARGE_AFTER_WRITE_2;
          end if;
 
        when READ_WAIT  =>
          case rdburst_end is
            when '1'    =>
              next_state   <= PRECHARGE_AFTER_WRITE;
            when '0'    =>
              if cas_count = "001" then
                next_state <= BURST_READ;
              else
                next_state <= READ_WAIT;
              end if;
            when others =>
              next_state   <= READ_WAIT;
          end case;
 
        when BURST_READ =>
          next_state <= READ_WAIT;
 
        when others =>
          next_state <= IDLE;
      end case;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        ddr_address1 <= (others => '0');
      elsif (init_mem = '1') then
        case (init_count) is
          when "0000" | "0101" =>
            ddr_address1 <= addr_const1((ROW_ADDRESS - 1) downto 0);
          when "0001"               =>
            ddr_address1 <= (others => '0');
          when "0010"               =>
            ddr_address1 <= (others => '0');
          when "0011"               =>
            ddr_address1 <= emr;
          when "0100"               =>
            ddr_address1 <= lmr_dll_rst;
          when "1000"               =>
            ddr_address1 <= lmr_dll_set;
          when "1001"               =>
            ddr_address1 <= emr or addr_const2((ROW_ADDRESS - 1) downto 0);
          when "1010"               =>
            ddr_address1 <= emr and addr_const3((ROW_ADDRESS - 1) downto 0);
          when others               =>
            ddr_address1 <= (others => '0');
        end case;
      elsif (current_state = PRECHARGE) then
        ddr_address1 <= addr_const1((ROW_ADDRESS - 1) downto 0);
      elsif (current_state = ACTIVE) then
        ddr_address1 <= row_address_reg;
      elsif (current_state = BURST_WRITE or current_state = FIRST_WRITE or
             current_state = BURST_READ) then
        ddr_address1 <= column_address_reg((ROW_ADDRESS - 1) downto 0);
      else
        ddr_address1 <= (others => '0');
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        ddr_ba1     <= (others => '0');
      elsif (init_mem = '1') then
        case (init_count) is
          when "0001" =>
            ddr_ba1 <= ba_const1((BANK_ADDRESS -1) downto 0);
          when "0010" =>
            ddr_ba1 <= ba_const2((BANK_ADDRESS -1) downto 0);
          when "0011" | "1001" | "1010" =>
            ddr_ba1 <= ba_const3((BANK_ADDRESS -1) downto 0);
          when others =>
            ddr_ba1 <= (others => '0');
        end case;
      elsif (current_state = ACTIVE or current_state = FIRST_WRITE or
             current_state = BURST_WRITE or current_state = BURST_READ) then
        ddr_ba1     <= ba_address_reg2;
      else
        ddr_ba1     <= (others => '0');
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        odt_deassert <= '0';
      elsif(wrburst_end_3 = '1') then
        odt_deassert <= '1';
      elsif(write_cmd3 = '0') then
        odt_deassert <= '0';
      else
        odt_deassert <= odt_deassert;
      end if;
    end if;
  end process;
 
  ddr_odt1 <= '1' when (write_cmd3 = '1' and (emr(6) = '1' or emr(2) = '1') and
                        odt_deassert = '0') else '0';
 
--******************************************************************************
-- Register CONTROL SIGNALS outputs
--******************************************************************************
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        ddr_odt2  <= '0';
        ddr_rasb2 <= '1';
        ddr_casb2 <= '1';
        ddr_web2  <= '1';
      else
        ddr_odt2  <= ddr_odt1;
        ddr_rasb2 <= ddr_rasb1;
        ddr_casb2 <= ddr_casb1;
        ddr_web2  <= ddr_web1;
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if clk'event and clk = '0' then
      if rst180_r = '1' then
        ddr_odt_cntrl <= '0';
      else
        ddr_odt_cntrl <= ddr_odt2;
      end if;
    end if;
  end process;
 
--******************************************************************************
-- control signals to the Memory
--******************************************************************************
 
  ddr_rasb1 <= '0' when (current_state = ACTIVE or current_state = PRECHARGE or
                         current_state = AUTO_REFRESH or
                         init_current_state = INIT_PRECHARGE or
                         init_current_state = INIT_AUTO_REFRESH or
                         init_current_state = INIT_LOAD_MODE_REG) else '1';
 
  ddr_casb1 <= '0' when (current_state = BURST_READ or
                         current_state = BURST_WRITE or
                         current_state = FIRST_WRITE or
                         current_state = AUTO_REFRESH or
                         init_current_state = INIT_AUTO_REFRESH or
                         init_current_state = INIT_LOAD_MODE_REG) else '1';
 
  ddr_web1 <= '0' when (current_state = BURST_WRITE or
                        current_state = FIRST_WRITE or
                        current_state = PRECHARGE or
                        init_current_state = INIT_PRECHARGE or
                        init_current_state = INIT_LOAD_MODE_REG) else '1';
 
-------------------------------------------------------------------------------
 
  process(clk)
  begin
    if(clk'event and clk = '0') then
      if rst180_r = '1' then
        dqs_div_cascount     <= "000";
      else
        if(ddr_rasb2 = '1' and ddr_casb2 = '0' and ddr_web2 = '1') then
          dqs_div_cascount   <= burst_cnt_max;
        else
          if dqs_div_cascount /= "000" then
            dqs_div_cascount <= dqs_div_cascount - "001";
          else
            dqs_div_cascount <= dqs_div_cascount;
          end if;
        end if;
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if(clk'event and clk = '0') then
      if rst180_r = '1' then
        dqs_div_rdburstcount     <= "000";
      else
        if (dqs_div_cascount = "001" and burst_length = "010") then
          dqs_div_rdburstcount   <= "010";
        elsif (dqs_div_cascount = "011" and burst_length = "011") then
          dqs_div_rdburstcount   <= "100";
        else
          if dqs_div_rdburstcount /= "000" then
            dqs_div_rdburstcount <= dqs_div_rdburstcount - "001";
          else
            dqs_div_rdburstcount <= dqs_div_rdburstcount;
          end if;
        end if;
      end if;
    end if;
  end process;
 
  process(clk)
  begin
    if(clk'event and clk = '0') then
      if rst180_r = '1' then
        rst_dqs_div_r     <= '0';
      else
        if (dqs_div_cascount = "001" and burst_length = "010")then
          rst_dqs_div_r   <= '1';
        elsif (dqs_div_cascount = "011" and burst_length = "011")then
          rst_dqs_div_r   <= '1';
        else
          if (dqs_div_rdburstcount = "001" and dqs_div_cascount = "000") then
            rst_dqs_div_r <= '0';
          else
            rst_dqs_div_r <= rst_dqs_div_r;
          end if;
        end if;
      end if;
    end if;
  end process;
 
  process(clk)                          -- For Reg dimm
  begin
    if(clk'event and clk = '0') then
      rst_dqs_div_r1 <= rst_dqs_div_r;
    end if;
  end process;
 
  process (clk)
  begin
    if (clk'event and clk = '0') then
      if (dqs_div_cascount /= "000" or dqs_div_rdburstcount /= "000") then
        rst_calib <= '1';
      else
        rst_calib <= '0';
      end if;
    end if;
  end process;
 
  rst_iob_out : FD
    port map (
      Q => rst_dqs_div_int1,
            D => rst_dqs_div_r, 
      C => clk
      );
 
--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. 
  process(clk)
  begin
    if clk'event and clk = '0' then
      read_fifo_rden <= rst_dqs_div_r1;
    end if;
  end process;
end arc;
 

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.