From 0711a2b4fc2dec8bf65e5821095bed895976b83a Mon Sep 17 00:00:00 2001 From: oharboe Date: Wed, 18 Jun 2008 09:22:21 +0000 Subject: * Various ZY2000 vhdl files of more general interest made available as part of the ZPU project under the same license(FreeBSD). Files should have headers updated. --- misc/ChangeLog | 5 + misc/arm7/src/arm7pkg.vhd | 31 + misc/arm7/src/arm7wb.vhd | 236 ++++++ misc/ddrsdram/simscripts/ddr_tb.do | 16 + misc/ddrsdram/simscripts/ddr_top.do | 104 +++ misc/ddrsdram/simsrc/ddr_tb.vhd | 301 ++++++++ misc/ddrsdram/src/ddr_pkg.vhd | 107 +++ misc/ddrsdram/src/ddr_top.vhd | 743 +++++++++++++++++++ misc/ddrsdram/src/mt46v16m16.vhd | 1320 +++++++++++++++++++++++++++++++++ misc/readme.txt | 20 + misc/wishbone/src/atomic32_access.vhd | 132 ++++ misc/wishbone/src/wishbone_pkg.vhd | 52 ++ 12 files changed, 3067 insertions(+) create mode 100644 misc/ChangeLog create mode 100644 misc/arm7/src/arm7pkg.vhd create mode 100644 misc/arm7/src/arm7wb.vhd create mode 100644 misc/ddrsdram/simscripts/ddr_tb.do create mode 100644 misc/ddrsdram/simscripts/ddr_top.do create mode 100644 misc/ddrsdram/simsrc/ddr_tb.vhd create mode 100644 misc/ddrsdram/src/ddr_pkg.vhd create mode 100644 misc/ddrsdram/src/ddr_top.vhd create mode 100644 misc/ddrsdram/src/mt46v16m16.vhd create mode 100644 misc/readme.txt create mode 100644 misc/wishbone/src/atomic32_access.vhd create mode 100644 misc/wishbone/src/wishbone_pkg.vhd (limited to 'misc') diff --git a/misc/ChangeLog b/misc/ChangeLog new file mode 100644 index 0000000..3225839 --- /dev/null +++ b/misc/ChangeLog @@ -0,0 +1,5 @@ +2008-06-18 Øyvind Harboe + + * Various ZY2000 vhdl files of more general interest made + available as part of the ZPU project under the same + license(FreeBSD). Files should have headers updated. diff --git a/misc/arm7/src/arm7pkg.vhd b/misc/arm7/src/arm7pkg.vhd new file mode 100644 index 0000000..855fbdb --- /dev/null +++ b/misc/arm7/src/arm7pkg.vhd @@ -0,0 +1,31 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +library work; +use work.wishbone_pkg.all; + +package arm7 is + + component arm7wb + generic( + simulate_io_time : boolean := false); + port ( areset : in std_logic; + cpu_clk : in std_logic; + cpu_clk_2x : in std_logic; + cpu_a_p : in std_logic_vector(23 downto 1); + cpu_wr_n_p : in std_logic_vector(1 downto 0); + cpu_cs_n_p : in std_logic_vector(3 downto 1); + cpu_oe_n_p : in std_logic; + cpu_d_p : inout std_logic_vector(15 downto 0); + cpu_wait_n_p : out std_logic; + + arm7_debug : out std_logic; + arm7_debug2 : out std_logic; + + wb_o : out wishbone_bus_in; + wb_i : in wishbone_bus_out); + end component; + +end arm7; + + \ No newline at end of file diff --git a/misc/arm7/src/arm7wb.vhd b/misc/arm7/src/arm7wb.vhd new file mode 100644 index 0000000..3366352 --- /dev/null +++ b/misc/arm7/src/arm7wb.vhd @@ -0,0 +1,236 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +library work; +use work.phi_config.all; +use work.wishbone_pkg.all; + +entity arm7wb is + generic( + simulate_io_time : boolean := false); + port ( areset : in std_logic; + cpu_clk : in std_logic; + cpu_clk_2x : in std_logic; + cpu_a_p : in std_logic_vector(23 downto 1); + cpu_wr_n_p : in std_logic_vector(1 downto 0); + cpu_cs_n_p : in std_logic_vector(3 downto 1); + cpu_oe_n_p : in std_logic; + cpu_d_p : inout std_logic_vector(15 downto 0); + cpu_wait_n_p : out std_logic; + + arm7_debug : out std_logic; + arm7_debug2 : out std_logic; + + wb_o : out wishbone_bus_in; + wb_i : in wishbone_bus_out); +end arm7wb; + +architecture behave of arm7wb is + +type cpu_state_type is (cpu_idle, cpu_cs, cpu_end); + +-- Input simulated delay +signal cpu_wr_n_p_del : std_logic_vector(1 downto 0); +signal cpu_a_p_del : std_logic_vector(23 downto 1); +signal cpu_d_p_del : std_logic_vector(15 downto 0); +signal cpu_cs_n_p_del : std_logic_vector(3 downto 1); +signal cpu_oe_n_p_del : std_logic; + +-- Clock phase detect signals +signal cpu_clk_toggle : std_logic; +signal cpu_clk_smp1 : std_logic; +signal cpu_clk_smp2 : std_logic; +signal cpu_clk_phase : std_logic; + +-- Internal version of control signal (for feedback) +signal arm7_din_int : std_logic_vector(15 downto 0); +signal arm7_dout_int : std_logic_vector(15 downto 0); +signal arm7_a_int : std_logic_vector(23 downto 1); +signal arm7_we_int : std_logic_vector(1 downto 0); +signal cyc_int : std_logic; +signal we_int : std_logic; +signal adr_reg : std_logic_vector(25 downto 24); + +-- Input sampled +signal cpu_a_smp : std_logic_vector(23 downto 1); +signal cpu_d_smp : std_logic_vector(15 downto 0); +signal cpu_cs_n : std_logic_vector(3 downto 1); +signal cpu_oe_n : std_logic; +signal cpu_wr_n : std_logic_vector(1 downto 0); + +-- Main FSM +signal cpu_state : cpu_state_type; + +constant Clock_2_Out : time := 5.5 ns; +constant Input_Setup : time := 2.5 ns; + +begin + + arm7_dout_int <= wb_i.dat(15 downto 0) when (arm7_a_int(1) = '0') else wb_i.dat(31 downto 16); + arm7_debug <= cpu_oe_n; + arm7_debug2 <= cpu_wr_n(0); + + -- Generate 64 MBytes address based on 3 CS_N signals from CPU + -- Memory map FPGA internal + -- 0x00000000 DDR 32 MBytes (CS_N2 and CS_N3) + -- 0x00200000 FPGA/Ethernet (CS_N1) + wb_o.adr(31 downto 26) <= "000000"; + wb_o.adr(25 downto 24) <= adr_reg; + wb_o.adr(23 downto 1) <= arm7_a_int(23 downto 1); + wb_o.adr(0) <= '0'; + + wb_o.dat <= (x"0000" & arm7_din_int) when (arm7_a_int(1) = '0') else (arm7_din_int & x"0000"); + wb_o.sel <= ("00" & arm7_we_int) when (arm7_a_int(1) = '0') else (arm7_we_int & "00"); + + wb_o.cyc <= cyc_int; + wb_o.stb <= cyc_int; + wb_o.we <= cpu_oe_n; + + iotimingon: + if simulate_io_time generate + begin + cpu_wr_n_p_del <= transport "XX" after 0 ns, cpu_wr_n_p after Input_Setup; + cpu_a_p_del <= transport "XXXXXXXXXXXXXXXXXXXXXXX" after 0 ns, cpu_a_p after Input_Setup; + cpu_d_p_del <= transport "XXXXXXXXXXXXXXXX" after 0 ns, cpu_d_p after Input_Setup; + cpu_cs_n_p_del <= transport "XXX" after 0 ns, cpu_cs_n_p after Input_Setup; + cpu_oe_n_p_del <= transport 'X' after 0 ns, cpu_oe_n_p after Input_Setup; + end generate; + + iotimingoff: + if not simulate_io_time generate + begin + cpu_wr_n_p_del <= cpu_wr_n_p; + cpu_a_p_del <= cpu_a_p; + cpu_d_p_del <= cpu_d_p; + cpu_cs_n_p_del <= cpu_cs_n_p; + cpu_oe_n_p_del <= cpu_oe_n_p; + end generate; + + process(cpu_clk, areset) -- Toggle FF with 1x clock to find phase + begin + if areset = '1' then + cpu_clk_toggle <= '0'; + elsif (cpu_clk'event and cpu_clk = '1') then + cpu_clk_toggle <= not(cpu_clk_toggle); + end if; + end process; + + process(cpu_clk_2x, areset) -- Find phase relationsship between 1x and 2x clock + begin + if areset = '1' then + cpu_clk_smp1 <= '0'; + cpu_clk_smp2 <= '1'; + cpu_clk_phase <= '0'; + elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then + cpu_clk_smp1 <= cpu_clk_toggle; + cpu_clk_smp2 <= cpu_clk_smp1; + if cpu_clk_smp1 = '1' and cpu_clk_smp2 = '0' then + cpu_clk_phase <= '0'; + else + cpu_clk_phase <= not(cpu_clk_phase); + end if; + end if; + end process; + + process(cpu_clk_2x, areset) -- Sample input signals on 2x clock + begin + if areset = '1' then + cpu_d_smp <= "0000000000000000"; + cpu_cs_n <= "111"; + elsif (cpu_clk_2x = '1' and cpu_clk_2x'event) then + cpu_d_smp <= cpu_d_p_del; + cpu_cs_n <= cpu_cs_n_p_del; + end if; + end process; + + process(cpu_clk, areset) -- Sample input signals on 1x clock + begin + if areset = '1' then + cpu_a_smp <= "00000000000000000000000"; + cpu_oe_n <= '1'; + cpu_wr_n <= "11"; + elsif (cpu_clk = '1' and cpu_clk'event) then + cpu_a_smp <= cpu_a_p_del; + cpu_oe_n <= cpu_oe_n_p_del; + cpu_wr_n <= cpu_wr_n_p_del; + end if; + end process; + + arm7_din_int <= cpu_d_smp; + arm7_a_int <= cpu_a_smp; + arm7_we_int <= not(cpu_wr_n); + + process(cpu_clk, areset) + begin + if areset = '1' then + cpu_state <= cpu_idle; + cyc_int <= '0'; + we_int <= '0'; + adr_reg <= "00"; + cpu_d_p <= (others => 'Z'); + elsif (cpu_clk'event and cpu_clk = '1') then + + cyc_int <= '0'; + we_int <= '0'; + cpu_d_p <= (others => 'Z') after Clock_2_Out; + + + case cpu_state is + + when cpu_idle => + if cpu_oe_n = '1' then + we_int <= '1'; + end if; + if cpu_cs_n(1) = '0' then + cyc_int <= '1'; + adr_reg <= "10"; + cpu_state <= cpu_cs; + end if; + if cpu_cs_n(2) = '0' then + cyc_int <= '1'; + adr_reg <= "00"; + cpu_state <= cpu_cs; + end if; + if cpu_cs_n(3) = '0' then + cyc_int <= '1'; + adr_reg <= "01"; + cpu_state <= cpu_cs; + end if; + + when cpu_cs => + if cpu_oe_n = '0' then + cpu_d_p <= arm7_dout_int after Clock_2_Out; + if wb_i.ack = '1' then + cpu_state <= cpu_end; + else + cyc_int <= '1'; + end if; + else + if wb_i.ack = '0' then + cyc_int <= '1'; + we_int <= '1'; + else + cpu_state <= cpu_end; + end if; + end if; + + when others => + cpu_state <= cpu_idle; + + end case; + end if; + end process; + + process(cpu_clk_2x, areset) + begin + if areset = '1' then + cpu_wait_n_p <= '1'; + elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then + cpu_wait_n_p <= '1' after Clock_2_Out; + if (cpu_state = cpu_cs and wb_i.ack = '0') then + cpu_wait_n_p <= '0' after Clock_2_Out; + end if; + end if; + end process; + +end behave; 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..249dffb --- /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..0e41a88 --- /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..033e9f8 --- /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..6b89345 --- /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; diff --git a/misc/readme.txt b/misc/readme.txt new file mode 100644 index 0000000..0ae1786 --- /dev/null +++ b/misc/readme.txt @@ -0,0 +1,20 @@ +These files are provided as is under a FreeBSD license. + +Patches most gratefully accepted to document this better. + +These are parts of the VHDL code that went into ZY2000 that +can be used on other FPGA brands and with other parts than +went into ZY2000. + +http://www.zylin.com/protoboard.htm + +The long term plan is to split out these from the ZPU project +into a DDR controller and ARM7 wishbone bridge +project on OpenCores.org and document them. + +Directories +=========== +arm7 - ARM7 wishbone interface +ddsdram - a generic ddr ram controller. Implemented for Xilinx + mt46v16m16 but +can be adapted to other FPGA brands and DRAM chips +wishbone - atomic 32 bit wishbone access inside FPGA and in ARM7 SW, over a 16 bit CPU databus \ No newline at end of file diff --git a/misc/wishbone/src/atomic32_access.vhd b/misc/wishbone/src/atomic32_access.vhd new file mode 100644 index 0000000..b062f98 --- /dev/null +++ b/misc/wishbone/src/atomic32_access.vhd @@ -0,0 +1,132 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +library work; +--use work.phi_config.all; +use work.wishbone_pkg.all; + +entity atomic32_access is + port ( cpu_clk : in std_logic; + areset : in std_logic; + + -- Wishbone from CPU interface + wb_16_i : in wishbone_bus_in; + wb_16_o : out wishbone_bus_out; + + -- Wishbone to FPGA registers and ethernet core + wb_32_i : in wishbone_bus_out; + wb_32_o : out wishbone_bus_in); +end atomic32_access; + +architecture behave of atomic32_access is + +type eth_state_wr_type is (idle, lsb_msb, lsb, msb, write, ack, wait_st); +signal eth_state_wr : eth_state_wr_type; +type eth_state_rd_type is (idle, lsb_msb, lsb_read, lsb, wait_st2, msb); +signal eth_state_rd : eth_state_rd_type; +signal core_data : std_logic_vector(31 downto 0); +signal core_addr : std_logic_vector(31 downto 0); + +begin + process(cpu_clk, areset) + begin + if areset = '1' then + eth_state_wr <= idle; + eth_state_rd <= idle; + wb_32_o.stb <= '0'; + wb_32_o.cyc <= '0'; + wb_16_o.ack <= '0'; + core_data <= (others => '0'); + core_addr <= (others => '0'); + elsif (rising_edge(cpu_clk)) then + + case eth_state_wr is --write cycle + when idle => + if wb_16_i.cyc = '1' and wb_16_i.we = '1' then + eth_state_wr <= lsb_msb; + end if; + when lsb_msb => + if wb_16_i.adr(1) = '0' then + eth_state_wr <= lsb; + end if; + if wb_16_i.adr(1) = '1' then + eth_state_wr <= msb; + end if; + when lsb => + core_data(15 downto 0) <= wb_16_i.dat(15 downto 0); + wb_16_o.ack <= '1'; + eth_state_wr <= wait_st; + when msb => + core_data(31 downto 16) <= wb_16_i.dat(31 downto 16); + core_addr <= wb_16_i.adr(31 downto 2) & "00"; + eth_state_wr <= write; + when write => + wb_32_o.dat <= core_data; + wb_32_o.adr <= core_addr; + wb_32_o.sel <= "1111"; + wb_32_o.we <= '1'; + wb_32_o.stb <= '1'; + wb_32_o.cyc <= '1'; + eth_state_wr <= ack; + when ack => + if wb_32_i.ack = '1' then + wb_16_o.ack <= '1'; + eth_state_wr <= wait_st; + wb_32_o.stb <= '0'; + wb_32_o.cyc <= '0'; + wb_32_o.sel <= "0000"; + wb_32_o.we <= '0'; + end if; + when wait_st => + wb_16_o.ack <= '0'; + eth_state_wr <= idle; + when others => + eth_state_wr <= idle; + end case; + + case eth_state_rd is --read cycle + when idle => + if wb_16_i.cyc = '1' and wb_16_i.we = '0' then + core_addr <= wb_16_i.adr(31 downto 2) & "00"; + eth_state_rd <= lsb_msb; + end if; + when lsb_msb => + if wb_16_i.adr(1) = '0' then + wb_32_o.adr <= core_addr; + eth_state_rd <= lsb_read; + end if; + if wb_16_i.adr(1) = '1' then + wb_32_o.adr <= core_addr; + eth_state_rd <= msb; + end if; + when lsb_read => + wb_32_o.sel <= "1111"; + wb_32_o.we <= '0'; + wb_32_o.stb <= '1'; + wb_32_o.cyc <= '1'; + eth_state_rd <= lsb; + when lsb => + if wb_32_i.ack = '1' then + wb_32_o.sel <= "0000"; + wb_32_o.stb <= '0'; + wb_32_o.cyc <= '0'; + core_data <= wb_32_i.dat; + wb_16_o.dat <= x"0000" & wb_32_i.dat(15 downto 0); + wb_16_o.ack <= '1'; + eth_state_rd <= wait_st2; + end if; + when wait_st2 => + wb_16_o.ack <= '0'; + eth_state_rd <= idle; + when msb => + wb_16_o.ack <= '1'; + wb_16_o.dat <= core_data(31 downto 16) & x"0000"; + eth_state_rd <= wait_st2; + when others => + eth_state_rd <= idle; + end case; + end if; + end process; + +end behave; \ No newline at end of file diff --git a/misc/wishbone/src/wishbone_pkg.vhd b/misc/wishbone/src/wishbone_pkg.vhd new file mode 100644 index 0000000..c3b0d9b --- /dev/null +++ b/misc/wishbone/src/wishbone_pkg.vhd @@ -0,0 +1,52 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +package wishbone_pkg is + + type wishbone_bus_in is record + adr : std_logic_vector(31 downto 0); + sel : std_logic_vector(3 downto 0); + we : std_logic; + dat : std_logic_vector(31 downto 0); -- Note! Data written with 'we' + cyc : std_logic; + stb : std_logic; + end record; + + type wishbone_bus_out is record + dat : std_logic_vector(31 downto 0); + ack : std_logic; + end record; + + type wishbone_bus is record + insig : wishbone_bus_in; + outsig : wishbone_bus_out; + end record; + + component atomic32_access is + port ( cpu_clk : in std_logic; + areset : in std_logic; + + -- Wishbone from CPU interface + wb_16_i : in wishbone_bus_in; + wb_16_o : out wishbone_bus_out; + -- Wishbone to FPGA registers and ethernet core + wb_32_i : in wishbone_bus_out; + wb_32_o : out wishbone_bus_in); + end component; + + component eth_access_corr is + port ( cpu_clk : in std_logic; + areset : in std_logic; + + -- Wishbone from Wishbone MUX + eth_raw_o : out wishbone_bus_out; + eth_raw_i : in wishbone_bus_in; + + -- Wishbone ethernet core + eth_slave_i : in wishbone_bus_out; + eth_slave_o : out wishbone_bus_in); + end component; + + +end wishbone_pkg; -- cgit v1.1 From 04772b6a0bbe7017f5f7b44cfa203c3f7efbff64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 1 Mar 2011 20:52:55 +0100 Subject: whitespace fixes: use fromdos on all .vhd files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Øyvind Harboe --- misc/arm7/src/arm7pkg.vhd | 60 +- misc/arm7/src/arm7wb.vhd | 472 +++--- misc/ddrsdram/simsrc/ddr_tb.vhd | 602 ++++---- misc/ddrsdram/src/ddr_pkg.vhd | 212 +-- misc/ddrsdram/src/ddr_top.vhd | 1486 +++++++++---------- misc/ddrsdram/src/mt46v16m16.vhd | 2640 ++++++++++++++++----------------- misc/wishbone/src/atomic32_access.vhd | 262 ++-- misc/wishbone/src/wishbone_pkg.vhd | 104 +- 8 files changed, 2919 insertions(+), 2919 deletions(-) (limited to 'misc') diff --git a/misc/arm7/src/arm7pkg.vhd b/misc/arm7/src/arm7pkg.vhd index 855fbdb..4dcbb9c 100644 --- a/misc/arm7/src/arm7pkg.vhd +++ b/misc/arm7/src/arm7pkg.vhd @@ -1,31 +1,31 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.all; -use IEEE.STD_LOGIC_UNSIGNED.ALL; -library work; -use work.wishbone_pkg.all; - -package arm7 is - - component arm7wb - generic( - simulate_io_time : boolean := false); - port ( areset : in std_logic; - cpu_clk : in std_logic; - cpu_clk_2x : in std_logic; - cpu_a_p : in std_logic_vector(23 downto 1); - cpu_wr_n_p : in std_logic_vector(1 downto 0); - cpu_cs_n_p : in std_logic_vector(3 downto 1); - cpu_oe_n_p : in std_logic; - cpu_d_p : inout std_logic_vector(15 downto 0); - cpu_wait_n_p : out std_logic; - - arm7_debug : out std_logic; - arm7_debug2 : out std_logic; - - wb_o : out wishbone_bus_in; - wb_i : in wishbone_bus_out); - end component; - -end arm7; - +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +library work; +use work.wishbone_pkg.all; + +package arm7 is + + component arm7wb + generic( + simulate_io_time : boolean := false); + port ( areset : in std_logic; + cpu_clk : in std_logic; + cpu_clk_2x : in std_logic; + cpu_a_p : in std_logic_vector(23 downto 1); + cpu_wr_n_p : in std_logic_vector(1 downto 0); + cpu_cs_n_p : in std_logic_vector(3 downto 1); + cpu_oe_n_p : in std_logic; + cpu_d_p : inout std_logic_vector(15 downto 0); + cpu_wait_n_p : out std_logic; + + arm7_debug : out std_logic; + arm7_debug2 : out std_logic; + + wb_o : out wishbone_bus_in; + wb_i : in wishbone_bus_out); + end component; + +end arm7; + \ No newline at end of file diff --git a/misc/arm7/src/arm7wb.vhd b/misc/arm7/src/arm7wb.vhd index 3366352..85f0ef7 100644 --- a/misc/arm7/src/arm7wb.vhd +++ b/misc/arm7/src/arm7wb.vhd @@ -1,236 +1,236 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.all; -use IEEE.STD_LOGIC_UNSIGNED.ALL; -library work; -use work.phi_config.all; -use work.wishbone_pkg.all; - -entity arm7wb is - generic( - simulate_io_time : boolean := false); - port ( areset : in std_logic; - cpu_clk : in std_logic; - cpu_clk_2x : in std_logic; - cpu_a_p : in std_logic_vector(23 downto 1); - cpu_wr_n_p : in std_logic_vector(1 downto 0); - cpu_cs_n_p : in std_logic_vector(3 downto 1); - cpu_oe_n_p : in std_logic; - cpu_d_p : inout std_logic_vector(15 downto 0); - cpu_wait_n_p : out std_logic; - - arm7_debug : out std_logic; - arm7_debug2 : out std_logic; - - wb_o : out wishbone_bus_in; - wb_i : in wishbone_bus_out); -end arm7wb; - -architecture behave of arm7wb is - -type cpu_state_type is (cpu_idle, cpu_cs, cpu_end); - --- Input simulated delay -signal cpu_wr_n_p_del : std_logic_vector(1 downto 0); -signal cpu_a_p_del : std_logic_vector(23 downto 1); -signal cpu_d_p_del : std_logic_vector(15 downto 0); -signal cpu_cs_n_p_del : std_logic_vector(3 downto 1); -signal cpu_oe_n_p_del : std_logic; - --- Clock phase detect signals -signal cpu_clk_toggle : std_logic; -signal cpu_clk_smp1 : std_logic; -signal cpu_clk_smp2 : std_logic; -signal cpu_clk_phase : std_logic; - --- Internal version of control signal (for feedback) -signal arm7_din_int : std_logic_vector(15 downto 0); -signal arm7_dout_int : std_logic_vector(15 downto 0); -signal arm7_a_int : std_logic_vector(23 downto 1); -signal arm7_we_int : std_logic_vector(1 downto 0); -signal cyc_int : std_logic; -signal we_int : std_logic; -signal adr_reg : std_logic_vector(25 downto 24); - --- Input sampled -signal cpu_a_smp : std_logic_vector(23 downto 1); -signal cpu_d_smp : std_logic_vector(15 downto 0); -signal cpu_cs_n : std_logic_vector(3 downto 1); -signal cpu_oe_n : std_logic; -signal cpu_wr_n : std_logic_vector(1 downto 0); - --- Main FSM -signal cpu_state : cpu_state_type; - -constant Clock_2_Out : time := 5.5 ns; -constant Input_Setup : time := 2.5 ns; - -begin - - arm7_dout_int <= wb_i.dat(15 downto 0) when (arm7_a_int(1) = '0') else wb_i.dat(31 downto 16); - arm7_debug <= cpu_oe_n; - arm7_debug2 <= cpu_wr_n(0); - - -- Generate 64 MBytes address based on 3 CS_N signals from CPU - -- Memory map FPGA internal - -- 0x00000000 DDR 32 MBytes (CS_N2 and CS_N3) - -- 0x00200000 FPGA/Ethernet (CS_N1) - wb_o.adr(31 downto 26) <= "000000"; - wb_o.adr(25 downto 24) <= adr_reg; - wb_o.adr(23 downto 1) <= arm7_a_int(23 downto 1); - wb_o.adr(0) <= '0'; - - wb_o.dat <= (x"0000" & arm7_din_int) when (arm7_a_int(1) = '0') else (arm7_din_int & x"0000"); - wb_o.sel <= ("00" & arm7_we_int) when (arm7_a_int(1) = '0') else (arm7_we_int & "00"); - - wb_o.cyc <= cyc_int; - wb_o.stb <= cyc_int; - wb_o.we <= cpu_oe_n; - - iotimingon: - if simulate_io_time generate - begin - cpu_wr_n_p_del <= transport "XX" after 0 ns, cpu_wr_n_p after Input_Setup; - cpu_a_p_del <= transport "XXXXXXXXXXXXXXXXXXXXXXX" after 0 ns, cpu_a_p after Input_Setup; - cpu_d_p_del <= transport "XXXXXXXXXXXXXXXX" after 0 ns, cpu_d_p after Input_Setup; - cpu_cs_n_p_del <= transport "XXX" after 0 ns, cpu_cs_n_p after Input_Setup; - cpu_oe_n_p_del <= transport 'X' after 0 ns, cpu_oe_n_p after Input_Setup; - end generate; - - iotimingoff: - if not simulate_io_time generate - begin - cpu_wr_n_p_del <= cpu_wr_n_p; - cpu_a_p_del <= cpu_a_p; - cpu_d_p_del <= cpu_d_p; - cpu_cs_n_p_del <= cpu_cs_n_p; - cpu_oe_n_p_del <= cpu_oe_n_p; - end generate; - - process(cpu_clk, areset) -- Toggle FF with 1x clock to find phase - begin - if areset = '1' then - cpu_clk_toggle <= '0'; - elsif (cpu_clk'event and cpu_clk = '1') then - cpu_clk_toggle <= not(cpu_clk_toggle); - end if; - end process; - - process(cpu_clk_2x, areset) -- Find phase relationsship between 1x and 2x clock - begin - if areset = '1' then - cpu_clk_smp1 <= '0'; - cpu_clk_smp2 <= '1'; - cpu_clk_phase <= '0'; - elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then - cpu_clk_smp1 <= cpu_clk_toggle; - cpu_clk_smp2 <= cpu_clk_smp1; - if cpu_clk_smp1 = '1' and cpu_clk_smp2 = '0' then - cpu_clk_phase <= '0'; - else - cpu_clk_phase <= not(cpu_clk_phase); - end if; - end if; - end process; - - process(cpu_clk_2x, areset) -- Sample input signals on 2x clock - begin - if areset = '1' then - cpu_d_smp <= "0000000000000000"; - cpu_cs_n <= "111"; - elsif (cpu_clk_2x = '1' and cpu_clk_2x'event) then - cpu_d_smp <= cpu_d_p_del; - cpu_cs_n <= cpu_cs_n_p_del; - end if; - end process; - - process(cpu_clk, areset) -- Sample input signals on 1x clock - begin - if areset = '1' then - cpu_a_smp <= "00000000000000000000000"; - cpu_oe_n <= '1'; - cpu_wr_n <= "11"; - elsif (cpu_clk = '1' and cpu_clk'event) then - cpu_a_smp <= cpu_a_p_del; - cpu_oe_n <= cpu_oe_n_p_del; - cpu_wr_n <= cpu_wr_n_p_del; - end if; - end process; - - arm7_din_int <= cpu_d_smp; - arm7_a_int <= cpu_a_smp; - arm7_we_int <= not(cpu_wr_n); - - process(cpu_clk, areset) - begin - if areset = '1' then - cpu_state <= cpu_idle; - cyc_int <= '0'; - we_int <= '0'; - adr_reg <= "00"; - cpu_d_p <= (others => 'Z'); - elsif (cpu_clk'event and cpu_clk = '1') then - - cyc_int <= '0'; - we_int <= '0'; - cpu_d_p <= (others => 'Z') after Clock_2_Out; - - - case cpu_state is - - when cpu_idle => - if cpu_oe_n = '1' then - we_int <= '1'; - end if; - if cpu_cs_n(1) = '0' then - cyc_int <= '1'; - adr_reg <= "10"; - cpu_state <= cpu_cs; - end if; - if cpu_cs_n(2) = '0' then - cyc_int <= '1'; - adr_reg <= "00"; - cpu_state <= cpu_cs; - end if; - if cpu_cs_n(3) = '0' then - cyc_int <= '1'; - adr_reg <= "01"; - cpu_state <= cpu_cs; - end if; - - when cpu_cs => - if cpu_oe_n = '0' then - cpu_d_p <= arm7_dout_int after Clock_2_Out; - if wb_i.ack = '1' then - cpu_state <= cpu_end; - else - cyc_int <= '1'; - end if; - else - if wb_i.ack = '0' then - cyc_int <= '1'; - we_int <= '1'; - else - cpu_state <= cpu_end; - end if; - end if; - - when others => - cpu_state <= cpu_idle; - - end case; - end if; - end process; - - process(cpu_clk_2x, areset) - begin - if areset = '1' then - cpu_wait_n_p <= '1'; - elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then - cpu_wait_n_p <= '1' after Clock_2_Out; - if (cpu_state = cpu_cs and wb_i.ack = '0') then - cpu_wait_n_p <= '0' after Clock_2_Out; - end if; - end if; - end process; - -end behave; +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +library work; +use work.phi_config.all; +use work.wishbone_pkg.all; + +entity arm7wb is + generic( + simulate_io_time : boolean := false); + port ( areset : in std_logic; + cpu_clk : in std_logic; + cpu_clk_2x : in std_logic; + cpu_a_p : in std_logic_vector(23 downto 1); + cpu_wr_n_p : in std_logic_vector(1 downto 0); + cpu_cs_n_p : in std_logic_vector(3 downto 1); + cpu_oe_n_p : in std_logic; + cpu_d_p : inout std_logic_vector(15 downto 0); + cpu_wait_n_p : out std_logic; + + arm7_debug : out std_logic; + arm7_debug2 : out std_logic; + + wb_o : out wishbone_bus_in; + wb_i : in wishbone_bus_out); +end arm7wb; + +architecture behave of arm7wb is + +type cpu_state_type is (cpu_idle, cpu_cs, cpu_end); + +-- Input simulated delay +signal cpu_wr_n_p_del : std_logic_vector(1 downto 0); +signal cpu_a_p_del : std_logic_vector(23 downto 1); +signal cpu_d_p_del : std_logic_vector(15 downto 0); +signal cpu_cs_n_p_del : std_logic_vector(3 downto 1); +signal cpu_oe_n_p_del : std_logic; + +-- Clock phase detect signals +signal cpu_clk_toggle : std_logic; +signal cpu_clk_smp1 : std_logic; +signal cpu_clk_smp2 : std_logic; +signal cpu_clk_phase : std_logic; + +-- Internal version of control signal (for feedback) +signal arm7_din_int : std_logic_vector(15 downto 0); +signal arm7_dout_int : std_logic_vector(15 downto 0); +signal arm7_a_int : std_logic_vector(23 downto 1); +signal arm7_we_int : std_logic_vector(1 downto 0); +signal cyc_int : std_logic; +signal we_int : std_logic; +signal adr_reg : std_logic_vector(25 downto 24); + +-- Input sampled +signal cpu_a_smp : std_logic_vector(23 downto 1); +signal cpu_d_smp : std_logic_vector(15 downto 0); +signal cpu_cs_n : std_logic_vector(3 downto 1); +signal cpu_oe_n : std_logic; +signal cpu_wr_n : std_logic_vector(1 downto 0); + +-- Main FSM +signal cpu_state : cpu_state_type; + +constant Clock_2_Out : time := 5.5 ns; +constant Input_Setup : time := 2.5 ns; + +begin + + arm7_dout_int <= wb_i.dat(15 downto 0) when (arm7_a_int(1) = '0') else wb_i.dat(31 downto 16); + arm7_debug <= cpu_oe_n; + arm7_debug2 <= cpu_wr_n(0); + + -- Generate 64 MBytes address based on 3 CS_N signals from CPU + -- Memory map FPGA internal + -- 0x00000000 DDR 32 MBytes (CS_N2 and CS_N3) + -- 0x00200000 FPGA/Ethernet (CS_N1) + wb_o.adr(31 downto 26) <= "000000"; + wb_o.adr(25 downto 24) <= adr_reg; + wb_o.adr(23 downto 1) <= arm7_a_int(23 downto 1); + wb_o.adr(0) <= '0'; + + wb_o.dat <= (x"0000" & arm7_din_int) when (arm7_a_int(1) = '0') else (arm7_din_int & x"0000"); + wb_o.sel <= ("00" & arm7_we_int) when (arm7_a_int(1) = '0') else (arm7_we_int & "00"); + + wb_o.cyc <= cyc_int; + wb_o.stb <= cyc_int; + wb_o.we <= cpu_oe_n; + + iotimingon: + if simulate_io_time generate + begin + cpu_wr_n_p_del <= transport "XX" after 0 ns, cpu_wr_n_p after Input_Setup; + cpu_a_p_del <= transport "XXXXXXXXXXXXXXXXXXXXXXX" after 0 ns, cpu_a_p after Input_Setup; + cpu_d_p_del <= transport "XXXXXXXXXXXXXXXX" after 0 ns, cpu_d_p after Input_Setup; + cpu_cs_n_p_del <= transport "XXX" after 0 ns, cpu_cs_n_p after Input_Setup; + cpu_oe_n_p_del <= transport 'X' after 0 ns, cpu_oe_n_p after Input_Setup; + end generate; + + iotimingoff: + if not simulate_io_time generate + begin + cpu_wr_n_p_del <= cpu_wr_n_p; + cpu_a_p_del <= cpu_a_p; + cpu_d_p_del <= cpu_d_p; + cpu_cs_n_p_del <= cpu_cs_n_p; + cpu_oe_n_p_del <= cpu_oe_n_p; + end generate; + + process(cpu_clk, areset) -- Toggle FF with 1x clock to find phase + begin + if areset = '1' then + cpu_clk_toggle <= '0'; + elsif (cpu_clk'event and cpu_clk = '1') then + cpu_clk_toggle <= not(cpu_clk_toggle); + end if; + end process; + + process(cpu_clk_2x, areset) -- Find phase relationsship between 1x and 2x clock + begin + if areset = '1' then + cpu_clk_smp1 <= '0'; + cpu_clk_smp2 <= '1'; + cpu_clk_phase <= '0'; + elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then + cpu_clk_smp1 <= cpu_clk_toggle; + cpu_clk_smp2 <= cpu_clk_smp1; + if cpu_clk_smp1 = '1' and cpu_clk_smp2 = '0' then + cpu_clk_phase <= '0'; + else + cpu_clk_phase <= not(cpu_clk_phase); + end if; + end if; + end process; + + process(cpu_clk_2x, areset) -- Sample input signals on 2x clock + begin + if areset = '1' then + cpu_d_smp <= "0000000000000000"; + cpu_cs_n <= "111"; + elsif (cpu_clk_2x = '1' and cpu_clk_2x'event) then + cpu_d_smp <= cpu_d_p_del; + cpu_cs_n <= cpu_cs_n_p_del; + end if; + end process; + + process(cpu_clk, areset) -- Sample input signals on 1x clock + begin + if areset = '1' then + cpu_a_smp <= "00000000000000000000000"; + cpu_oe_n <= '1'; + cpu_wr_n <= "11"; + elsif (cpu_clk = '1' and cpu_clk'event) then + cpu_a_smp <= cpu_a_p_del; + cpu_oe_n <= cpu_oe_n_p_del; + cpu_wr_n <= cpu_wr_n_p_del; + end if; + end process; + + arm7_din_int <= cpu_d_smp; + arm7_a_int <= cpu_a_smp; + arm7_we_int <= not(cpu_wr_n); + + process(cpu_clk, areset) + begin + if areset = '1' then + cpu_state <= cpu_idle; + cyc_int <= '0'; + we_int <= '0'; + adr_reg <= "00"; + cpu_d_p <= (others => 'Z'); + elsif (cpu_clk'event and cpu_clk = '1') then + + cyc_int <= '0'; + we_int <= '0'; + cpu_d_p <= (others => 'Z') after Clock_2_Out; + + + case cpu_state is + + when cpu_idle => + if cpu_oe_n = '1' then + we_int <= '1'; + end if; + if cpu_cs_n(1) = '0' then + cyc_int <= '1'; + adr_reg <= "10"; + cpu_state <= cpu_cs; + end if; + if cpu_cs_n(2) = '0' then + cyc_int <= '1'; + adr_reg <= "00"; + cpu_state <= cpu_cs; + end if; + if cpu_cs_n(3) = '0' then + cyc_int <= '1'; + adr_reg <= "01"; + cpu_state <= cpu_cs; + end if; + + when cpu_cs => + if cpu_oe_n = '0' then + cpu_d_p <= arm7_dout_int after Clock_2_Out; + if wb_i.ack = '1' then + cpu_state <= cpu_end; + else + cyc_int <= '1'; + end if; + else + if wb_i.ack = '0' then + cyc_int <= '1'; + we_int <= '1'; + else + cpu_state <= cpu_end; + end if; + end if; + + when others => + cpu_state <= cpu_idle; + + end case; + end if; + end process; + + process(cpu_clk_2x, areset) + begin + if areset = '1' then + cpu_wait_n_p <= '1'; + elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then + cpu_wait_n_p <= '1' after Clock_2_Out; + if (cpu_state = cpu_cs and wb_i.ack = '0') then + cpu_wait_n_p <= '0' after Clock_2_Out; + end if; + end if; + end process; + +end behave; diff --git a/misc/ddrsdram/simsrc/ddr_tb.vhd b/misc/ddrsdram/simsrc/ddr_tb.vhd index 249dffb..92d1e4b 100644 --- a/misc/ddrsdram/simsrc/ddr_tb.vhd +++ b/misc/ddrsdram/simsrc/ddr_tb.vhd @@ -1,301 +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; +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 index 0e41a88..af4a705 100644 --- a/misc/ddrsdram/src/ddr_pkg.vhd +++ b/misc/ddrsdram/src/ddr_pkg.vhd @@ -1,107 +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; - +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 index 033e9f8..2aceae9 100644 --- a/misc/ddrsdram/src/ddr_top.vhd +++ b/misc/ddrsdram/src/ddr_top.vhd @@ -1,743 +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; - - +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 index 6b89345..356bb28 100644 --- a/misc/ddrsdram/src/mt46v16m16.vhd +++ b/misc/ddrsdram/src/mt46v16m16.vhd @@ -1,1320 +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; +----------------------------------------------------------------------------------------- +-- +-- 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; diff --git a/misc/wishbone/src/atomic32_access.vhd b/misc/wishbone/src/atomic32_access.vhd index b062f98..9bc9825 100644 --- a/misc/wishbone/src/atomic32_access.vhd +++ b/misc/wishbone/src/atomic32_access.vhd @@ -1,132 +1,132 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use IEEE.STD_LOGIC_UNSIGNED.ALL; - -library work; ---use work.phi_config.all; -use work.wishbone_pkg.all; - -entity atomic32_access is - port ( cpu_clk : in std_logic; - areset : in std_logic; - - -- Wishbone from CPU interface - wb_16_i : in wishbone_bus_in; - wb_16_o : out wishbone_bus_out; - - -- Wishbone to FPGA registers and ethernet core - wb_32_i : in wishbone_bus_out; - wb_32_o : out wishbone_bus_in); -end atomic32_access; - -architecture behave of atomic32_access is - -type eth_state_wr_type is (idle, lsb_msb, lsb, msb, write, ack, wait_st); -signal eth_state_wr : eth_state_wr_type; -type eth_state_rd_type is (idle, lsb_msb, lsb_read, lsb, wait_st2, msb); -signal eth_state_rd : eth_state_rd_type; -signal core_data : std_logic_vector(31 downto 0); -signal core_addr : std_logic_vector(31 downto 0); - -begin - process(cpu_clk, areset) - begin - if areset = '1' then - eth_state_wr <= idle; - eth_state_rd <= idle; - wb_32_o.stb <= '0'; - wb_32_o.cyc <= '0'; - wb_16_o.ack <= '0'; - core_data <= (others => '0'); - core_addr <= (others => '0'); - elsif (rising_edge(cpu_clk)) then - - case eth_state_wr is --write cycle - when idle => - if wb_16_i.cyc = '1' and wb_16_i.we = '1' then - eth_state_wr <= lsb_msb; - end if; - when lsb_msb => - if wb_16_i.adr(1) = '0' then - eth_state_wr <= lsb; - end if; - if wb_16_i.adr(1) = '1' then - eth_state_wr <= msb; - end if; - when lsb => - core_data(15 downto 0) <= wb_16_i.dat(15 downto 0); - wb_16_o.ack <= '1'; - eth_state_wr <= wait_st; - when msb => - core_data(31 downto 16) <= wb_16_i.dat(31 downto 16); - core_addr <= wb_16_i.adr(31 downto 2) & "00"; - eth_state_wr <= write; - when write => - wb_32_o.dat <= core_data; - wb_32_o.adr <= core_addr; - wb_32_o.sel <= "1111"; - wb_32_o.we <= '1'; - wb_32_o.stb <= '1'; - wb_32_o.cyc <= '1'; - eth_state_wr <= ack; - when ack => - if wb_32_i.ack = '1' then - wb_16_o.ack <= '1'; - eth_state_wr <= wait_st; - wb_32_o.stb <= '0'; - wb_32_o.cyc <= '0'; - wb_32_o.sel <= "0000"; - wb_32_o.we <= '0'; - end if; - when wait_st => - wb_16_o.ack <= '0'; - eth_state_wr <= idle; - when others => - eth_state_wr <= idle; - end case; - - case eth_state_rd is --read cycle - when idle => - if wb_16_i.cyc = '1' and wb_16_i.we = '0' then - core_addr <= wb_16_i.adr(31 downto 2) & "00"; - eth_state_rd <= lsb_msb; - end if; - when lsb_msb => - if wb_16_i.adr(1) = '0' then - wb_32_o.adr <= core_addr; - eth_state_rd <= lsb_read; - end if; - if wb_16_i.adr(1) = '1' then - wb_32_o.adr <= core_addr; - eth_state_rd <= msb; - end if; - when lsb_read => - wb_32_o.sel <= "1111"; - wb_32_o.we <= '0'; - wb_32_o.stb <= '1'; - wb_32_o.cyc <= '1'; - eth_state_rd <= lsb; - when lsb => - if wb_32_i.ack = '1' then - wb_32_o.sel <= "0000"; - wb_32_o.stb <= '0'; - wb_32_o.cyc <= '0'; - core_data <= wb_32_i.dat; - wb_16_o.dat <= x"0000" & wb_32_i.dat(15 downto 0); - wb_16_o.ack <= '1'; - eth_state_rd <= wait_st2; - end if; - when wait_st2 => - wb_16_o.ack <= '0'; - eth_state_rd <= idle; - when msb => - wb_16_o.ack <= '1'; - wb_16_o.dat <= core_data(31 downto 16) & x"0000"; - eth_state_rd <= wait_st2; - when others => - eth_state_rd <= idle; - end case; - end if; - end process; - +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +library work; +--use work.phi_config.all; +use work.wishbone_pkg.all; + +entity atomic32_access is + port ( cpu_clk : in std_logic; + areset : in std_logic; + + -- Wishbone from CPU interface + wb_16_i : in wishbone_bus_in; + wb_16_o : out wishbone_bus_out; + + -- Wishbone to FPGA registers and ethernet core + wb_32_i : in wishbone_bus_out; + wb_32_o : out wishbone_bus_in); +end atomic32_access; + +architecture behave of atomic32_access is + +type eth_state_wr_type is (idle, lsb_msb, lsb, msb, write, ack, wait_st); +signal eth_state_wr : eth_state_wr_type; +type eth_state_rd_type is (idle, lsb_msb, lsb_read, lsb, wait_st2, msb); +signal eth_state_rd : eth_state_rd_type; +signal core_data : std_logic_vector(31 downto 0); +signal core_addr : std_logic_vector(31 downto 0); + +begin + process(cpu_clk, areset) + begin + if areset = '1' then + eth_state_wr <= idle; + eth_state_rd <= idle; + wb_32_o.stb <= '0'; + wb_32_o.cyc <= '0'; + wb_16_o.ack <= '0'; + core_data <= (others => '0'); + core_addr <= (others => '0'); + elsif (rising_edge(cpu_clk)) then + + case eth_state_wr is --write cycle + when idle => + if wb_16_i.cyc = '1' and wb_16_i.we = '1' then + eth_state_wr <= lsb_msb; + end if; + when lsb_msb => + if wb_16_i.adr(1) = '0' then + eth_state_wr <= lsb; + end if; + if wb_16_i.adr(1) = '1' then + eth_state_wr <= msb; + end if; + when lsb => + core_data(15 downto 0) <= wb_16_i.dat(15 downto 0); + wb_16_o.ack <= '1'; + eth_state_wr <= wait_st; + when msb => + core_data(31 downto 16) <= wb_16_i.dat(31 downto 16); + core_addr <= wb_16_i.adr(31 downto 2) & "00"; + eth_state_wr <= write; + when write => + wb_32_o.dat <= core_data; + wb_32_o.adr <= core_addr; + wb_32_o.sel <= "1111"; + wb_32_o.we <= '1'; + wb_32_o.stb <= '1'; + wb_32_o.cyc <= '1'; + eth_state_wr <= ack; + when ack => + if wb_32_i.ack = '1' then + wb_16_o.ack <= '1'; + eth_state_wr <= wait_st; + wb_32_o.stb <= '0'; + wb_32_o.cyc <= '0'; + wb_32_o.sel <= "0000"; + wb_32_o.we <= '0'; + end if; + when wait_st => + wb_16_o.ack <= '0'; + eth_state_wr <= idle; + when others => + eth_state_wr <= idle; + end case; + + case eth_state_rd is --read cycle + when idle => + if wb_16_i.cyc = '1' and wb_16_i.we = '0' then + core_addr <= wb_16_i.adr(31 downto 2) & "00"; + eth_state_rd <= lsb_msb; + end if; + when lsb_msb => + if wb_16_i.adr(1) = '0' then + wb_32_o.adr <= core_addr; + eth_state_rd <= lsb_read; + end if; + if wb_16_i.adr(1) = '1' then + wb_32_o.adr <= core_addr; + eth_state_rd <= msb; + end if; + when lsb_read => + wb_32_o.sel <= "1111"; + wb_32_o.we <= '0'; + wb_32_o.stb <= '1'; + wb_32_o.cyc <= '1'; + eth_state_rd <= lsb; + when lsb => + if wb_32_i.ack = '1' then + wb_32_o.sel <= "0000"; + wb_32_o.stb <= '0'; + wb_32_o.cyc <= '0'; + core_data <= wb_32_i.dat; + wb_16_o.dat <= x"0000" & wb_32_i.dat(15 downto 0); + wb_16_o.ack <= '1'; + eth_state_rd <= wait_st2; + end if; + when wait_st2 => + wb_16_o.ack <= '0'; + eth_state_rd <= idle; + when msb => + wb_16_o.ack <= '1'; + wb_16_o.dat <= core_data(31 downto 16) & x"0000"; + eth_state_rd <= wait_st2; + when others => + eth_state_rd <= idle; + end case; + end if; + end process; + end behave; \ No newline at end of file diff --git a/misc/wishbone/src/wishbone_pkg.vhd b/misc/wishbone/src/wishbone_pkg.vhd index c3b0d9b..359a33f 100644 --- a/misc/wishbone/src/wishbone_pkg.vhd +++ b/misc/wishbone/src/wishbone_pkg.vhd @@ -1,52 +1,52 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.all; -use IEEE.STD_LOGIC_UNSIGNED.ALL; - -package wishbone_pkg is - - type wishbone_bus_in is record - adr : std_logic_vector(31 downto 0); - sel : std_logic_vector(3 downto 0); - we : std_logic; - dat : std_logic_vector(31 downto 0); -- Note! Data written with 'we' - cyc : std_logic; - stb : std_logic; - end record; - - type wishbone_bus_out is record - dat : std_logic_vector(31 downto 0); - ack : std_logic; - end record; - - type wishbone_bus is record - insig : wishbone_bus_in; - outsig : wishbone_bus_out; - end record; - - component atomic32_access is - port ( cpu_clk : in std_logic; - areset : in std_logic; - - -- Wishbone from CPU interface - wb_16_i : in wishbone_bus_in; - wb_16_o : out wishbone_bus_out; - -- Wishbone to FPGA registers and ethernet core - wb_32_i : in wishbone_bus_out; - wb_32_o : out wishbone_bus_in); - end component; - - component eth_access_corr is - port ( cpu_clk : in std_logic; - areset : in std_logic; - - -- Wishbone from Wishbone MUX - eth_raw_o : out wishbone_bus_out; - eth_raw_i : in wishbone_bus_in; - - -- Wishbone ethernet core - eth_slave_i : in wishbone_bus_out; - eth_slave_o : out wishbone_bus_in); - end component; - - -end wishbone_pkg; +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +package wishbone_pkg is + + type wishbone_bus_in is record + adr : std_logic_vector(31 downto 0); + sel : std_logic_vector(3 downto 0); + we : std_logic; + dat : std_logic_vector(31 downto 0); -- Note! Data written with 'we' + cyc : std_logic; + stb : std_logic; + end record; + + type wishbone_bus_out is record + dat : std_logic_vector(31 downto 0); + ack : std_logic; + end record; + + type wishbone_bus is record + insig : wishbone_bus_in; + outsig : wishbone_bus_out; + end record; + + component atomic32_access is + port ( cpu_clk : in std_logic; + areset : in std_logic; + + -- Wishbone from CPU interface + wb_16_i : in wishbone_bus_in; + wb_16_o : out wishbone_bus_out; + -- Wishbone to FPGA registers and ethernet core + wb_32_i : in wishbone_bus_out; + wb_32_o : out wishbone_bus_in); + end component; + + component eth_access_corr is + port ( cpu_clk : in std_logic; + areset : in std_logic; + + -- Wishbone from Wishbone MUX + eth_raw_o : out wishbone_bus_out; + eth_raw_i : in wishbone_bus_in; + + -- Wishbone ethernet core + eth_slave_i : in wishbone_bus_out; + eth_slave_o : out wishbone_bus_in); + end component; + + +end wishbone_pkg; -- cgit v1.1