--########################################################################### -- -- LOGIC CORE: Control Interface - Top level module -- MODULE NAME: control_interface() -- COMPANY: Altera Corporation -- www.altera.com -- -- REVISION HISTORY: -- -- Revision 1.1 06/06/2000 Description: Initial Release. -- -- FUNCTIONAL DESCRIPTION: -- -- This module is the command interface module for the SDR SDRAM controller. -- -- Copyright (C) 1991-2000 Altera Corporation -- --########################################################################## library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity control_interface is generic (ASIZE : integer := 32); port ( CLK : in std_logic; -- System Clock RESET_N : in std_logic; -- System Reset CMD : in std_logic_vector(2 downto 0); -- Command input ADDR : in std_logic_vector(ASIZE-1 downto 0); -- Address REF_ACK : in std_logic; -- Refresh request acknowledge CM_ACK : in std_logic; -- Command acknowledge NOP : out std_logic; -- Decoded NOP command READA : out std_logic; -- Decoded READA command WRITEA : out std_logic; -- Decoded WRITEA command REFRESH : out std_logic; -- Decoded REFRESH command PRECHARGE : out std_logic; -- Decoded PRECHARGE command LOAD_MODE : out std_logic; -- Decoded LOAD_MODE command SADDR : out std_logic_vector(ASIZE-1 downto 0); -- Registered version of ADDR SC_CL : out std_logic_vector(1 downto 0); -- Programmed CAS latency SC_RC : out std_logic_vector(1 downto 0); -- Programmed RC delay SC_RRD : out std_logic_vector(3 downto 0); -- Programmed RRD delay SC_PM : out std_logic; -- programmed Page Mode SC_BL : out std_logic_vector(3 downto 0); -- Programmed burst length REF_REQ : out std_logic; -- Hidden refresh request CMD_ACK : out std_logic -- Command acknowledge ); end control_interface; architecture RTL of control_interface is -- signal declarations signal LOAD_REG1 : std_logic; signal LOAD_REG2 : std_logic; signal REF_PER : std_logic_vector(15 downto 0); signal timer : signed(15 downto 0); signal timer_zero : std_logic; signal SADDR_int : std_logic_vector(ASIZE-1 downto 0); signal CMD_ACK_int : std_logic; signal SC_BL_int : std_logic_vector(3 downto 0); begin -- This module decodes the commands from the CMD input to individual -- command lines, NOP, READA, WRITEA, REFRESH, PRECHARGE, LOAD_MODE. -- ADDR is register in order to keep it aligned with decoded command. process(CLK, RESET_N) begin if (RESET_N = '0') then NOP <= '0'; READA <= '0'; WRITEA <= '0'; REFRESH <= '0'; PRECHARGE <= '0'; LOAD_MODE <= '0'; load_reg1 <= '0'; load_reg2 <= '0'; SADDR_int <= (others => '0'); elsif rising_edge(CLK) then SADDR_int <= ADDR; -- register the address to keep proper -- alignment with the command if (CMD = "000") then -- NOP command NOP <= '1'; else NOP <= '0'; end if; if (CMD = "001") then -- READA command READA <= '1'; else READA <= '0'; end if; if (CMD = "010") then -- WRITEA command WRITEA <= '1'; else WRITEA <= '0'; end if; if (CMD = "011") then -- REFRESH command REFRESH <= '1'; else REFRESH <= '0'; end if; if (CMD = "100") then -- PRECHARGE command PRECHARGE <= '1'; else PRECHARGE <= '0'; end if; if (CMD = "101") then -- LOAD_MODE command LOAD_MODE <= '1'; else LOAD_MODE <= '0'; end if; if ((CMD = "110") and (LOAD_REG1 = '0')) then --LOAD_REG1 command LOAD_REG1 <= '1'; else LOAD_REG1 <= '0'; end if; if ((CMD = "111") and (LOAD_REG2 = '0')) then --LOAD_REG2 command LOAD_REG2 <= '1'; else LOAD_REG2 <= '0'; end if; end if; end process; -- This always block processes the LOAD_REG1 and LOAD_REG2 commands. -- The register data comes in on SADDR and is distributed to the various -- registers. process(CLK, RESET_N) begin if (RESET_N = '0') then SC_CL <= (others => '0'); SC_RC <= (others => '0'); SC_RRD <= (others => '0'); SC_PM <= '0'; SC_BL_int <= (others => '0'); REF_PER <= (others => '0'); elsif rising_edge(CLK) then if (LOAD_REG1 = '1') then -- LOAD_REG1 command SC_CL <= SADDR_int(1 downto 0); -- CAS Latency SC_RC <= SADDR_int(3 downto 2); -- RC delay SC_RRD <= SADDR_int(7 downto 4); -- RRD delay SC_PM <= SADDR_int(8); -- Page Mode SC_BL_int <= SADDR_int(12 downto 9); -- Burst length end if; if (LOAD_REG2 = '1') then -- LOAD_REG2 command REF_PER <= SADDR_int(15 downto 0); -- REFRESH Period end if; end if; end process; SADDR <= SADDR_int; SC_BL <= SC_BL_int; -- This always block generates the command acknowledge, CMD_ACK, for the -- commands that are handled by this module, LOAD_RE1,2, and it lets -- the command ack from the lower module pass through when necessary. process(CLK, RESET_N) begin if (RESET_N = '0') then CMD_ACK_int <= '0'; elsif rising_edge(CLK) then if (((CM_ACK = '1') or (LOAD_REG1 = '1') or (LOAD_REG2 = '1')) and (CMD_ACK_int = '0')) then CMD_ACK_int <= '1'; else CMD_ACK_int <= '0'; end if; end if; end process; CMD_ACK <= CMD_ACK_int; -- This always block implements the refresh timer. The timer is a 16bit -- downcounter and a REF_REQ is generated whenever the counter reaches the -- count of zero. After reaching zero, the counter reloads with the value that -- was loaded into the refresh period register with the LOAD_REG2 command. -- Note that the refresh counter is disabled when the controller is in -- page mode operation. process(CLK, RESET_N) begin if (RESET_N = '0') then timer <= (others => '0'); timer_zero <= '0'; REF_REQ <= '0'; elsif rising_edge(CLK) then if (timer_zero = '1') then timer <= signed(REF_PER); elsif (not (SC_BL_int = "0000")) then -- only run timer if not in page mode timer <= timer - 1; end if; if (timer=0 and not (SC_BL_int = "0000")) then timer_zero <= '1'; -- count has reached zero, issue ref_req and reload REF_REQ <= '1'; -- the timer else if (REF_ACK = '1') then -- wait for the ack to come back from the lower timer_zero <= '0'; REF_REQ <= '0'; end if; end if; end if; end process; end RTL;