summaryrefslogtreecommitdiffstats
path: root/misc/ddrsdram
diff options
context:
space:
mode:
Diffstat (limited to 'misc/ddrsdram')
-rw-r--r--misc/ddrsdram/simscripts/ddr_tb.do16
-rw-r--r--misc/ddrsdram/simscripts/ddr_top.do104
-rw-r--r--misc/ddrsdram/simsrc/ddr_tb.vhd301
-rw-r--r--misc/ddrsdram/src/ddr_pkg.vhd107
-rw-r--r--misc/ddrsdram/src/ddr_top.vhd743
-rw-r--r--misc/ddrsdram/src/mt46v16m16.vhd1320
6 files changed, 2591 insertions, 0 deletions
diff --git a/misc/ddrsdram/simscripts/ddr_tb.do b/misc/ddrsdram/simscripts/ddr_tb.do
new file mode 100644
index 0000000..1f643f1
--- /dev/null
+++ b/misc/ddrsdram/simscripts/ddr_tb.do
@@ -0,0 +1,16 @@
+vlib work
+vcom -93 -explicit ../src/ddr_pkg.vhd
+vcom -93 -explicit ../src/ddr_top.vhd
+vcom -93 -explicit ../src/mt46v16m16.vhd
+vcom -93 -explicit ../simsrc/ddr_tb.vhd
+vsim -t 1ps ddr_tb
+view wave
+view signals
+radix hex
+add wave *
+add wave sim:/ddr_tb/ddr_ctrl/*
+force -freeze sim:/ddr_tb/areset 1 0
+run 10 ns
+force -freeze sim:/ddr_tb/areset 0 0
+when sim:/ddr_tb/break_out stop
+run 10 ms \ No newline at end of file
diff --git a/misc/ddrsdram/simscripts/ddr_top.do b/misc/ddrsdram/simscripts/ddr_top.do
new file mode 100644
index 0000000..141e164
--- /dev/null
+++ b/misc/ddrsdram/simscripts/ddr_top.do
@@ -0,0 +1,104 @@
+vlib work
+vcom -93 -explicit ../src/ddr_pkg.vhd
+vcom -93 -explicit ../src/ddr_top.vhd
+vsim -t 1ps ddr_top
+view wave
+view signals
+radix hex
+# Add wave signals
+
+add wave -divider "System"
+add wave sim:/ddr_top/areset
+add wave sim:/ddr_top/cpu_clk
+add wave sim:/ddr_top/cpu_clk_2x
+add wave sim:/ddr_top/cpu_clk_4x
+add wave sim:/ddr_top/ddr_in_clk
+add wave sim:/ddr_top/ddr_in_clk_2x
+
+add wave -divider "Ctrl interface"
+add wave sim:/ddr_top/cpu_clk
+add wave sim:/ddr_top/ddr_data_read
+add wave sim:/ddr_top/ddr_data_write
+add wave sim:/ddr_top/ddr_req
+add wave sim:/ddr_top/ddr_rd_wr_n
+add wave sim:/ddr_top/ddr_req_len
+add wave sim:/ddr_top/ddr_read_en
+add wave sim:/ddr_top/ddr_write_en
+add wave sim:/ddr_top/ddr_command
+add wave sim:/ddr_top/ddr_command_we
+
+add wave -divider "DDR interface"
+add wave sim:/ddr_top/sdr_clk_p
+add wave sim:/ddr_top/sdr_clk_n_p
+add wave sim:/ddr_top/cke_q_p
+add wave sim:/ddr_top/cs_qn_p
+add wave sim:/ddr_top/ras_qn_p
+add wave sim:/ddr_top/cas_qn_p
+add wave sim:/ddr_top/we_qn_p
+add wave sim:/ddr_top/dm_q_p
+add wave sim:/ddr_top/dqs_q_p
+add wave sim:/ddr_top/ba_q_p
+add wave sim:/ddr_top/sdr_a_p
+add wave sim:/ddr_top/sdr_d_p
+
+add wave -divider "Internal signals"
+add wave sim:/ddr_top/clk2_phase
+add wave sim:/ddr_top/clk4_phase
+add wave sim:/ddr_top/ddr_state
+add wave sim:/ddr_top/sdr_oe_n
+add wave sim:/ddr_top/sdr_smp
+add wave sim:/ddr_top/sdr_d
+
+
+# Add input signals
+force -freeze sim:/ddr_top/cpu_clk_4x 1 0, 0 {1.875 ns} -r 3.75 ns
+run 100 ps
+force -freeze sim:/ddr_top/cpu_clk_2x 1 0, 0 {3.75 ns} -r 7.5 ns
+run 100 ps
+force -freeze sim:/ddr_top/cpu_clk 1 0, 0 {7.5 ns} -r 15 ns
+force -freeze sim:/ddr_top/ddr_in_clk 1 2ns, 0 {5.75 ns} -r 7.5 ns
+force -freeze sim:/ddr_top/ddr_in_clk_2x 0 0.125ns, 1 {2 ns} -r 3.75 ns
+
+force -freeze sim:/ddr_top/areset 1 0
+force -freeze sim:/ddr_top/ddr_command 0000 0
+force -freeze sim:/ddr_top/ddr_command_we 0 0
+force -freeze sim:/ddr_top/ddr_data_write 1234abcd 0
+force -freeze sim:/ddr_top/ddr_req 0 0
+force -freeze sim:/ddr_top/ddr_req_adr 000000 0
+force -freeze sim:/ddr_top/ddr_rd_wr_n 0 0
+force -freeze sim:/ddr_top/ddr_req_len 0 0
+
+# Start simulation
+run 45 ns
+force -freeze sim:/ddr_top/areset 0 0
+run 92 ns
+# DDR Command
+force -freeze sim:/ddr_top/ddr_command 000A 0
+force -freeze sim:/ddr_top/ddr_command_we 1 0
+run 15 ns
+force -freeze sim:/ddr_top/ddr_command 0000 0
+force -freeze sim:/ddr_top/ddr_command_we 0 0
+run 90 ns
+# DDR Read
+force -freeze sim:/ddr_top/ddr_req 1 0
+force -freeze sim:/ddr_top/ddr_req_adr 00ABCD 0
+force -freeze sim:/ddr_top/ddr_rd_wr_n 1 0
+force -freeze sim:/ddr_top/ddr_req_len 0 0
+run 15 ns
+force -freeze sim:/ddr_top/ddr_req 0 0
+force -freeze sim:/ddr_top/ddr_req_adr 000000 0
+force -freeze sim:/ddr_top/ddr_rd_wr_n 0 0
+force -freeze sim:/ddr_top/ddr_req_len 0 0
+run 150 ns
+# DDR Write
+force -freeze sim:/ddr_top/ddr_req 1 0
+force -freeze sim:/ddr_top/ddr_req_adr 00ABCD 0
+force -freeze sim:/ddr_top/ddr_rd_wr_n 0 0
+force -freeze sim:/ddr_top/ddr_req_len 0 0
+run 15 ns
+force -freeze sim:/ddr_top/ddr_req 0 0
+force -freeze sim:/ddr_top/ddr_req_adr 000000 0
+force -freeze sim:/ddr_top/ddr_rd_wr_n 0 0
+force -freeze sim:/ddr_top/ddr_req_len 0 0
+run 180 ns
+
diff --git a/misc/ddrsdram/simsrc/ddr_tb.vhd b/misc/ddrsdram/simsrc/ddr_tb.vhd
new file mode 100644
index 0000000..92d1e4b
--- /dev/null
+++ b/misc/ddrsdram/simsrc/ddr_tb.vhd
@@ -0,0 +1,301 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+library work;
+use work.ddr.all;
+
+entity ddr_tb is
+ port ( areset : in std_logic;
+ break_out : out std_logic);
+end ddr_tb;
+
+architecture behave of ddr_tb is
+
+signal cpu_clk : std_logic;
+signal cpu_clk_2x : std_logic;
+signal cpu_clk_4x : std_logic;
+signal ddr_in_clk : std_logic;
+signal ddr_in_clk_2x : std_logic;
+
+signal ddr_command : std_logic_vector(15 downto 0);
+signal ddr_command_we : std_logic;
+
+signal ddr_data_read : std_logic_vector(31 downto 0); -- Data read from DDR SDRAM
+signal ddr_data_write : std_logic_vector(35 downto 0); -- Data to be written to DDR SDRAM
+signal ddr_req_adr : std_logic_vector(23 downto 1); -- Request address
+signal ddr_req : std_logic; -- Request DDR SDRAM access
+signal ddr_req_ack : std_logic; -- Request acknowledge
+signal ddr_busy : std_logic; -- Request acknowledge
+signal ddr_rd_wr_n : std_logic; -- Access type 1=READ, 0=WRITE
+signal ddr_req_len : std_logic; -- Number of 16-bits words to transfer
+signal ddr_read_en : std_logic; -- Enable signal for read data
+signal ddr_write_en : std_logic; -- Enable (read) signal for data write
+signal refresh_en : std_logic;
+
+signal sdr_clk_p : std_logic; -- ddr_sdram_clock
+signal sdr_clk_n_p : std_logic; -- /ddr_sdram_clock
+signal cke_q_p : std_logic; -- clock enable
+signal cs_qn_p : std_logic; -- /chip select
+signal ras_qn_p : std_logic; -- /ras
+signal cas_qn_p : std_logic; -- /cas
+signal we_qn_p : std_logic; -- /write enable
+signal dm_q_p : std_logic_vector(1 downto 0); -- data mask bits, set to "00"
+signal dqs_q_p : std_logic_vector(1 downto 0); -- data strobe, only for write
+signal ba_q_p : std_logic_vector(1 downto 0); -- bank select
+signal sdr_a_p : std_logic_vector(12 downto 0); -- address bus
+signal sdr_d_p : std_logic_vector(15 downto 0); -- bidir data bus
+
+constant min_time : time := 1.875 ns;
+
+begin
+
+ clock1:
+ process
+ begin
+ loop
+ cpu_clk_4x <= '1';
+ wait for min_time;
+ cpu_clk_4x <= '0';
+ wait for min_time;
+ end loop;
+ end process;
+
+ clock2:
+ process
+ begin
+ loop
+ cpu_clk_2x <= '1' after 100 ps;
+ wait until rising_edge(cpu_clk_4x);
+ cpu_clk_2x <= '0' after 100 ps;
+ wait until rising_edge(cpu_clk_4x);
+ end loop;
+ end process;
+
+ clock3:
+ process
+ begin
+ loop
+ cpu_clk <= '1' after 100 ps;
+ wait until rising_edge(cpu_clk_2x);
+ cpu_clk <= '0' after 100 ps;
+ wait until rising_edge(cpu_clk_2x);
+ end loop;
+ end process;
+
+ ddr_in_clk_2x <= cpu_clk_4x after 1 ns;
+
+ clock4:
+ process
+ begin
+ loop
+ ddr_in_clk <= '0' after 100 ps;
+ wait until rising_edge(ddr_in_clk_2x);
+ ddr_in_clk <= '1' after 100 ps;
+ wait until rising_edge(ddr_in_clk_2x);
+ end loop;
+ end process;
+
+ inputdata:
+ process
+ begin
+ -- Wait until global reset released
+ loop
+ ddr_command <= x"0000";
+ ddr_command_we <= '0';
+ ddr_data_write <= x"000000000";
+ ddr_req <= '0';
+ ddr_req_adr <= "00000000000000000000000";
+ ddr_rd_wr_n <= '0';
+ ddr_req_len <= '0';
+ break_out <= '0';
+ refresh_en <= '0';
+
+ wait until falling_edge(areset);
+
+ -- DDR initialization sequence
+ -- Wait more than 200 us
+ wait for 201000 ns;
+
+ -- Send precharge command
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"8000";
+ ddr_command_we <= '1';
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0000";
+ ddr_command_we <= '0';
+
+ -- Wait for 1 us
+ wait for 1000 ns;
+
+ -- Load extended mode register
+ -- Enable DLL
+ -- Normal drive strength
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"2000";
+ ddr_command_we <= '1';
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0000";
+ ddr_command_we <= '0';
+
+ -- Wait for 1 us
+ wait for 1000 ns;
+
+ -- Load mode register
+ -- Burst length: 2
+ -- Burst type: Sequential
+ -- Cas latency: 2
+ -- Reset DLL
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0121";
+ ddr_command_we <= '1';
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0000";
+ ddr_command_we <= '0';
+
+ -- Wait for 1 us
+ wait for 1000 ns;
+
+ -- Send precharge command
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"8000";
+ ddr_command_we <= '1';
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0000";
+ ddr_command_we <= '0';
+
+ -- Enable refresh
+ refresh_en <= '1';
+
+ -- Wait 30 us (minimum 2 autorefresh cycles)
+ wait for 30000 ns;
+
+ -- Load mode register
+ -- Burst length: 2
+ -- Burst type: Sequential
+ -- Cas latency: 2
+ -- Deactivate Reset DLL
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0021";
+ ddr_command_we <= '1';
+ wait until rising_edge(cpu_clk);
+ ddr_command <= x"0000";
+ ddr_command_we <= '0';
+
+ -- Wait for 2 us (DLL stable)
+ wait for 2000 ns;
+
+ -- Write data to DDR
+ wait until rising_edge(cpu_clk_2x);
+ ddr_data_write <= x"312345678";
+ ddr_req <= '1';
+ ddr_req_adr <= "00000000000000000000000";
+ ddr_rd_wr_n <= '0';
+ ddr_req_len <= '0';
+ wait until rising_edge(ddr_write_en);
+ wait until rising_edge(cpu_clk_2x);
+ ddr_req <= '0';
+ ddr_req_adr <= "00000000000000000000000";
+ ddr_rd_wr_n <= '0';
+ ddr_req_len <= '0';
+ ddr_data_write <= x"000000000";
+ wait for 100 ns;
+
+ -- Read data from DDR
+ wait until rising_edge(cpu_clk_2x);
+ ddr_req <= '1';
+ ddr_req_adr <= "00000000000000000000000";
+ ddr_rd_wr_n <= '1';
+ ddr_req_len <= '0';
+ wait until rising_edge(ddr_req_ack);
+ wait until rising_edge(cpu_clk_2x);
+ ddr_req <= '0';
+ ddr_req_adr <= "00000000000000000000000";
+ ddr_rd_wr_n <= '0';
+ ddr_req_len <= '0';
+ ddr_data_write <= x"000000000";
+
+
+
+ wait for 100 ns;
+ break_out <= '1';
+ wait for 100 ns;
+
+ end loop;
+
+ end process;
+
+ ddr_ctrl:
+ ddr_top port map(
+ areset => areset,
+ cpu_clk => cpu_clk,
+ cpu_clk_2x => cpu_clk_2x,
+ cpu_clk_4x => cpu_clk_4x,
+ ddr_in_clk => ddr_in_clk,
+ ddr_in_clk_2x => ddr_in_clk_2x,
+
+ -- Command interface
+ ddr_command => ddr_command,
+ ddr_command_we => ddr_command_we,
+ refresh_en => refresh_en,
+
+ -- Data interface signals
+ ddr_data_read => ddr_data_read,
+ ddr_data_write => ddr_data_write,
+ ddr_req_adr => ddr_req_adr,
+ ddr_req => ddr_req,
+ ddr_req_ack => ddr_req_ack,
+ ddr_busy => ddr_busy,
+ ddr_rd_wr_n => ddr_rd_wr_n,
+ ddr_req_len => ddr_req_len,
+ ddr_read_en => ddr_read_en,
+ ddr_write_en => ddr_write_en,
+ -- DDR SDRAM Signals
+ sdr_clk_p => sdr_clk_p,
+ sdr_clk_n_p => sdr_clk_n_p,
+ cke_q_p => cke_q_p,
+ cs_qn_p => cs_qn_p,
+ ras_qn_p => ras_qn_p,
+ cas_qn_p => cas_qn_p,
+ we_qn_p => we_qn_p,
+ dm_q_p => dm_q_p,
+ dqs_q_p => dqs_q_p,
+ ba_q_p => ba_q_p,
+ sdr_a_p => sdr_a_p,
+ sdr_d_p => sdr_d_p);
+
+ myram:
+ MT46V16M16 generic map(
+ tCK => 7.500 ns,
+ tCH => 3.375 ns, -- 0.45*tCK
+ tCL => 3.375 ns, -- 0.45*tCK
+ tDH => 0.500 ns,
+ tDS => 0.500 ns,
+ tIH => 0.900 ns,
+ tIS => 0.900 ns,
+ tMRD => 15.000 ns,
+ tRAS => 40.000 ns,
+ tRAP => 20.000 ns,
+ tRC => 65.000 ns,
+ tRFC => 75.000 ns,
+ tRCD => 20.000 ns,
+ tRP => 20.000 ns,
+ tRRD => 15.000 ns,
+ tWR => 15.000 ns,
+ addr_bits => 13,
+ data_bits => 16,
+ cols_bits => 9)
+ port map(
+ Dq => sdr_d_p,
+ Dqs => dqs_q_p,
+ Addr => sdr_a_p,
+ Ba => ba_q_p,
+ Clk => sdr_clk_p,
+ Clk_n => sdr_clk_n_p,
+ Cke => cke_q_p,
+ Cs_n => cs_qn_p,
+ Ras_n => ras_qn_p,
+ Cas_n => cas_qn_p,
+ We_n => we_qn_p,
+ Dm => dm_q_p);
+
+end behave;
diff --git a/misc/ddrsdram/src/ddr_pkg.vhd b/misc/ddrsdram/src/ddr_pkg.vhd
new file mode 100644
index 0000000..af4a705
--- /dev/null
+++ b/misc/ddrsdram/src/ddr_pkg.vhd
@@ -0,0 +1,107 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+package ddr is
+
+ function mirror_bus32 ( org_sig : std_logic_vector) return std_logic_vector;
+ function mirror_bus4 ( org_sig : std_logic_vector) return std_logic_vector;
+
+ component ddr_top
+ generic(
+ simulate_io_time : boolean := false);
+ port ( -- Asyncronous reset and clocks
+ areset : in std_logic;
+ cpu_clk : in std_logic;
+ cpu_clk_2x : in std_logic;
+ cpu_clk_4x : in std_logic;
+ ddr_in_clk : in std_logic;
+ ddr_in_clk_2x : in std_logic;
+
+ -- Command interface
+ ddr_command : in std_logic_vector(15 downto 0);
+ ddr_command_we : in std_logic;
+ refresh_en : in std_logic;
+
+
+ -- Data interface signals
+ ddr_data_read : out std_logic_vector(31 downto 0); -- Data read from DDR SDRAM
+ ddr_data_write : in std_logic_vector(35 downto 0); -- Data to be written to DDR SDRAM
+ ddr_req_adr : in std_logic_vector(25 downto 1); -- Request address
+ ddr_req : in std_logic; -- Request DDR SDRAM access
+ ddr_busy : out std_logic; -- Request acknowledge
+ ddr_rd_wr_n : in std_logic; -- Access type 1=READ, 0=WRITE
+ ddr_req_len : in std_logic; -- Number of 16-bits words to transfer (0=2, 1=8)
+ ddr_read_en : out std_logic; -- Enable signal for read data
+ ddr_write_en : out std_logic; -- Enable (read) signal for data write
+
+ -- DDR SDRAM Signals
+ sdr_clk_p : out std_logic; -- ddr_sdram_clock
+ sdr_clk_n_p : out std_logic; -- /ddr_sdram_clock
+ cke_q_p : out std_logic; -- clock enable
+ cs_qn_p : out std_logic; -- /chip select
+ ras_qn_p : inout std_logic; -- /ras
+ cas_qn_p : inout std_logic; -- /cas
+ we_qn_p : inout std_logic; -- /write enable
+ dm_q_p : out std_logic_vector(1 downto 0); -- data mask bits, set to "00"
+ dqs_q_p : out std_logic_vector(1 downto 0); -- data strobe, only for write
+ ba_q_p : out std_logic_vector(1 downto 0); -- bank select
+ sdr_a_p : out std_logic_vector(12 downto 0); -- address bus
+ sdr_d_p : inout std_logic_vector(15 downto 0)); -- bidir data bus
+ end component;
+
+ component MT46V16M16
+ GENERIC ( -- Timing for -75Z CL2
+ tCK : TIME := 7.500 ns;
+ tCH : TIME := 3.375 ns; -- 0.45*tCK
+ tCL : TIME := 3.375 ns; -- 0.45*tCK
+ tDH : TIME := 0.500 ns;
+ tDS : TIME := 0.500 ns;
+ tIH : TIME := 0.900 ns;
+ tIS : TIME := 0.900 ns;
+ tMRD : TIME := 15.000 ns;
+ tRAS : TIME := 40.000 ns;
+ tRAP : TIME := 20.000 ns;
+ tRC : TIME := 65.000 ns;
+ tRFC : TIME := 75.000 ns;
+ tRCD : TIME := 20.000 ns;
+ tRP : TIME := 20.000 ns;
+ tRRD : TIME := 15.000 ns;
+ tWR : TIME := 15.000 ns;
+ addr_bits : INTEGER := 13;
+ data_bits : INTEGER := 16;
+ cols_bits : INTEGER := 9
+ );
+ PORT (
+ Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
+ Dqs : INOUT STD_LOGIC_VECTOR (1 DOWNTO 0) := "ZZ";
+ Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
+ Clk : IN STD_LOGIC;
+ Clk_n : IN STD_LOGIC;
+ Cke : IN STD_LOGIC;
+ Cs_n : IN STD_LOGIC;
+ Ras_n : IN STD_LOGIC;
+ Cas_n : IN STD_LOGIC;
+ We_n : IN STD_LOGIC;
+ Dm : IN STD_LOGIC_VECTOR (1 DOWNTO 0)
+ );
+ end component;
+
+end;
+
+package body ddr is
+
+ function mirror_bus32 ( org_sig : std_logic_vector) return std_logic_vector is
+ begin
+ return (org_sig(7 downto 0) & org_sig(15 downto 8) & org_sig(23 downto 16) & org_sig(31 downto 24));
+ end function mirror_bus32;
+
+ function mirror_bus4 ( org_sig : std_logic_vector) return std_logic_vector is
+ begin
+ return (org_sig(0) & org_sig(1) & org_sig(2) & org_sig(3));
+ end function mirror_bus4;
+
+end package body;
+
+ \ No newline at end of file
diff --git a/misc/ddrsdram/src/ddr_top.vhd b/misc/ddrsdram/src/ddr_top.vhd
new file mode 100644
index 0000000..2aceae9
--- /dev/null
+++ b/misc/ddrsdram/src/ddr_top.vhd
@@ -0,0 +1,743 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+library UNISIM;
+use UNISIM.vcomponents.all;
+
+entity ddr_top is
+ generic(
+ simulate_io_time : boolean := false);
+ port ( -- Asyncronous reset and clocks
+ areset : in std_logic;
+ cpu_clk : in std_logic;
+ cpu_clk_2x : in std_logic;
+ cpu_clk_4x : in std_logic;
+ ddr_in_clk : in std_logic;
+ ddr_in_clk_2x : in std_logic;
+
+ -- Command interface
+ ddr_command : in std_logic_vector(15 downto 0);
+ ddr_command_we : in std_logic;
+ refresh_en : in std_logic;
+
+ -- Data interface signals
+ ddr_data_read : out std_logic_vector(31 downto 0); -- Data read from DDR SDRAM
+ ddr_data_write : in std_logic_vector(35 downto 0); -- Data to be written to DDR SDRAM
+ ddr_req_adr : in std_logic_vector(25 downto 1); -- Request address
+ ddr_req : in std_logic; -- Request DDR SDRAM access
+ ddr_busy : out std_logic; -- Request acknowledge
+ ddr_rd_wr_n : in std_logic; -- Access type 1=READ, 0=WRITE
+ ddr_req_len : in std_logic; -- Number of 16-bits words to transfer (0=2, 1=8)
+ ddr_read_en : out std_logic; -- Enable signal for read data
+ ddr_write_en : out std_logic; -- Enable (read) signal for data write
+
+ -- DDR SDRAM Signals
+ sdr_clk_p : out std_logic; -- ddr_sdram_clock
+ sdr_clk_n_p : out std_logic; -- /ddr_sdram_clock
+ cke_q_p : out std_logic; -- clock enable
+ cs_qn_p : out std_logic; -- /chip select
+ ras_qn_p : inout std_logic; -- /ras
+ cas_qn_p : inout std_logic; -- /cas
+ we_qn_p : inout std_logic; -- /write enable
+ dm_q_p : out std_logic_vector(1 downto 0); -- data mask bits, set to "00"
+ dqs_q_p : out std_logic_vector(1 downto 0); -- data strobe, only for write
+ ba_q_p : out std_logic_vector(1 downto 0); -- bank select
+ sdr_a_p : out std_logic_vector(12 downto 0); -- address bus
+ sdr_d_p : inout std_logic_vector(15 downto 0)); -- bidir data bus
+end ddr_top;
+
+architecture behave of ddr_top is
+
+attribute keep : string;
+
+type clk4_type is array(0 to 15) of std_logic_vector(1 downto 0);
+
+signal cpu_clk_tog : std_logic;
+signal ddr_cmd : std_logic_vector(15 downto 0);
+signal ddr_cmd_we_smp : std_logic;
+signal new_command : std_logic;
+
+signal cpu_clk_2x_smp1 : std_logic;
+signal cpu_clk_2x_smp2 : std_logic;
+signal cpu_clk_4x_smp1 : std_logic;
+signal cpu_clk_4x_smp2 : std_logic;
+
+signal clk2_phase : std_logic;
+signal clk4_phase : std_logic_vector(3 downto 0);
+signal clk4_phase_short : clk4_type;
+attribute keep of clk4_phase_short:signal is "true";
+
+signal ddr_clk_tog : std_logic;
+signal ddr_clk_smp1 : std_logic;
+signal ddr_clk_smp2 : std_logic;
+signal ddr_clk_phase : std_logic;
+
+signal smp_req_adr : std_logic_vector(25 downto 1);
+signal smp_req_type : std_logic;
+signal smp_req_len : std_logic;
+signal ddr_write_en_int : std_logic;
+signal ddr_read_en_int : std_logic;
+
+signal dqs_q : std_logic_vector(1 downto 0);
+signal dqs_oe_n : std_logic_vector(1 downto 0);
+attribute keep of dqs_oe_n:signal is "true";
+signal cas_qn : std_logic;
+signal ras_qn : std_logic;
+signal we_qn : std_logic;
+signal ba_q : std_logic_vector(1 downto 0);
+signal sdr_clk : std_logic;
+signal sdr_clk_n : std_logic;
+signal sdr_a : std_logic_vector(12 downto 0);
+signal sdr_d : std_logic_vector(15 downto 0);
+signal sdr_smp : std_logic_vector(35 downto 0);
+signal sdr_oe_n : std_logic_vector(15 downto 0);
+attribute keep of sdr_oe_n:signal is "true";
+signal sdr_oe_ctrl : std_logic_vector(15 downto 0);
+attribute keep of sdr_oe_ctrl:signal is "true";
+signal sdr_wr_msw : std_logic_vector(17 downto 0);
+attribute keep of sdr_wr_msw:signal is "true";
+signal dm_q : std_logic_vector(1 downto 0);
+
+signal nowin_idle_dqs : std_logic_vector(1 downto 0);
+signal nowin_wr_nop1_d : std_logic_vector(15 downto 0);
+signal nowin_wr_nop1_dqs : std_logic_vector(1 downto 0);
+signal nowin_wr_nop1_dm : std_logic_vector(1 downto 0);
+signal nowin_wr_nop2_dqs : std_logic_vector(1 downto 0);
+signal nowin_wr_nop3_d : std_logic_vector(15 downto 0);
+signal nowin_wr_nop3_dqs : std_logic_vector(1 downto 0);
+attribute keep of nowin_idle_dqs:signal is "true";
+attribute keep of nowin_wr_nop1_d:signal is "true";
+attribute keep of nowin_wr_nop1_dqs:signal is "true";
+attribute keep of nowin_wr_nop1_dm:signal is "true";
+attribute keep of nowin_wr_nop2_dqs:signal is "true";
+attribute keep of nowin_wr_nop3_d:signal is "true";
+attribute keep of nowin_wr_nop3_dqs:signal is "true";
+
+signal cas_n_smp : std_logic;
+signal ras_n_smp : std_logic;
+signal we_n_smp : std_logic;
+signal read_start_sig : std_logic;
+signal sdr_d_in : std_logic_vector(15 downto 0);
+signal read_time_cnt : std_logic_vector(1 downto 0);
+signal read_input_en : std_logic;
+signal read_input_en_del : std_logic;
+signal ddr_data_read_int : std_logic_vector(31 downto 0);
+
+signal refresh_pend : std_logic;
+signal refresh_end : std_logic;
+signal refresh_cnt : std_logic_vector(9 downto 0);
+signal refresh_wait_cnt : std_logic_vector(3 downto 0);
+signal refresh_wait_end : std_logic;
+
+signal cas_qn_p_del : std_logic;
+signal ras_qn_p_del : std_logic;
+signal we_qn_p_del : std_logic;
+signal sdr_d_p_del : std_logic_vector(15 downto 0);
+
+signal saved_row : std_logic_vector(26 downto 11);
+signal operation : std_logic_vector(1 downto 0);
+
+signal ddr_req_adr_int : std_logic_vector(25 downto 1);
+
+type state_type is (idle, act, act_nop1, act_nop2, rd_wr, rd_nop1,
+ rd_nop2,rd_nop3,rd_nop4, rd_nop5,pre, pre_nop1, pre_nop2, wr_nop1, wr_nop2,
+ wr_nop3, cmd, cpu_pre, refresh, refresh_wait);
+signal ddr_state : state_type;
+
+constant Clk_to_Output : time := 2.2 ns;
+constant Input_Setup : time := 2.5 ns;
+
+constant Refresh_Interval : std_logic_vector(9 downto 0) := "1111100110";
+
+begin
+
+ iotimingon:
+ if simulate_io_time generate
+ begin
+ cas_qn_p_del <= 'X' after 0 ns, cas_qn_p after Input_Setup;
+ ras_qn_p_del <= 'X' after 0 ns, ras_qn_p after Input_Setup;
+ we_qn_p_del <= 'X' after 0 ns, we_qn_p after Input_Setup;
+ sdr_d_p_del <= "XXXXXXXXXXXXXXXX" after 0 ns, sdr_d_p after Input_Setup;
+ end generate;
+
+ iotimingoff:
+ if not simulate_io_time generate
+ begin
+ cas_qn_p_del <= cas_qn_p;
+ ras_qn_p_del <= ras_qn_p;
+ we_qn_p_del <= we_qn_p;
+ sdr_d_p_del <= sdr_d_p;
+ end generate;
+
+ ddr_write_en <= ddr_write_en_int;
+ ddr_read_en <= ddr_read_en_int;
+ ddr_data_read <= ddr_data_read_int;
+
+ ddr_req_adr_int <= (ddr_req_adr(24 downto 10) & '0' & ddr_req_adr(9 downto 1)) when (simulate_io_time) else ddr_req_adr;
+
+ process(cpu_clk, areset) -- Toggle a flip-flop with cpu_clk, in order
+ begin -- to find phase relation with 2x and 4x clocks
+ if areset = '1' then
+ cpu_clk_tog <= '0';
+ elsif (cpu_clk'event and cpu_clk = '1') then
+ cpu_clk_tog <= not(cpu_clk_tog);
+ end if;
+ end process;
+
+ process(cpu_clk_2x, areset) -- Find phase relation between cpu_clk and cpu_clk_2x
+ begin
+ if areset = '1' then
+ cpu_clk_2x_smp1 <= '0';
+ cpu_clk_2x_smp2 <= '0';
+ clk2_phase <= '0';
+ elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then
+ cpu_clk_2x_smp1 <= cpu_clk_tog;
+ cpu_clk_2x_smp2 <= cpu_clk_2x_smp1;
+ if (cpu_clk_2x_smp1 = '1' and cpu_clk_2x_smp2 = '0') then
+ clk2_phase <= '0';
+ else
+ clk2_phase <= not(clk2_phase);
+ end if;
+ end if;
+ end process;
+
+ process(cpu_clk_4x, areset) -- Find phase relation between cpu_clk and cpu_clk_4x
+ begin
+ if areset = '1' then
+ cpu_clk_4x_smp1 <= '0';
+ cpu_clk_4x_smp2 <= '0';
+ clk4_phase <= "0000";
+ clk4_phase_short(0) <= "00";
+ clk4_phase_short(1) <= "00";
+ clk4_phase_short(2) <= "00";
+ clk4_phase_short(3) <= "00";
+ clk4_phase_short(4) <= "00";
+ clk4_phase_short(5) <= "00";
+ clk4_phase_short(6) <= "00";
+ clk4_phase_short(7) <= "00";
+ clk4_phase_short(8) <= "00";
+ clk4_phase_short(9) <= "00";
+ clk4_phase_short(10) <= "00";
+ clk4_phase_short(11) <= "00";
+ clk4_phase_short(12) <= "00";
+ clk4_phase_short(13) <= "00";
+ clk4_phase_short(14) <= "00";
+ clk4_phase_short(15) <= "00";
+ elsif (cpu_clk_4x'event and cpu_clk_4x = '1') then
+ cpu_clk_4x_smp1 <= cpu_clk_tog;
+ cpu_clk_4x_smp2 <= cpu_clk_4x_smp1;
+ for i in 0 to 15 loop
+ if (cpu_clk_4x_smp1 = '1' and cpu_clk_4x_smp2 = '0') then
+ clk4_phase <= "0100";
+ clk4_phase_short(i) <= "01";
+ else
+ clk4_phase <= (clk4_phase(2 downto 0) & clk4_phase(3));
+ clk4_phase_short(i) <= clk4_phase_short(i)(0) & clk4_phase_short(i)(1);
+ end if;
+ end loop;
+ end if;
+ end process;
+
+ process(cpu_clk_4x, areset) --
+ begin
+ if areset = '1' then
+ sdr_clk <= '0';
+ sdr_clk_n <= '0';
+ elsif (cpu_clk_4x'event and cpu_clk_4x = '1') then
+ if clk4_phase_short(0)(0) = '1' then
+ sdr_clk <= '1';
+ else
+ sdr_clk <= '0';
+ end if;
+ if clk4_phase_short(0)(1) = '1' then
+ sdr_clk_n <= '1';
+ else
+ sdr_clk_n <= '0';
+ end if;
+ end if;
+ end process;
+
+ cke_q_p <= '1' after Clk_to_Output;
+ cs_qn_p <= '0' after Clk_to_Output;
+
+ process(cpu_clk_4x, areset) --
+ begin
+ if areset = '1' then
+ ras_qn_p <= '1';
+ cas_qn_p <= '1';
+ we_qn_p <= '1';
+ dqs_q_p <= "ZZ";
+ sdr_a_p <= "0000000000000";
+ ba_q_p <= "00";
+ sdr_clk_p <= '0';
+ sdr_clk_n_p <= '1';
+ elsif (cpu_clk_4x'event and cpu_clk_4x = '1') then
+ ras_qn_p <= transport ras_qn after Clk_to_Output;
+ cas_qn_p <= transport cas_qn after Clk_to_Output;
+ we_qn_p <= transport we_qn after Clk_to_Output;
+ if dqs_oe_n(0) = '0' then
+ dqs_q_p(0) <= transport dqs_q(0) after Clk_to_Output;
+ else
+ dqs_q_p(0) <= transport 'Z' after Clk_to_Output;
+ end if;
+ if dqs_oe_n(1) = '0' then
+ dqs_q_p(1) <= transport dqs_q(1) after Clk_to_Output;
+ else
+ dqs_q_p(1) <= transport 'Z' after Clk_to_Output;
+ end if;
+ sdr_a_p <= transport sdr_a after Clk_to_Output;
+ ba_q_p <= transport ba_q after Clk_to_Output;
+ sdr_clk_p <= transport sdr_clk after Clk_to_Output;
+ sdr_clk_n_p <= transport sdr_clk_n after Clk_to_Output;
+ end if;
+ end process;
+
+ process(cpu_clk_2x, areset) --
+ begin
+ if areset = '1' then
+ ddr_state <= idle;
+ ras_qn <= '1';
+ cas_qn <= '1';
+ we_qn <= '1';
+ smp_req_adr <= (others => '0');
+ smp_req_type <= '0';
+ smp_req_len <= '0';
+ sdr_a <= "XXXXXXXXXXXXX";
+ ba_q <= "00";
+ ddr_busy <= '1';
+ saved_row <= "1000000000000000";
+ ddr_write_en_int <= '0';
+ ddr_read_en_int <= '0';
+ nowin_idle_dqs <= "11";
+ nowin_wr_nop1_d <= "0000000000000000";
+ nowin_wr_nop1_dqs <= "00";
+ nowin_wr_nop1_dm <= "00";
+ nowin_wr_nop2_dqs <= "00";
+ nowin_wr_nop3_d <= "0000000000000000";
+ nowin_wr_nop3_dqs <= "00";
+ elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then
+
+ -- Default values
+ ras_qn <= '1';
+ cas_qn <= '1';
+ we_qn <= '1';
+ sdr_a <= "XXXXXXXXXXXXX";
+ ddr_busy <= '1';
+ ddr_write_en_int <= '0';
+ ddr_read_en_int <= '0';
+
+ nowin_idle_dqs <= "00";
+ nowin_wr_nop1_d <= "0000000000000000";
+ nowin_wr_nop1_dqs <= "00";
+ nowin_wr_nop1_dm <= "00";
+ nowin_wr_nop2_dqs <= "00";
+ nowin_wr_nop3_d <= "0000000000000000";
+ nowin_wr_nop3_dqs <= "00";
+
+ case ddr_state is
+ when idle =>
+ smp_req_adr <= ddr_req_adr_int;
+ smp_req_type <= ddr_rd_wr_n;
+ smp_req_len <= ddr_req_len;
+ ddr_busy <= '0';
+ operation <= "00";
+ if refresh_pend = '1' then
+ operation <= "01";
+ ddr_state <= pre;
+ elsif new_command = '1' then
+ if ddr_cmd(15) = '1' then
+ operation <= "10";
+ ddr_state <= cpu_pre;
+ else
+ ddr_state <= cmd;
+ end if;
+ elsif (ddr_req = '1' and ddr_req_adr_int(25 downto 11) = saved_row(25 downto 11) and saved_row(26) = '0') then
+ operation <= "11";
+ ddr_write_en_int <= not(ddr_rd_wr_n);
+ ddr_state <= rd_wr;
+ elsif ddr_req = '1' then
+ operation <= "11";
+ ddr_state <= pre;
+ else
+ ddr_state <= idle;
+ nowin_idle_dqs <= "11";
+ end if;
+ when act =>
+ sdr_a <= smp_req_adr(23 downto 11);
+ ba_q <= smp_req_adr(25 downto 24);
+ ras_qn <= '0';
+ ddr_write_en_int <= not(smp_req_type);
+ ddr_state <= act_nop1;
+ when act_nop1 =>
+ ddr_state <= act_nop2;
+ when act_nop2 =>
+ ddr_state <= rd_wr;
+ when rd_wr =>
+ sdr_a(10) <= '0'; -- Disable auto precharge
+ sdr_a(9 downto 0) <= smp_req_adr(10 downto 1);
+ ba_q <= smp_req_adr(25 downto 24);
+ saved_row <= '0' & smp_req_adr(25 downto 11);
+ cas_qn <= '0';
+ we_qn <= smp_req_type;
+ if smp_req_type = '1' then
+ ddr_state <= rd_nop1;
+ else
+ ddr_state <= wr_nop1;
+ nowin_wr_nop1_d <= "1111111111111111";
+ nowin_wr_nop1_dqs <= "11";
+ nowin_wr_nop1_dm <= "11";
+ end if;
+ when wr_nop1 =>
+ ddr_state <= wr_nop2;
+ nowin_wr_nop2_dqs <= "11";
+ when wr_nop2 =>
+ ddr_state <= wr_nop3;
+ nowin_wr_nop3_d <= "1111111111111111";
+ nowin_wr_nop3_dqs <= "11";
+ when wr_nop3 =>
+ nowin_idle_dqs <= "11";
+ ddr_state <= idle;
+ when rd_nop1 =>
+ ddr_state <= rd_nop2;
+ when rd_nop2 =>
+ if operation /= "11" then
+ nowin_idle_dqs <= "11";
+ ddr_state <= idle;
+ else
+ ddr_state <= rd_nop3;
+ end if;
+ when rd_nop3 =>
+ ddr_state <= rd_nop4;
+ when rd_nop4 =>
+ ddr_read_en_int <= '1';
+ ddr_state <= rd_nop5;
+ when rd_nop5 =>
+ nowin_idle_dqs <= "11";
+ ddr_state <= idle;
+ when pre =>
+ ras_qn <= '0';
+ we_qn <= '0';
+ sdr_a(10) <= '1'; -- Precharge all banks
+ ba_q <= smp_req_adr(25 downto 24);
+ ddr_state <= pre_nop1;
+ when pre_nop1 =>
+ ddr_state <= pre_nop2;
+ when cmd =>
+ cas_qn <= '0';
+ ras_qn <= '0';
+ we_qn <= '0';
+ ba_q <= ddr_cmd(14 downto 13);
+ sdr_a <= ddr_cmd(12 downto 0);
+ nowin_idle_dqs <= "11";
+ ddr_state <= idle;
+ when cpu_pre =>
+ ddr_state <= pre;
+ when refresh =>
+ cas_qn <= '0';
+ ras_qn <= '0';
+ saved_row(26) <= '1';
+ ddr_state <= refresh_wait;
+ when refresh_wait =>
+ if refresh_wait_end = '1' then
+ ddr_state <= pre_nop2;
+ end if;
+ when pre_nop2 =>
+ if operation = "01" then
+ operation <= "10";
+ ddr_state <= refresh;
+ elsif operation = "10" then
+ nowin_idle_dqs <= "11";
+ ddr_state <= idle;
+ else
+ ddr_state <= act;
+ end if;
+ when others =>
+ ddr_state <= idle;
+ nowin_idle_dqs <= "11";
+ end case;
+ end if;
+ end process;
+
+ process(cpu_clk, areset) --
+ begin
+ if areset = '1' then
+ ddr_cmd <= "0000000000000000";
+ elsif (cpu_clk'event and cpu_clk = '1') then
+ if ddr_command_we = '1' then
+ ddr_cmd <= ddr_command;
+ else
+ ddr_cmd <= ddr_cmd;
+ end if;
+ end if;
+ end process;
+
+ process(cpu_clk_2x, areset) --
+ begin
+ if areset = '1' then
+ ddr_cmd_we_smp <= '0';
+ new_command <= '0';
+ sdr_smp <= "000000000000000000000000000000000000";
+ elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then
+ ddr_cmd_we_smp <= ddr_command_we;
+ if ddr_command_we = '0' and ddr_cmd_we_smp = '1' then
+ new_command <= '1';
+ elsif ddr_state = cmd or ddr_state = cpu_pre then
+ new_command <= '0';
+ else
+ new_command <= new_command;
+ end if;
+
+ if ddr_write_en_int = '1' then
+ sdr_smp <= ddr_data_write;
+ else
+ sdr_smp <= sdr_smp;
+ end if;
+
+ end if;
+ end process;
+
+ process(cpu_clk_4x, areset) --
+ begin
+ if areset = '1' then
+ dqs_q <= "00";
+ dqs_oe_n <= "11";
+ sdr_oe_ctrl <= "1111111111111111";
+ sdr_wr_msw <= "000000000000000000";
+ elsif (cpu_clk_4x'event and cpu_clk_4x = '1') then
+
+ for i in 0 to 15 loop
+ if nowin_wr_nop1_d(i) = '1' and clk4_phase_short(i)(0) = '1' then
+ sdr_oe_ctrl(i) <= '0';
+ elsif nowin_wr_nop3_d(i) = '1' and clk4_phase_short(i)(0) = '1' then
+ sdr_oe_ctrl(i) <= '1';
+ end if;
+ end loop;
+
+ for i in 0 to 1 loop
+ if nowin_idle_dqs(i) = '1' or nowin_wr_nop3_dqs(i) = '1' then
+ dqs_oe_n(i) <= '1';
+ elsif nowin_wr_nop1_dqs(i) = '1' then
+ dqs_oe_n(i) <= '0';
+ end if;
+ end loop;
+
+ for i in 0 to 1 loop
+ if (nowin_wr_nop2_dqs(i) = '1' and clk4_phase_short(i)(0) = '1') then
+ dqs_q(i) <= '1';
+ else
+ dqs_q(i) <= '0';
+ end if;
+ end loop;
+
+ for i in 0 to 15 loop
+ if nowin_wr_nop1_d(i) = '1' and clk4_phase_short(i)(1) = '1' then
+ sdr_wr_msw(i) <= '1';
+ else
+ sdr_wr_msw(i) <= '0';
+ end if;
+ end loop;
+
+ for i in 0 to 1 loop
+ if nowin_wr_nop1_dm(i) = '1' and clk4_phase_short(i)(1) = '1' then
+ sdr_wr_msw(i+16) <= '1';
+ else
+ sdr_wr_msw(i+16) <= '0';
+ end if;
+ end loop;
+
+ end if;
+ end process;
+
+ -- NOTE! DATA OUTPUT PATH. CLOCKED ON FALLING 4X CLOCK
+ process(cpu_clk_4x, areset) --
+ begin
+ if areset = '1' then
+ sdr_d_p <= "ZZZZZZZZZZZZZZZZ";
+ dm_q_p <= "11";
+ sdr_oe_n <= "1111111111111111";
+ sdr_d <= "0000000000000000";
+ dm_q <= "11";
+ elsif (cpu_clk_4x'event and cpu_clk_4x = '0') then
+
+ for i in 0 to 15 loop
+ if sdr_oe_n(i) = '0' then
+ sdr_d_p(i) <= transport sdr_d(i) after Clk_to_Output;
+ else
+ sdr_d_p(i) <= transport 'Z' after Clk_to_Output;
+ end if;
+ end loop;
+
+ dm_q_p <= transport dm_q after Clk_to_Output;
+
+ for i in 0 to 15 loop
+ if sdr_oe_ctrl(i) = '0' then
+ sdr_oe_n(i) <= '0';
+ else
+ sdr_oe_n(i) <= '1';
+ end if;
+ end loop;
+
+ for i in 0 to 15 loop
+ if sdr_wr_msw(i) = '1' then
+ sdr_d(i) <= sdr_smp(i);
+ else
+ sdr_d(i) <= sdr_smp(i+16);
+ end if;
+ end loop;
+
+ for i in 0 to 1 loop
+ if sdr_wr_msw(i+16) = '1' then
+ dm_q(i) <= sdr_smp(i+32);
+ else
+ dm_q(i) <= sdr_smp(i+34);
+ end if;
+ end loop;
+
+ end if;
+ end process;
+
+ process(cpu_clk_2x, areset) --
+ begin
+ if areset = '1' then
+ refresh_cnt <= "0000000000";
+ refresh_pend <= '0';
+ refresh_end <= '0';
+ refresh_wait_cnt <= "0000";
+ refresh_wait_end <= '0';
+ elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then
+
+ if refresh_cnt = Refresh_Interval then
+ refresh_end <= '1';
+ else
+ refresh_end <= '0';
+ end if;
+
+ if refresh_end = '1' then
+ refresh_cnt <= "0000000000";
+ else
+ refresh_cnt <= refresh_cnt + '1';
+ end if;
+
+ if refresh_end = '1' and refresh_en = '1' then
+ refresh_pend <= '1';
+ elsif ddr_state = refresh then
+ refresh_pend <= '0';
+ else
+ refresh_pend <= refresh_pend;
+ end if;
+
+ if ddr_state = refresh_wait then
+ refresh_wait_cnt <= refresh_wait_cnt + '1';
+ else
+ refresh_wait_cnt <= "0000";
+ end if;
+
+ if refresh_wait_cnt = "1011" then
+ refresh_wait_end <= '1';
+ else
+ refresh_wait_end <= '0';
+ end if;
+
+ end if;
+ end process;
+
+ -- 911. THIS IS A DUMMY FOR FGPA IMPEMENTATION TESTING
+
+ process(ddr_in_clk, areset)
+ begin
+ if areset = '1' then
+ ddr_clk_tog <= '0';
+ elsif (ddr_in_clk'event and ddr_in_clk = '1') then
+ ddr_clk_tog <= not(ddr_clk_tog);
+ end if;
+ end process;
+
+ process(ddr_in_clk_2x, areset)
+ begin
+ if areset = '1' then
+ ddr_clk_smp1 <= '0';
+ ddr_clk_smp2 <= '0';
+ ddr_clk_phase <= '0';
+ elsif (ddr_in_clk_2x'event and ddr_in_clk_2x = '1') then
+ ddr_clk_smp1 <= ddr_clk_tog;
+ ddr_clk_smp2 <= ddr_clk_smp1;
+ if ddr_clk_smp1 = '1' and ddr_clk_smp2 = '0' then
+ ddr_clk_phase <= '0';
+ else
+ ddr_clk_phase <= not(ddr_clk_phase);
+ end if;
+ end if;
+ end process;
+
+ process(ddr_in_clk_2x, areset)
+ begin
+ if areset = '1' then
+ cas_n_smp <= '0';
+ ras_n_smp <= '0';
+ we_n_smp <= '0';
+ read_start_sig <= '0';
+ elsif (ddr_in_clk_2x'event and ddr_in_clk_2x = '1') then
+ cas_n_smp <= cas_qn_p_del;
+ ras_n_smp <= ras_qn_p_del;
+ we_n_smp <= we_qn_p_del;
+ if ras_n_smp = '1' and cas_n_smp = '0' and we_n_smp = '1' and ddr_clk_phase = '1' then
+ read_start_sig <= '1';
+ else
+ read_start_sig <= '0';
+ end if;
+ end if;
+ end process;
+
+ process(ddr_in_clk_2x, areset)
+ begin
+ if areset = '1' then
+ sdr_d_in <= "0000000000000000";
+ elsif (ddr_in_clk_2x'event and ddr_in_clk_2x = '1') then
+ sdr_d_in <= sdr_d_p_del;
+ end if;
+ end process;
+
+ process(ddr_in_clk_2x, areset)
+ begin
+ if areset = '1' then
+ read_time_cnt <= "00";
+ read_input_en <= '0';
+ elsif (ddr_in_clk_2x'event and ddr_in_clk_2x = '1') then
+
+ if read_start_sig = '1' then
+ read_time_cnt <= "01";
+ elsif read_time_cnt = "00" then
+ read_time_cnt <= read_time_cnt;
+ else
+ read_time_cnt <= read_time_cnt + '1';
+ end if;
+
+ if read_time_cnt = "11" then
+ read_input_en <= '1';
+ else
+ read_input_en <= '0';
+ end if;
+
+ read_input_en_del <= read_input_en;
+
+ end if;
+ end process;
+
+ process(ddr_in_clk_2x, areset)
+ begin
+ if areset = '1' then
+ ddr_data_read_int <= "00000000000000000000000000000000";
+ elsif (ddr_in_clk_2x'event and ddr_in_clk_2x = '1') then
+ if read_input_en = '1' then
+ ddr_data_read_int(15 downto 0) <= sdr_d_in;
+ end if;
+ if read_input_en_del = '1' then
+ ddr_data_read_int(31 downto 16) <= sdr_d_in;
+ end if;
+ end if;
+ end process;
+
+end behave;
+
+
diff --git a/misc/ddrsdram/src/mt46v16m16.vhd b/misc/ddrsdram/src/mt46v16m16.vhd
new file mode 100644
index 0000000..356bb28
--- /dev/null
+++ b/misc/ddrsdram/src/mt46v16m16.vhd
@@ -0,0 +1,1320 @@
+-----------------------------------------------------------------------------------------
+--
+-- File Name: MT46V16M16.VHD
+-- Version: 2.1
+-- Date: January 14th, 2002
+-- Model: Behavioral
+-- Simulator: NCDesktop - http://www.cadence.com
+-- ModelSim PE - http://www.model.com
+--
+-- Dependencies: None
+--
+-- Author: Son P. Huynh
+-- Email: sphuynh@micron.com
+-- Phone: (208) 368-3825
+-- Company: Micron Technology, Inc.
+-- Part Number: MT46V16M16 (4 Mb x 16 x 4 Banks)
+--
+-- Description: Micron 256 Mb SDRAM DDR (Double Data Rate)
+--
+-- Limitation: Doesn't model internal refresh counter
+--
+-- Note:
+--
+-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
+-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
+-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
+-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
+--
+-- Copyright (c) 1998 Micron Semiconductor Products, Inc.
+-- All rights researved
+--
+-- Rev Author Date Changes
+-- --- ---------------------------- ---------- -------------------------------------
+-- 2.1 Son P. Huynh 01/14/2002 - Fix Burst_counter
+-- Micron Technology, Inc.
+--
+-- 2.0 Son P. Huynh 11/08/2001 - Second release
+-- Micron Technology, Inc. - Rewrote and remove SHARED VARIABLE
+--
+-----------------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+ USE IEEE.STD_LOGIC_1164.ALL;
+ USE IEEE.STD_LOGIC_UNSIGNED.ALL;
+ USE IEEE.STD_LOGIC_ARITH.ALL;
+
+ENTITY MT46V16M16 IS
+ GENERIC ( -- Timing for -75Z CL2
+ tCK : TIME := 7.500 ns;
+ tCH : TIME := 3.375 ns; -- 0.45*tCK
+ tCL : TIME := 3.375 ns; -- 0.45*tCK
+ tDH : TIME := 0.500 ns;
+ tDS : TIME := 0.500 ns;
+ tIH : TIME := 0.900 ns;
+ tIS : TIME := 0.900 ns;
+ tMRD : TIME := 15.000 ns;
+ tRAS : TIME := 40.000 ns;
+ tRAP : TIME := 20.000 ns;
+ tRC : TIME := 65.000 ns;
+ tRFC : TIME := 75.000 ns;
+ tRCD : TIME := 20.000 ns;
+ tRP : TIME := 20.000 ns;
+ tRRD : TIME := 15.000 ns;
+ tWR : TIME := 15.000 ns;
+ addr_bits : INTEGER := 13;
+ data_bits : INTEGER := 16;
+ cols_bits : INTEGER := 9
+ );
+ PORT (
+ Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
+ Dqs : INOUT STD_LOGIC_VECTOR (1 DOWNTO 0) := "ZZ";
+ Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
+ Clk : IN STD_LOGIC;
+ Clk_n : IN STD_LOGIC;
+ Cke : IN STD_LOGIC;
+ Cs_n : IN STD_LOGIC;
+ Ras_n : IN STD_LOGIC;
+ Cas_n : IN STD_LOGIC;
+ We_n : IN STD_LOGIC;
+ Dm : IN STD_LOGIC_VECTOR (1 DOWNTO 0)
+ );
+END MT46V16M16;
+
+ARCHITECTURE behave OF MT46V16M16 IS
+ -- Array for Read pipeline
+ TYPE Array_Read_cmnd IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Read_bank IS ARRAY (8 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0);
+ TYPE Array_Read_cols IS ARRAY (8 DOWNTO 0) OF STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+
+ -- Array for Write pipeline
+ TYPE Array_Write_cmnd IS ARRAY (2 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Write_bank IS ARRAY (2 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0);
+ TYPE Array_Write_cols IS ARRAY (2 DOWNTO 0) OF STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+
+ -- Array for Auto Precharge
+ TYPE Array_Read_precharge IS ARRAY (3 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Write_precharge IS ARRAY (3 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Count_precharge IS ARRAY (3 DOWNTO 0) OF INTEGER;
+
+ -- Array for Manual Precharge
+ TYPE Array_A10_precharge IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Bank_precharge IS ARRAY (8 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0);
+ TYPE Array_Cmnd_precharge IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+
+ -- Array for Burst Terminate
+ TYPE Array_Cmnd_bst IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+
+ -- Array for Memory Access
+ TYPE Array_ram_type IS ARRAY (2**cols_bits - 1 DOWNTO 0) OF STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0);
+ TYPE Array_ram_pntr IS ACCESS Array_ram_type;
+ TYPE Array_ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF Array_ram_pntr;
+
+ -- Data pair
+ SIGNAL Dq_pair : STD_LOGIC_VECTOR (2 * data_bits - 1 DOWNTO 0);
+ SIGNAL Dm_pair : STD_LOGIC_VECTOR (3 DOWNTO 0);
+
+ -- Mode Register
+ SIGNAL Mode_reg : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
+
+ -- Command Decode Variables
+ SIGNAL Active_enable, Aref_enable, Burst_term, Ext_mode_enable : STD_LOGIC := '0';
+ SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : STD_LOGIC := '0';
+
+ -- Burst Length Decode Variables
+ SIGNAL Burst_length_2, Burst_length_4, Burst_length_8, Burst_length_f : STD_LOGIC := '0';
+
+ -- Cas Latency Decode Variables
+ SIGNAL Cas_latency_15, Cas_latency_2, Cas_latency_25, Cas_latency_3, Cas_latency_4 : STD_LOGIC := '0';
+
+ -- Internal Control Signals
+ SIGNAL Cs_in, Ras_in, Cas_in, We_in : STD_LOGIC := '0';
+
+ -- System Clock
+ SIGNAL Sys_clk : STD_LOGIC := '0';
+
+ -- Dqs buffer
+ SIGNAL Dqs_out : STD_LOGIC_VECTOR (1 DOWNTO 0) := "ZZ";
+
+BEGIN
+ -- Strip the strength
+ Cs_in <= To_X01 (Cs_n);
+ Ras_in <= To_X01 (Ras_n);
+ Cas_in <= To_X01 (Cas_n);
+ We_in <= To_X01 (We_n);
+
+ -- Commands Decode
+ Active_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND We_in;
+ Aref_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND We_in;
+ Burst_term <= NOT(Cs_in) AND Ras_in AND Cas_in AND NOT(We_in);
+ Ext_mode_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in) AND Ba(0) AND NOT(Ba(1));
+ Mode_reg_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in) AND NOT(Ba(0)) AND NOT(Ba(1));
+ Prech_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND NOT(We_in);
+ Read_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND We_in;
+ Write_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND NOT(We_in);
+
+ -- Burst Length Decode
+ Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0);
+ Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0));
+ Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
+ Burst_length_f <= (Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
+
+ -- CAS Latency Decode
+ Cas_latency_15 <= Mode_reg(6) AND NOT(Mode_reg(5)) AND (Mode_reg(4));
+ Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4));
+ Cas_latency_25 <= Mode_reg(6) AND Mode_reg(5) AND NOT(Mode_reg(4));
+ Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4);
+ Cas_latency_4 <= (Mode_reg(6)) AND NOT(Mode_reg(5)) AND NOT(Mode_reg(4));
+
+ -- Dqs buffer
+ Dqs <= Dqs_out;
+
+ --
+ -- System Clock
+ --
+ int_clk : PROCESS (Clk, Clk_n)
+ VARIABLE ClkZ, CkeZ : STD_LOGIC := '0';
+ begin
+ IF Clk = '1' AND Clk_n = '0' THEN
+ ClkZ := '1';
+ CkeZ := Cke;
+ ELSIF Clk = '0' AND Clk_n = '1' THEN
+ ClkZ := '0';
+ END IF;
+ Sys_clk <= CkeZ AND ClkZ;
+ END PROCESS;
+
+ --
+ -- Main Process
+ --
+ state_register : PROCESS
+ -- Precharge Variables
+ VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : STD_LOGIC := '0';
+
+ -- Activate Variables
+ VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : STD_LOGIC := '1';
+
+ -- Data IO variables
+ VARIABLE Data_in_enable, Data_out_enable : STD_LOGIC := '0';
+
+ -- Internal address mux variables
+ VARIABLE Cols_brst : STD_LOGIC_VECTOR (2 DOWNTO 0);
+ VARIABLE Prev_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00";
+ VARIABLE Bank_addr : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00";
+ VARIABLE Cols_addr : STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+ VARIABLE Rows_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B0_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B1_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B2_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B3_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+
+ -- DLL Reset variables
+ VARIABLE DLL_enable : STD_LOGIC := '0';
+ VARIABLE DLL_reset : STD_LOGIC := '0';
+ VARIABLE DLL_done : STD_LOGIC := '0';
+ VARIABLE DLL_count : INTEGER := 0;
+
+ -- Timing Check
+ VARIABLE MRD_chk : TIME := 0 ns;
+ VARIABLE RFC_chk : TIME := 0 ns;
+ VARIABLE RRD_chk : TIME := 0 ns;
+ VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns;
+ VARIABLE RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3 : TIME := 0 ns;
+ VARIABLE RC_chk0, RC_chk1, RC_chk2, RC_chk3 : TIME := 0 ns;
+ VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns;
+ VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns;
+ VARIABLE WR_chk0, WR_chk1, WR_chk2, WR_chk3 : TIME := 0 ns;
+
+ -- Read pipeline variables
+ VARIABLE Read_cmnd : Array_Read_cmnd;
+ VARIABLE Read_bank : Array_Read_bank;
+ VARIABLE Read_cols : Array_Read_cols;
+
+ -- Write pipeline variables
+ VARIABLE Write_cmnd : Array_Write_cmnd;
+ VARIABLE Write_bank : Array_Write_bank;
+ VARIABLE Write_cols : Array_Write_cols;
+
+ -- Auto Precharge variables
+ VARIABLE Read_precharge : Array_Read_precharge := ('0' & '0' & '0' & '0');
+ VARIABLE Write_precharge : Array_Write_precharge := ('0' & '0' & '0' & '0');
+ VARIABLE Count_precharge : Array_Count_precharge := ( 0 & 0 & 0 & 0 );
+
+ -- Manual Precharge variables
+ VARIABLE A10_precharge : Array_A10_precharge;
+ VARIABLE Bank_precharge : Array_Bank_precharge;
+ VARIABLE Cmnd_precharge : Array_Cmnd_precharge;
+
+ -- Burst Terminate variable
+ VARIABLE Cmnd_bst : Array_Cmnd_bst;
+
+ -- Memory Banks
+ VARIABLE Bank0 : Array_ram_stor;
+ VARIABLE Bank1 : Array_ram_stor;
+ VARIABLE Bank2 : Array_ram_stor;
+ VARIABLE Bank3 : Array_ram_stor;
+
+ -- Burst Counter
+ VARIABLE Burst_counter : STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+
+ -- Internal Dqs initialize
+ VARIABLE Dqs_int : STD_LOGIC := '0';
+
+ -- Data buffer for DM Mask
+ VARIABLE Data_buf : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
+
+ --
+ -- Initialize empty rows
+ --
+ PROCEDURE Init_mem (Bank : STD_LOGIC_VECTOR; Row_index : INTEGER) IS
+ VARIABLE i, j : INTEGER := 0;
+ BEGIN
+ IF Bank = "00" THEN
+ IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty
+ Bank0 (Row_index) := NEW Array_ram_type; -- Open new row for access
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank0 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ ELSIF Bank = "01" THEN
+ IF Bank1 (Row_index) = NULL THEN
+ Bank1 (Row_index) := NEW Array_ram_type;
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank1 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ ELSIF Bank = "10" THEN
+ IF Bank2 (Row_index) = NULL THEN
+ Bank2 (Row_index) := NEW Array_ram_type;
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank2 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ ELSIF Bank = "11" THEN
+ IF Bank3 (Row_index) = NULL THEN
+ Bank3 (Row_index) := NEW Array_ram_type;
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank3 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ END IF;
+ END;
+
+ --
+ -- Burst Counter
+ --
+ PROCEDURE Burst_decode IS
+ VARIABLE Cols_temp : STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0) := (OTHERS => '0');
+ BEGIN
+ -- Advance burst counter
+ Burst_counter := Burst_counter + 1;
+
+ -- Burst Type
+ IF Mode_reg (3) = '0' THEN
+ Cols_temp := Cols_addr + 1;
+ ELSIF Mode_reg (3) = '1' THEN
+ Cols_temp (2) := Burst_counter (2) XOR Cols_brst (2);
+ Cols_temp (1) := Burst_counter (1) XOR Cols_brst (1);
+ Cols_temp (0) := Burst_counter (0) XOR Cols_brst (0);
+ END IF;
+
+ -- Burst Length
+ IF Burst_length_2 = '1' THEN
+ Cols_addr (0) := Cols_temp (0);
+ ELSIF Burst_length_4 = '1' THEN
+ Cols_addr (1 DOWNTO 0) := Cols_temp (1 DOWNTO 0);
+ ELSIF Burst_length_8 = '1' THEN
+ Cols_addr (2 DOWNTO 0) := Cols_temp (2 DOWNTO 0);
+ ELSE
+ Cols_addr := Cols_temp;
+ END IF;
+
+ -- Data counter
+ IF Burst_length_2 = '1' THEN
+ IF Burst_counter >= 2 THEN
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ ELSIF Data_out_enable = '1' THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+ ELSIF Burst_length_4 = '1' THEN
+ IF Burst_counter >= 4 THEN
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ ELSIF Data_out_enable = '1' THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+ ELSIF Burst_length_8 = '1' THEN
+ IF Burst_counter >= 8 THEN
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ ELSIF Data_out_enable = '1' THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+ END IF;
+ END;
+
+ BEGIN
+ WAIT ON Sys_clk;
+
+ --
+ -- Manual Precharge Pipeline
+ --
+ IF ((Sys_clk'EVENT AND Sys_clk = '0') OR (Sys_clk'EVENT AND Sys_clk = '1')) THEN
+ -- A10 Precharge Pipeline
+ A10_precharge(0) := A10_precharge(1);
+ A10_precharge(1) := A10_precharge(2);
+ A10_precharge(2) := A10_precharge(3);
+ A10_precharge(3) := A10_precharge(4);
+ A10_precharge(4) := A10_precharge(5);
+ A10_precharge(5) := A10_precharge(6);
+ A10_precharge(6) := A10_precharge(7);
+ A10_precharge(7) := A10_precharge(8);
+ A10_precharge(8) := '0';
+
+ -- Bank Precharge Pipeline
+ Bank_precharge(0) := Bank_precharge(1);
+ Bank_precharge(1) := Bank_precharge(2);
+ Bank_precharge(2) := Bank_precharge(3);
+ Bank_precharge(3) := Bank_precharge(4);
+ Bank_precharge(4) := Bank_precharge(5);
+ Bank_precharge(5) := Bank_precharge(6);
+ Bank_precharge(6) := Bank_precharge(7);
+ Bank_precharge(7) := Bank_precharge(8);
+ Bank_precharge(8) := "00";
+
+ -- Command Precharge Pipeline
+ Cmnd_precharge(0) := Cmnd_precharge(1);
+ Cmnd_precharge(1) := Cmnd_precharge(2);
+ Cmnd_precharge(2) := Cmnd_precharge(3);
+ Cmnd_precharge(3) := Cmnd_precharge(4);
+ Cmnd_precharge(4) := Cmnd_precharge(5);
+ Cmnd_precharge(5) := Cmnd_precharge(6);
+ Cmnd_precharge(6) := Cmnd_precharge(7);
+ Cmnd_precharge(7) := Cmnd_precharge(8);
+ Cmnd_precharge(8) := '0';
+
+ -- Terminate Read if same bank or all banks
+ IF ((Cmnd_precharge (0) = '1') AND
+ (Bank_precharge (0) = Bank_addr OR A10_precharge (0) = '1') AND
+ (Data_out_enable = '1')) THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+
+ --
+ -- Burst Terminate Pipeline
+ --
+ IF ((Sys_clk'EVENT AND Sys_clk = '0') OR (Sys_clk'EVENT AND Sys_clk = '1')) THEN
+ -- Burst Terminate pipeline
+ Cmnd_bst (0) := Cmnd_bst (1);
+ Cmnd_bst (1) := Cmnd_bst (2);
+ Cmnd_bst (2) := Cmnd_bst (3);
+ Cmnd_bst (3) := Cmnd_bst (4);
+ Cmnd_bst (4) := Cmnd_bst (5);
+ Cmnd_bst (5) := Cmnd_bst (6);
+ Cmnd_bst (6) := Cmnd_bst (7);
+ Cmnd_bst (7) := Cmnd_bst (8);
+ Cmnd_bst (8) := '0';
+
+ -- Terminate current Read
+ IF ((Cmnd_bst (0) = '1') AND (Data_out_enable = '1')) THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+
+ --
+ -- Dq and Dqs Drivers
+ --
+ IF ((Sys_clk'EVENT AND Sys_clk = '0') OR (Sys_clk'EVENT AND Sys_clk = '1')) THEN
+ -- Read Command Pipeline
+ Read_cmnd (0) := Read_cmnd (1);
+ Read_cmnd (1) := Read_cmnd (2);
+ Read_cmnd (2) := Read_cmnd (3);
+ Read_cmnd (3) := Read_cmnd (4);
+ Read_cmnd (4) := Read_cmnd (5);
+ Read_cmnd (5) := Read_cmnd (6);
+ Read_cmnd (6) := Read_cmnd (7);
+ Read_cmnd (7) := Read_cmnd (8);
+ Read_cmnd (8) := '0';
+
+ -- Read Bank Pipeline
+ Read_bank (0) := Read_bank (1);
+ Read_bank (1) := Read_bank (2);
+ Read_bank (2) := Read_bank (3);
+ Read_bank (3) := Read_bank (4);
+ Read_bank (4) := Read_bank (5);
+ Read_bank (5) := Read_bank (6);
+ Read_bank (6) := Read_bank (7);
+ Read_bank (7) := Read_bank (8);
+ Read_bank (8) := "00";
+
+ -- Read Column Pipeline
+ Read_cols (0) := Read_cols (1);
+ Read_cols (1) := Read_cols (2);
+ Read_cols (2) := Read_cols (3);
+ Read_cols (3) := Read_cols (4);
+ Read_cols (4) := Read_cols (5);
+ Read_cols (5) := Read_cols (6);
+ Read_cols (6) := Read_cols (7);
+ Read_cols (7) := Read_cols (8);
+ Read_cols (8) := (OTHERS => '0');
+
+ -- Initialize Read command
+ IF Read_cmnd (0) = '1' THEN
+ Data_out_enable := '1';
+ Bank_addr := Read_bank (0);
+ Cols_addr := Read_cols (0);
+ Cols_brst := Cols_addr (2 DOWNTO 0);
+ Burst_counter := (OTHERS => '0');
+
+ -- Row address mux
+ CASE Bank_addr IS
+ WHEN "00" => Rows_addr := B0_row_addr;
+ WHEN "01" => Rows_addr := B1_row_addr;
+ WHEN "10" => Rows_addr := B2_row_addr;
+ WHEN OTHERS => Rows_addr := B3_row_addr;
+ END CASE;
+ END IF;
+
+ -- Toggle Dqs during Read command
+ IF Data_out_enable = '1' THEN
+ Dqs_int := '0';
+ IF Dqs_out = "00" THEN
+ Dqs_out <= "11";
+ ELSIF Dqs_out = "11" THEN
+ Dqs_out <= "00";
+ ELSE
+ Dqs_out <= "00";
+ END IF;
+ ELSIF Data_out_enable = '0' AND Dqs_int = '0' THEN
+ Dqs_out <= "ZZ";
+ END IF;
+
+ -- Initialize Dqs for Read command
+ IF Read_cmnd (2) = '1' THEN
+ IF Data_out_enable = '0' THEN
+ Dqs_int := '1';
+ Dqs_out <= "00";
+ END IF;
+ END IF;
+
+ -- Read Latch
+ IF Data_out_enable = '1' THEN
+ -- Initialize Memory
+ Init_mem (Bank_addr, CONV_INTEGER(Rows_addr));
+
+ -- Output Data
+ CASE Bank_addr IS
+ WHEN "00" => Dq <= Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "01" => Dq <= Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "10" => Dq <= Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN OTHERS => Dq <= Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ END CASE;
+
+ -- Increase Burst Counter
+ Burst_decode;
+ ELSE
+ Dq <= (OTHERS => 'Z');
+ END IF;
+ END IF;
+
+ --
+ -- Write FIFO and DM Mask Logic
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ -- Write command pipeline
+ Write_cmnd (0) := Write_cmnd (1);
+ Write_cmnd (1) := Write_cmnd (2);
+ Write_cmnd (2) := '0';
+
+ -- Write command pipeline
+ Write_bank (0) := Write_bank (1);
+ Write_bank (1) := Write_bank (2);
+ Write_bank (2) := "00";
+
+ -- Write column pipeline
+ Write_cols (0) := Write_cols (1);
+ Write_cols (1) := Write_cols (2);
+ Write_cols (2) := (OTHERS => '0');
+
+ -- Initialize Write command
+ IF Write_cmnd (0) = '1' THEN
+ Data_in_enable := '1';
+ Bank_addr := Write_bank (0);
+ Cols_addr := Write_cols (0);
+ Cols_brst := Cols_addr (2 DOWNTO 0);
+ Burst_counter := (OTHERS => '0');
+
+ -- Row address mux
+ CASE Bank_addr IS
+ WHEN "00" => Rows_addr := B0_row_addr;
+ WHEN "01" => Rows_addr := B1_row_addr;
+ WHEN "10" => Rows_addr := B2_row_addr;
+ WHEN OTHERS => Rows_addr := B3_row_addr;
+ END CASE;
+ END IF;
+
+ -- Write data
+ IF Data_in_enable = '1' THEN
+ -- Initialize memory
+ Init_mem (Bank_addr, CONV_INTEGER(Rows_addr));
+
+ -- Write first data
+ IF Dm_pair (1) = '0' OR Dm_pair (0) = '0' THEN
+ -- Data Buffer
+ CASE Bank_addr IS
+ WHEN "00" => Data_buf := Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "01" => Data_buf := Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "10" => Data_buf := Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN OTHERS => Data_buf := Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ END CASE;
+
+ -- Perform DM Mask
+ IF Dm_pair (0) = '0' THEN
+ Data_buf ( 7 DOWNTO 0) := Dq_pair ( 7 DOWNTO 0);
+ END IF;
+ IF Dm_pair (1) = '0' THEN
+ Data_buf (15 DOWNTO 8) := Dq_pair (15 DOWNTO 8);
+ END IF;
+
+ -- Write Data
+ CASE Bank_addr IS
+ WHEN "00" => Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "01" => Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "10" => Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN OTHERS => Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ END CASE;
+ END IF;
+
+ -- Increase Burst Counter
+ Burst_decode;
+
+ -- Write second data
+ IF Dm_pair (3) = '0' OR Dm_pair (2) = '0' THEN
+ -- Data Buffer
+ CASE Bank_addr IS
+ WHEN "00" => Data_buf := Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "01" => Data_buf := Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "10" => Data_buf := Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN OTHERS => Data_buf := Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ END CASE;
+
+ -- Perform DM Mask
+ IF Dm_pair (2) = '0' THEN
+ Data_buf ( 7 DOWNTO 0) := Dq_pair (23 DOWNTO 16);
+ END IF;
+ IF Dm_pair (3) = '0' THEN
+ Data_buf (15 DOWNTO 8) := Dq_pair (31 DOWNTO 24);
+ END IF;
+
+ -- Write Data
+ CASE Bank_addr IS
+ WHEN "00" => Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "01" => Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "10" => Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN OTHERS => Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ END CASE;
+ END IF;
+
+ -- Increase Burst Counter
+ Burst_decode;
+
+ -- tWR start and tWTR check
+ IF Dm_pair (3 DOWNTO 2) = "00" OR Dm_pair (1 DOWNTO 0) = "00" THEN
+ CASE Bank_addr IS
+ WHEN "00" => WR_chk0 := NOW;
+ WHEN "01" => WR_chk1 := NOW;
+ WHEN "10" => WR_chk2 := NOW;
+ WHEN OTHERS => WR_chk3 := NOW;
+ END CASE;
+
+ -- tWTR check
+ ASSERT (Read_enable = '0')
+ REPORT "tWTR violation during Read"
+ SEVERITY WARNING;
+ END IF;
+ END IF;
+ END IF;
+
+ --
+ -- Auto Precharge Calculation
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ -- Precharge counter
+ IF Read_precharge (0) = '1' OR Write_precharge (0) = '1' THEN
+ Count_precharge (0) := Count_precharge (0) + 1;
+ END IF;
+ IF Read_precharge (1) = '1' OR Write_precharge (1) = '1' THEN
+ Count_precharge (1) := Count_precharge (1) + 1;
+ END IF;
+ IF Read_precharge (2) = '1' OR Write_precharge (2) = '1' THEN
+ Count_precharge (2) := Count_precharge (2) + 1;
+ END IF;
+ IF Read_precharge (3) = '1' OR Write_precharge (3) = '1' THEN
+ Count_precharge (3) := Count_precharge (3) + 1;
+ END IF;
+
+ -- Read with AutoPrecharge Calculation
+ -- The device start internal precharge when:
+ -- 1. Meet tRAS requirement
+ -- 2. BL/2 cycles after command
+ IF ((Read_precharge(0) = '1') AND (NOW - RAS_chk0 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(0) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(0) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(0) >= 4)) THEN
+ Pc_b0 := '1';
+ Act_b0 := '0';
+ RP_chk0 := NOW;
+ Read_precharge(0) := '0';
+ END IF;
+ END IF;
+ IF ((Read_precharge(1) = '1') AND (NOW - RAS_chk1 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(1) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(1) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(1) >= 4)) THEN
+ Pc_b1 := '1';
+ Act_b1 := '0';
+ RP_chk1 := NOW;
+ Read_precharge(1) := '0';
+ END IF;
+ END IF;
+ IF ((Read_precharge(2) = '1') AND (NOW - RAS_chk2 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(2) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(2) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(2) >= 4)) THEN
+ Pc_b2 := '1';
+ Act_b2 := '0';
+ RP_chk2 := NOW;
+ Read_precharge(2) := '0';
+ END IF;
+ END IF;
+ IF ((Read_precharge(3) = '1') AND (NOW - RAS_chk3 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(3) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(3) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(3) >= 4)) THEN
+ Pc_b3 := '1';
+ Act_b3 := '0';
+ RP_chk3 := NOW;
+ Read_precharge(3) := '0';
+ END IF;
+ END IF;
+
+ -- Write with AutoPrecharge Calculation
+ -- The device start internal precharge when:
+ -- 1. Meet tRAS requirement
+ -- 2. Two clock after last burst
+ -- Since tWR is time base, the model will compensate tRP
+ IF ((Write_precharge(0) = '1') AND (NOW - RAS_chk0 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (0) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (0) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (0) >= 7)) THEN
+ Pc_b0 := '1';
+ Act_b0 := '0';
+ RP_chk0 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(0) := '0';
+ END IF;
+ END IF;
+ IF ((Write_precharge(1) = '1') AND (NOW - RAS_chk1 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (1) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (1) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (1) >= 7)) THEN
+ Pc_b1 := '1';
+ Act_b1 := '0';
+ RP_chk1 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(1) := '0';
+ END IF;
+ END IF;
+ IF ((Write_precharge(2) = '1') AND (NOW - RAS_chk2 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (2) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (2) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (2) >= 7)) THEN
+ Pc_b2 := '1';
+ Act_b2 := '0';
+ RP_chk2 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(2) := '0';
+ END IF;
+ END IF;
+ IF ((Write_precharge(3) = '1') AND (NOW - RAS_chk3 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (3) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (3) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (3) >= 7)) THEN
+ Pc_b3 := '1';
+ Act_b3 := '0';
+ RP_chk3 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(3) := '0';
+ END IF;
+ END IF;
+ END IF;
+
+ --
+ -- DLL Counter
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ IF (DLL_Reset = '1' AND DLL_done = '0') THEN
+ DLL_count := DLL_count + 1;
+ IF (DLL_count >= 200) THEN
+ DLL_done := '1';
+ END IF;
+ END IF;
+ END IF;
+
+ --
+ -- Control Logic
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ -- Auto Refresh
+ IF Aref_enable = '1' THEN
+ -- Auto Refresh to Auto Refresh
+ ASSERT (NOW - RFC_chk >= tRFC)
+ REPORT "tRFC violation during Auto Refresh"
+ SEVERITY WARNING;
+
+ -- Precharge to Auto Refresh
+ ASSERT ((NOW - RP_chk0 >= tRP) AND (NOW - RP_chk1 >= tRP) AND
+ (NOW - RP_chk2 >= tRP) AND (NOW - RP_chk3 >= tRP))
+ REPORT "tRP violation during Auto Refresh"
+ SEVERITY WARNING;
+
+ -- Precharge to Auto Refresh
+ ASSERT (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1')
+ REPORT "All banks must be Precharge before Auto Refresh"
+ SEVERITY WARNING;
+
+ -- Record current tRFC time
+ RFC_chk := NOW;
+ END IF;
+
+ -- Extended Load Mode Register
+ IF Ext_mode_enable = '1' THEN
+ IF (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1') THEN
+ IF (Addr (0) = '0') THEN
+ DLL_enable := '1';
+ ELSE
+ DLL_enable := '0';
+ END IF;
+ END IF;
+
+ -- Precharge to EMR
+ ASSERT (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1')
+ REPORT "All bank must be Precharged before Extended Mode Register"
+ SEVERITY WARNING;
+
+ -- Precharge to EMR
+ ASSERT ((NOW - RP_chk0 >= tRP) AND (NOW - RP_chk1 >= tRP) AND
+ (NOW - RP_chk2 >= tRP) AND (NOW - RP_chk3 >= tRP))
+ REPORT "tRP violation during Extended Load Register"
+ SEVERITY WARNING;
+
+ -- LMR/EMR to EMR
+ ASSERT (NOW - MRD_chk >= tMRD)
+ REPORT "tMRD violation during Extended Mode Register"
+ SEVERITY WARNING;
+
+ -- Record current tMRD time
+ MRD_chk := NOW;
+ END IF;
+
+ -- Load Mode Register
+ IF Mode_reg_enable = '1' THEN
+ -- Register mode
+ Mode_reg <= Addr;
+
+ -- DLL Reset
+ IF (DLL_enable = '1' AND Addr (8) = '1') THEN
+ DLL_reset := '1';
+ DLL_done := '0';
+ DLL_count := 0;
+ ELSIF (DLL_enable = '1' AND DLL_reset = '0' AND Addr (8) = '0') THEN
+ ASSERT (FALSE)
+ REPORT "DLL is ENABLE: DLL RESET is require"
+ SEVERITY WARNING;
+ ELSIF (DLL_enable = '0' AND Addr (8) = '1') THEN
+ ASSERT (FALSE)
+ REPORT "DLL is DISABLE: DLL RESET will be ignored"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge to LMR
+ ASSERT (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1')
+ REPORT "All bank must be Precharged before Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Precharge to EMR
+ ASSERT ((NOW - RP_chk0 >= tRP) AND (NOW - RP_chk1 >= tRP) AND
+ (NOW - RP_chk2 >= tRP) AND (NOW - RP_chk3 >= tRP))
+ REPORT "tRP violation during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- LMR/ELMR to LMR
+ ASSERT (NOW - MRD_chk >= tMRD)
+ REPORT "tMRD violation during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Check for invalid Burst Length
+ ASSERT ((Addr (2 DOWNTO 0) = "001") OR -- BL = 2
+ (Addr (2 DOWNTO 0) = "010") OR -- BL = 4
+ (Addr (2 DOWNTO 0) = "011")) -- BL = 8
+ REPORT "Invalid Burst Length during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Check for invalid CAS Latency
+ ASSERT ((Addr (6 DOWNTO 4) = "010") OR -- CL = 2.0
+ (Addr (6 DOWNTO 4) = "110")) -- CL = 2.5
+ REPORT "Invalid CAS Latency during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Record current tMRD time
+ MRD_chk := NOW;
+ END IF;
+
+ -- Active Block (latch Bank and Row Address)
+ IF Active_enable = '1' THEN
+ -- Activate an OPEN bank can corrupt data
+ ASSERT ((Ba = "00" AND Act_b0 = '0') OR
+ (Ba = "01" AND Act_b1 = '0') OR
+ (Ba = "10" AND Act_b2 = '0') OR
+ (Ba = "11" AND Act_b3 = '0'))
+ REPORT "Bank is already activated - data can be corrupted"
+ SEVERITY WARNING;
+
+ -- Activate Bank 0
+ IF Ba = "00" AND Pc_b0 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk0 >= tRC)
+ REPORT "tRC violation during Activate Bank 0"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk0 >= tRP)
+ REPORT "tRP violation during Activate Bank 0"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b0 := '1';
+ Pc_b0 := '0';
+ B0_row_addr := Addr;
+ RC_chk0 := NOW;
+ RCD_chk0 := NOW;
+ RAS_chk0 := NOW;
+ RAP_chk0 := NOW;
+ END IF;
+
+ -- Activate Bank 1
+ IF Ba = "01" AND Pc_b1 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk1 >= tRC)
+ REPORT "tRC violation during Activate Bank 1"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk1 >= tRP)
+ REPORT "tRP violation during Activate Bank 1"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b1 := '1';
+ Pc_b1 := '0';
+ B1_row_addr := Addr;
+ RC_chk1 := NOW;
+ RCD_chk1 := NOW;
+ RAS_chk1 := NOW;
+ RAP_chk1 := NOW;
+ END IF;
+
+ -- Activate Bank 2
+ IF Ba = "10" AND Pc_b2 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk2 >= tRC)
+ REPORT "tRC violation during Activate Bank 2"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk2 >= tRP)
+ REPORT "tRP violation during Activate Bank 2"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b2 := '1';
+ Pc_b2 := '0';
+ B2_row_addr := Addr;
+ RC_chk2 := NOW;
+ RCD_chk2 := NOW;
+ RAS_chk2 := NOW;
+ RAP_chk2 := NOW;
+ END IF;
+
+ -- Activate Bank 3
+ IF Ba = "11" AND Pc_b3 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk3 >= tRC)
+ REPORT "tRC violation during Activate Bank 3"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk3 >= tRP)
+ REPORT "tRP violation during Activate Bank 3"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b3 := '1';
+ Pc_b3 := '0';
+ B3_row_addr := Addr;
+ RC_chk3 := NOW;
+ RCD_chk3 := NOW;
+ RAS_chk3 := NOW;
+ RAP_chk3 := NOW;
+ END IF;
+
+ -- Activate Bank A to Activate Bank B
+ IF (Prev_bank /= Ba) THEN
+ ASSERT (NOW - RRD_chk >= tRRD)
+ REPORT "tRRD violation during Activate"
+ SEVERITY WARNING;
+ END IF;
+
+ -- AutoRefresh to Activate
+ ASSERT (NOW - RFC_chk >= tRFC)
+ REPORT "tRFC violation during Activate"
+ SEVERITY WARNING;
+
+ -- Record Variables for Checking Violation
+ RRD_chk := NOW;
+ Prev_bank := Ba;
+ END IF;
+
+ -- Precharge Block - Consider NOP if bank already precharged or in process of precharging
+ IF Prech_enable = '1' THEN
+ -- EMR or LMR to Precharge
+ ASSERT (NOW - MRD_chk >= tMRD)
+ REPORT "tMRD violation during Precharge"
+ SEVERITY WARNING;
+
+ -- Precharge Bank 0
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "00")) AND Act_b0 = '1') THEN
+ Act_b0 := '0';
+ Pc_b0 := '1';
+ RP_chk0 := NOW;
+
+ -- Activate to Precharge bank 0
+ ASSERT (NOW - RAS_chk0 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk0 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge Bank 1
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "01")) AND Act_b1 = '1') THEN
+ Act_b1 := '0';
+ Pc_b1 := '1';
+ RP_chk1 := NOW;
+
+ -- Activate to Precharge
+ ASSERT (NOW - RAS_chk1 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk1 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge Bank 2
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "10")) AND Act_b2 = '1') THEN
+ Act_b2 := '0';
+ Pc_b2 := '1';
+ RP_chk2 := NOW;
+
+ -- Activate to Precharge
+ ASSERT (NOW - RAS_chk2 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk2 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge Bank 3
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "11")) AND Act_b3 = '1') THEN
+ Act_b3 := '0';
+ Pc_b3 := '1';
+ RP_chk3 := NOW;
+
+ -- Activate to Precharge
+ ASSERT (NOW - RAS_chk3 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk3 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Pipeline for READ
+ IF CAS_latency_15 = '1' THEN
+ A10_precharge (3) := Addr(10);
+ Bank_precharge (3) := Ba;
+ Cmnd_precharge (3) := '1';
+ ELSIF CAS_latency_2 = '1' THEN
+ A10_precharge (4) := Addr(10);
+ Bank_precharge (4) := Ba;
+ Cmnd_precharge (4) := '1';
+ ELSIF CAS_latency_25 = '1' THEN
+ A10_precharge (5) := Addr(10);
+ Bank_precharge (5) := Ba;
+ Cmnd_precharge (5) := '1';
+ ELSIF CAS_latency_3 = '1' THEN
+ A10_precharge (6) := Addr(10);
+ Bank_precharge (6) := Ba;
+ Cmnd_precharge (6) := '1';
+ ELSIF CAS_latency_4 = '1' THEN
+ A10_precharge (8) := Addr(10);
+ Bank_precharge (8) := Ba;
+ Cmnd_precharge (8) := '1';
+ END IF;
+ END IF;
+
+ -- Burst Terminate
+ IF Burst_term = '1' THEN
+ -- Pipeline for Read
+ IF CAS_latency_15 = '1' THEN
+ Cmnd_bst (3) := '1';
+ ELSIF CAS_latency_2 = '1' THEN
+ Cmnd_bst (4) := '1';
+ ELSIF CAS_latency_25 = '1' THEN
+ Cmnd_bst (5) := '1';
+ ELSIF CAS_latency_3 = '1' THEN
+ Cmnd_bst (6) := '1';
+ ELSIF CAS_latency_4 = '1' THEN
+ Cmnd_bst (8) := '1';
+ END IF;
+
+ -- Terminate Write
+ ASSERT (Data_in_enable = '0')
+ REPORT "It's illegal to Burst Terminate a Write"
+ SEVERITY WARNING;
+
+ -- Terminate Read with Auto Precharge
+ ASSERT (Read_precharge (0) = '0' AND Read_precharge (1) = '0' AND
+ Read_precharge (2) = '0' AND Read_precharge (3) = '0')
+ REPORT "It's illegal to Burst Terminate a Read with Auto Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Read Command
+ IF Read_enable = '1' THEN
+ -- CAS Latency Pipeline
+ IF Cas_latency_15 = '1' THEN
+ Read_cmnd (3) := '1';
+ Read_bank (3) := Ba;
+ Read_cols (3) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_2 = '1' THEN
+ Read_cmnd (4) := '1';
+ Read_bank (4) := Ba;
+ Read_cols (4) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_25 = '1' THEN
+ Read_cmnd (5) := '1';
+ Read_bank (5) := Ba;
+ Read_cols (5) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_3 = '1' THEN
+ Read_cmnd (6) := '1';
+ Read_bank (6) := Ba;
+ Read_cols (6) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_4 = '1' THEN
+ Read_cmnd (8) := '1';
+ Read_bank (8) := Ba;
+ Read_cols (8) := Addr (8 DOWNTO 0);
+ END IF;
+
+ -- Write to Read: Terminate Write Immediately
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ END IF;
+
+ -- Interrupting a Read with Auto Precharge (same bank only)
+ ASSERT (Read_precharge(CONV_INTEGER(Ba)) = '0')
+ REPORT "It's illegal to interrupt a Read with Auto Precharge"
+ SEVERITY WARNING;
+
+ -- Activate to Read
+ ASSERT ((Ba = "00" AND Act_b0 = '1') OR
+ (Ba = "01" AND Act_b1 = '1') OR
+ (Ba = "10" AND Act_b2 = '1') OR
+ (Ba = "11" AND Act_b3 = '1'))
+ REPORT "Bank is not Activated for Read"
+ SEVERITY WARNING;
+
+ -- Activate to Read without Auto Precharge
+ IF Addr (10) = '0' THEN
+ ASSERT ((Ba = "00" AND NOW - RCD_chk0 >= tRCD) OR
+ (Ba = "01" AND NOW - RCD_chk1 >= tRCD) OR
+ (Ba = "10" AND NOW - RCD_chk2 >= tRCD) OR
+ (Ba = "11" AND NOW - RCD_chk3 >= tRCD))
+ REPORT "tRCD violation during Read"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Activate to Read with Auto Precharge
+ IF Addr (10) = '1' THEN
+ ASSERT ((Ba = "00" AND NOW - RAP_chk0 >= tRAP) OR
+ (Ba = "01" AND NOW - RAP_chk1 >= tRAP) OR
+ (Ba = "10" AND NOW - RAP_chk2 >= tRAP) OR
+ (Ba = "11" AND NOW - RAP_chk3 >= tRAP))
+ REPORT "tRAP violation during Read"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Auto precharge
+ IF Addr (10) = '1' THEN
+ Read_precharge (Conv_INTEGER(Ba)) := '1';
+ Count_precharge (Conv_INTEGER(Ba)) := 0;
+ END IF;
+
+ -- DLL Check
+ IF (DLL_reset = '1') THEN
+ ASSERT (DLL_done = '1')
+ REPORT "DLL RESET not complete"
+ SEVERITY WARNING;
+ END IF;
+ END IF;
+
+ -- Write Command
+ IF Write_enable = '1' THEN
+ -- Pipeline for Write
+ Write_cmnd (2) := '1';
+ Write_bank (2) := Ba;
+ Write_cols (2) := Addr (8 DOWNTO 0);
+
+ -- Interrupting a Write with Auto Precharge (same bank only)
+ ASSERT (Write_precharge(CONV_INTEGER(Ba)) = '0')
+ REPORT "It's illegal to interrupt a Write with Auto Precharge"
+ SEVERITY WARNING;
+
+ -- Activate to Write
+ ASSERT ((Ba = "00" AND Act_b0 = '1') OR
+ (Ba = "01" AND Act_b1 = '1') OR
+ (Ba = "10" AND Act_b2 = '1') OR
+ (Ba = "11" AND Act_b3 = '1'))
+ REPORT "Bank is not Activated for Write"
+ SEVERITY WARNING;
+
+ -- Activate to Write
+ ASSERT ((Ba = "00" AND NOW - RCD_chk0 >= tRCD) OR
+ (Ba = "01" AND NOW - RCD_chk1 >= tRCD) OR
+ (Ba = "10" AND NOW - RCD_chk2 >= tRCD) OR
+ (Ba = "11" AND NOW - RCD_chk3 >= tRCD))
+ REPORT "tRCD violation during Write"
+ SEVERITY WARNING;
+
+ -- Auto precharge
+ IF Addr (10) = '1' THEN
+ Write_precharge (Conv_INTEGER(Ba)) := '1';
+ Count_precharge (Conv_INTEGER(Ba)) := 0;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+ --
+ -- Dqs Receiver
+ --
+ dqs_rcvrs : PROCESS
+ VARIABLE Dm_temp : STD_LOGIC_VECTOR (1 DOWNTO 0);
+ VARIABLE Dq_temp : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0);
+ BEGIN
+ WAIT ON Dqs;
+ -- Latch data at posedge Dqs
+ IF Dqs'EVENT AND Dqs (1) = '1' AND Dqs (0) = '1' THEN
+ Dq_temp := Dq;
+ Dm_temp := Dm;
+ END IF;
+ -- Latch data at negedge Dqs
+ IF Dqs'EVENT AND Dqs (1) = '0' AND Dqs (0) = '0' THEN
+ Dq_pair <= (Dq & Dq_temp);
+ Dm_pair <= (Dm & Dm_temp);
+ END IF;
+ END PROCESS;
+
+ --
+ -- Setup timing checks
+ --
+ Setup_check : PROCESS
+ BEGIN
+ WAIT ON Sys_clk;
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ ASSERT(Cke'LAST_EVENT >= tIS)
+ REPORT "CKE Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Cs_n'LAST_EVENT >= tIS)
+ REPORT "CS# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Cas_n'LAST_EVENT >= tIS)
+ REPORT "CAS# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Ras_n'LAST_EVENT >= tIS)
+ REPORT "RAS# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(We_n'LAST_EVENT >= tIS)
+ REPORT "WE# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Addr'LAST_EVENT >= tIS)
+ REPORT "ADDR Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Ba'LAST_EVENT >= tIS)
+ REPORT "BA Setup time violation -- tIS"
+ SEVERITY WARNING;
+ END IF;
+ END PROCESS;
+
+ --
+ -- Hold timing checks
+ --
+ Hold_check : PROCESS
+ BEGIN
+ WAIT ON Sys_clk'DELAYED (tIH);
+ IF Sys_clk'DELAYED (tIH) = '1' THEN
+ ASSERT(Cke'LAST_EVENT >= tIH)
+ REPORT "CKE Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Cs_n'LAST_EVENT >= tIH)
+ REPORT "CS# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Cas_n'LAST_EVENT >= tIH)
+ REPORT "CAS# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Ras_n'LAST_EVENT >= tIH)
+ REPORT "RAS# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(We_n'LAST_EVENT >= tIH)
+ REPORT "WE# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Addr'LAST_EVENT >= tIH)
+ REPORT "ADDR Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Ba'LAST_EVENT >= tIH)
+ REPORT "BA Hold time violation -- tIH"
+ SEVERITY WARNING;
+ END IF;
+ END PROCESS;
+
+END behave;
OpenPOWER on IntegriCloud