📄 sdr_ctrl.vhd
字号:
---------------------------------------------------------------------------------------------------
--
-- Title : SDR_CTRL
-- Design : SDR_controller
-- Author : Michal Krepa
-- Company : XXX
--
---------------------------------------------------------------------------------------------------
--
-- File : SDR_CTRL.vhd
-- Generated : Tue Sep 16 10:07:58 2003
-- From : interface description file
-- By : Itf2Vhdl ver. 1.20
--
---------------------------------------------------------------------------------------------------
--
-- Description : Single data rate SDRAM controller
-- FEATURES:
-- support for read burst size of one/two/four/eight
-- write single access location
-- CAS latency = 1,2 or 3
-- editable timing parameters
-- pipelined operation
-- supports the NOP, READ, WRITE, AUTO_REFRESH, PRECHARGE, ACTIVATE,
-- and LOAD_MR commands
-- LIMITATIONS:
-- support for 32 bits data-path width only
-- does not support BURST_STOP command
-- burst write is not supported
---------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity SDR_CTRL is
port(
CLK : in STD_LOGIC;
nRST : in std_logic;
ADDR : in std_logic_vector(20 downto 0);
DATA_IN : in std_logic_vector(31 downto 0);
DATA_OUT_SDR : out std_logic_vector(31 downto 0);
nDTACK : out std_logic;
WnR : in std_logic;
nAS : in std_logic;
nLBE : in std_logic_vector(3 downto 0);
-- sdram signals
nCS : out STD_LOGIC;
nRAS : out STD_LOGIC;
nCAS : out STD_LOGIC;
nWE : out STD_LOGIC;
BS : out STD_LOGIC_vector(1 downto 0);
CKE : out STD_LOGIC;
DQM : out STD_LOGIC_VECTOR(3 downto 0);
A : out STD_LOGIC_VECTOR(10 downto 0)
);
end SDR_CTRL;
architecture SDR_CTRL of SDR_CTRL is
-- burst size
-- "000" burst size of 1
-- "001" b.s. of 2
-- "010" b.s. of 4
-- "011" b.s. of 8
constant burst_size : std_logic_vector(2 downto 0) := "011";
constant CLOCK_PERIOD : positive := 30; -- in ns
-- timing constants in ns:
constant tRC : positive := 65;
constant tRCD : positive := 20;
constant tRP : positive := 20;
constant tREF : positive := 15000; -- for 1 row (for 4096 you need to divide number by 4096)
constant tRFC : positive := 65;
constant tWR : positive := CLOCK_PERIOD + 7;
-- sdram initialization time
-- fo eg.: if 100 us sdram initialization is needed, tSTARTUP_NOP should be 100000 [ns]
constant tSTARTUP_NOP : positive := 100000;
-- timing constants in cycles
-- actual cycles will be one cycle longer (every) because of state transition time (1 cycle time)
constant tRC_CYCLES : natural := tRC / CLOCK_PERIOD; -- tRC_time = tRC_CYCLES + 1
constant tRCD_CYCLES : natural := tRCD / CLOCK_PERIOD; -- tRCD_time = tRCD_CYCLES + 1
constant tRP_CYCLES : natural := tRP / CLOCK_PERIOD; -- tRP_time = tRP_CYCLES + 1
constant tMRD_CYCLES : natural := 2; -- tMRD_time = 2 tCK
constant tREF_CYCLES : natural := tREF / CLOCK_PERIOD; -- tREF_time = tREF_CYCLES + 1
constant tRFC_CYCLES : NATURAL := tRFC / CLOCK_PERIOD; -- tRFC_time = tRFC_CYCLES + 1
constant tWR_CYCLES : natural := tWR / CLOCK_PERIOD; -- tWR_time = tWR_CYCLES + 1
constant tSTARTUP_NOP_CYCLES : positive := tSTARTUP_NOP / (2*CLOCK_PERIOD);
constant CAS_LATENCY : positive := 2;
-- specified to supress simulation warnings from micron sdram models
constant hold_time: time:= 2 ns;
type state_type is (
initialize,
active,
read_data,
read,
write,
set_ModeRegister,
precharge,
auto_refresh,
nop
);
signal state : state_type;
signal refresh_req : std_logic; -- Refresh request signals
signal refresh_done_flg : std_logic;
signal refresh_timer : integer range 0 to tREF_CYCLES;
signal startup_timer : integer range 0 to tSTARTUP_NOP_CYCLES;
signal startup_pending : std_logic; -- '1' - in startup sequence
signal wait_counter : integer range 0 to 15; -- how many cycles wait until next command can be issued
signal twice_autorefresh : std_logic; -- double autorefresh command needed in startup sequence
signal nAS_WAITING : std_logic; -- if read/write is waiting to be executed
signal CAS_counter : integer range 0 to 3;
signal execute_nop : std_logic;
signal nLBE_s : std_logic_vector(3 downto 0);
signal aref_enable : std_logic; -- autorefresh enable
signal bank_numb : std_logic_vector(1 downto 0);
signal row_addr : std_logic_vector(10 downto 0);
signal col_addr : std_logic_vector(7 downto 0);
signal WnR_S : std_logic;
signal burst_counter : integer range 0 to 7;
begin
-- Hold nAS
-- nAS - active low address strobe
ADS_DETECT: process(nRST, CLK)
begin
if nRST = '0' then
nAS_WAITING <= '0';
bank_numb <= (others => '0');
col_addr <= (others => '0');
row_addr <= (others => '0');
DATA_OUT_SDR <= (others => '0');
nLBE_s <= (others => '1');
elsif rising_edge(CLK) then
-- if address strobe latch address
if nAS='0' then
nAS_WAITING <= '1';
bank_numb <= ADDR(20 downto 19) after hold_time;
row_addr <= ADDR(18 downto 8) after hold_time;
col_addr <= ADDR(7 downto 0) after hold_time;
DATA_OUT_SDR <= DATA_IN after hold_time;
nLBE_s <= nLBE;
elsif state = active then
nAS_WAITING <= '0';
end if;
end if;
end process;
sdram_ctrl : process(CLK, nRST)
begin
if nRST = '0' then
CKE <= '0';
DQM <= (others => '1');
nCS <= '1';
nRAS <= '1';
nCAS <= '1';
nWE <= '1';
BS <= "00";
A <= (others => '0');
state <= initialize;
startup_pending <= '1';
wait_counter <= 0;
twice_autorefresh <= '1';
nDTACK <= '1';
CAS_counter <= 0;
burst_counter <= 0;
startup_timer <= 0;
refresh_done_flg <= '0';
WnR_S <= '0';
execute_nop <= '0';
aref_enable <= '1';
elsif rising_edge(CLK) then
case state is
--------------------------
-- initialization
--------------------------
when initialize =>
CKE <= '1';
nCS <= '0';
state <= nop after hold_time;
-----------------------------
-- MODE REGISTER SET command
-----------------------------
when set_ModeRegister =>
nCS <= '0' after hold_time;
nRAS <= '0' after hold_time;
nCAS <= '0' after hold_time;
nWE <= '0' after hold_time;
A <= '0' -- should be '0' to ensure compability with future devices
& '1' -- write burst mode: '0' - programmed burst length; '1' - single acces location
& "00" -- operation mode: "00" - standard; others - reserved
& conv_std_logic_vector(CAS_Latency,3) -- CAS Latency
& '0' -- Burst Mode: '0' - sequence; '1' - interleave
& burst_size; -- BURST LENGTH of 8
-- after MRS command issue n nop cycles where n = tMRD_CYCLES
if execute_nop = '1' then
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
end if;
-- wait for tMRD_CYCLES before issue
if wait_counter < tMRD_CYCLES then
wait_counter <= wait_counter + 1;
execute_nop <= '1';
else
-- sdram initialization complete
wait_counter <= 0;
startup_pending <= '0';
nDTACK <= '0' after hold_time;
state <= nop after hold_time;
execute_nop <= '0';
end if;
--------------------------
-- NOP command
--------------------------
when nop =>
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
DQM <= (others => '0') after hold_time;
WnR_S <= WnR after hold_time;
execute_nop <= '0';
nDTACK <= '1' after hold_time;
if startup_pending = '1' then
if startup_timer < tSTARTUP_NOP_CYCLES then
startup_timer <= startup_timer + 1;
state <= initialize after hold_time;
else
state <= precharge after hold_time;
end if;
elsif refresh_req = '1' and aref_enable = '1' then
refresh_done_flg <= '1';
state <= auto_refresh after hold_time;
elsif nAS_WAITING = '1' then
aref_enable <= '0';
refresh_done_flg <= '0';
state <= active after hold_time;
else
refresh_done_flg <= '0';
end if;
--------------------------
-- PRECHARGE command
--------------------------
when precharge =>
nCS <= '0' after hold_time;
nRAS <= '0' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '0' after hold_time;
A(10) <= '1'; -- precharge all banks
if execute_nop = '1' then
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
end if;
-- if burst size 1 or 2
if burst_size(2 downto 1) = "00" then
nDTACK <= '1';
end if;
if wait_counter < tRP_CYCLES then
wait_counter <= wait_counter + 1;
execute_nop <= '1';
else
execute_nop <= '0';
wait_counter <= 0;
if startup_pending = '1' then
state <= auto_refresh after hold_time;
else
state <= nop after hold_time;
end if;
end if;
-------------------------
-- AUTO REFRESH command
-------------------------
when auto_refresh =>
nCS <= '0' after hold_time;
nRAS <= '0' after hold_time;
nCAS <= '0' after hold_time;
nWE <= '1' after hold_time;
if execute_nop = '1' then
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
end if;
if wait_counter < (tRFC_CYCLES-1)+conv_integer(startup_pending) then
wait_counter <= wait_counter + 1;
execute_nop <= '1';
else
execute_nop <= '0';
wait_counter <= 0;
if twice_autorefresh = '1' then
twice_autorefresh <= '0';
else
if startup_pending = '1' then
state <= set_ModeRegister after hold_time;
else
state <= nop after hold_time;
end if;
end if;
end if;
-------------------------
-- ACTIVE command
-------------------------
when active =>
nCS <= '0' after hold_time;
nRAS <= '0' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
A <= row_addr after hold_time;
BS(1 downto 0) <= bank_numb after hold_time;
if execute_nop = '1' then
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
end if;
if wait_counter < tRCD_CYCLES then
wait_counter <= wait_counter + 1;
execute_nop <= '1';
else
execute_nop <= '0';
wait_counter <= 0;
if WnR_S = '1' then
state <= write after hold_time;
nDTACK <= '0' after hold_time;
else
state <= read after hold_time;
end if;
end if;
------------------------
-- READ command
------------------------
when read =>
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '0' after hold_time;
nWE <= '1' after hold_time;
DQM <= (others => '0') after hold_time;
A(7 downto 0) <= col_addr after hold_time;
A(10) <= '0';
if execute_nop = '1' then
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
end if;
if CAS_counter < CAS_LATENCY then
CAS_counter <= CAS_counter + 1;
execute_nop <= '1';
else
if burst_size = "000" then
state <= precharge after hold_time;
aref_enable <= '1';
execute_nop <= '0';
nDTACK <= '0' after hold_time;
else
CAS_counter <= 0;
execute_nop <= '0';
nDTACK <= '0' after hold_time;
state <= read_data after hold_time;
end if;
end if;
case burst_size is
-- burst size of 2
when "001" =>
wait_counter <= 5;
-- burst size of 4
when "010" =>
wait_counter <= 4;
-- burst size of 8 or no burst
when others =>
wait_counter <= 0;
end case;
------------------------
-- reading data
------------------------
when read_data =>
if wait_counter = 5 then
state <= precharge after hold_time;
aref_enable <= '1';
wait_counter <= 0;
else
wait_counter <= wait_counter + 1;
end if;
------------------------
-- WRITE command
------------------------
when write =>
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '0' after hold_time;
nWE <= '0' after hold_time;
DQM <= nLBE_s after hold_time;
A(10) <= '0'; -- disable autoprecharge
A(9 downto 8) <= "00" after hold_time;
A(7 downto 0) <= col_addr after hold_time;
nDTACK <= '1' after hold_time;
if execute_nop = '1' then
nCS <= '0' after hold_time;
nRAS <= '1' after hold_time;
nCAS <= '1' after hold_time;
nWE <= '1' after hold_time;
end if;
if wait_counter < tWR_CYCLES then
wait_counter <= wait_counter + 1;
execute_nop <= '1';
else
execute_nop <= '0';
wait_counter <= 0;
aref_enable <= '1';
state <= precharge after hold_time;
end if;
when others =>
nDTACK <= '1' after hold_time;
state <= nop;
nCS <= '1';
nRAS <= '1';
nCAS <= '1';
nWE <= '1';
BS <= (others => '0');
CKE <= '1';
DQM <= (others => '1');
A <= (others => '0');
end case;
end if;
end process;
-- generate refresh counts and requests
refresh_process: process (CLK, nRST) is
begin
if nRST = '0' then
refresh_timer <= 0;
refresh_req <= '0';
elsif rising_edge(CLK) then
if refresh_timer < tREF_CYCLES then
refresh_req <= '0';
refresh_timer <= refresh_timer + 1;
elsif refresh_done_flg = '1' then
refresh_req <= '0';
refresh_timer <= 0;
else
refresh_req <= '1';
end if;
end if;
end process refresh_process;
end SDR_CTRL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -