diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 9577a0ca48378e3eede404c1f93486941a0fa9e2..0a2afbc86ec912364931c6450d836d1ce316dfb3 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -57,8 +57,13 @@ ENTITY ddrctrl IS PORT ( clk : IN STD_LOGIC := '0'; rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC := '0'; + mm_rst : IN STD_LOGIC := '0'; in_sosi_arr : IN t_dp_sosi_arr; -- input data + wr_not_rd : IN STD_LOGIC := '0'; out_of : OUT NATURAL; -- amount of internal overflow this output + out_adr : OUT NATURAL; + term_ctrl_out : OUT t_tech_ddr3_phy_terminationcontrol; term_ctrl_in : IN t_tech_ddr3_phy_terminationcontrol := c_tech_ddr3_phy_terminationcontrol_rst; @@ -83,12 +88,11 @@ ARCHITECTURE str OF ddrctrl IS CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- signals for connecting the components - SIGNAL data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); SIGNAL sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL adr : NATURAL := 0; SIGNAL a_of : NATURAL := 0; - SIGNAL ctrl_clk : STD_LOGIC := '0'; - SIGNAL ctrl_rst : STD_LOGIC := '0'; + SIGNAL ctrl_clk : STD_LOGIC; + SIGNAL ctrl_rst : STD_LOGIC; SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL wr_siso : t_dp_siso; SIGNAL rd_siso : t_dp_siso; @@ -96,51 +100,25 @@ ARCHITECTURE str OF ddrctrl IS BEGIN - dvr_mosi.address <= TO_UVEC(adr, dvr_mosi.address'length); - - -- makes one data vector out of all the data from the t_dp_sosi_arr - u_pack : ENTITY work.ddrctrl_pack - GENERIC MAP( - - g_nof_streams => g_nof_streams, -- number of input streams - g_data_w => g_data_w -- data with of input data vectors - - ) - PORT MAP( - - in_sosi_arr => in_sosi_arr, -- input data - out_data => data -- output data - - ); - - -- resizes the input data vector so that the output data vector can be stored into the ddr memory - u_repack : ENTITY work.ddrctrl_repack + dvr_mosi.address <= TO_UVEC(adr, dvr_mosi.address'length); + dvr_mosi.burstbegin <= wr_sosi.valid; + dvr_mosi.wr <= wr_not_rd; + dvr_mosi.rd <= NOT wr_not_rd; + -- input to io_ddr + u_ddrctrl_input : ENTITY work.ddrctrl_input GENERIC MAP( - g_tech_ddr => g_tech_ddr, -- type of memory - g_in_data_w => c_out_data_w -- the input data with - ) - PORT MAP( - clk => clk, - rst => rst, - in_data => data, -- input data - out_of => a_of, -- amount of internal overflow - out_sosi => sosi -- output data - ); - - -- creates address by counting input valids - u_address_counter : ENTITY work.ddrctrl_address_counter - GENERIC MAP( - g_tech_ddr => g_tech_ddr, -- type of memory - g_sim_model => g_sim_model -- determens if this is a simulation + g_tech_ddr => g_tech_ddr, + g_sim_model => g_sim_model, + g_nof_streams => g_nof_streams, + g_data_w => g_data_w ) PORT MAP( - clk => clk, - rst => rst, - in_sosi => sosi, -- input data - in_of => a_of, - out_sosi => wr_sosi, -- output data - out_of => out_of, - out_adr => adr + clk => clk, + rst => rst, + in_sosi_arr => in_sosi_arr, + out_of => out_of, + out_sosi => wr_sosi, + out_adr => out_adr ); -- functions as a fifo buffer for input data into the sdram stick. also manages input to sdram stick. @@ -173,8 +151,8 @@ BEGIN ctlr_rst_in => ctrl_rst, -- MM clock + reset - mm_rst => rst, - mm_clk => clk, + mm_rst => mm_rst, + mm_clk => mm_clk, -- MM interface reg_io_ddr_mosi => open, diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd new file mode 100644 index 0000000000000000000000000000000000000000..3f46046f2ea2459685d898534382d876d5458843 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd @@ -0,0 +1,121 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2022 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- +-- Author: Job van Wee +-- Purpose: Folding a stream of data into a mm data configuration so it can be +-- stored in a DDR RAM-stick. +-- +-- Description: +-- First the data from the sosi array gets collected into one data vector. +-- After that this data vector gets resized to the right size data vector in +-- order to make it storable in a DDR RAM-stick. +-- After that a address gets assigned to the data so the data can be found back. +-- +-- Remark: +-- Use VHDL coding template from: +-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding +-- The maximum value of the address is determend by g_tech_ddr. + +LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE technology_lib.technology_pkg.ALL; +USE tech_ddr_lib.tech_ddr_pkg.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + + +ENTITY ddrctrl_input IS + GENERIC ( + g_tech_ddr : t_c_tech_ddr; -- type of memory + g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + g_nof_streams : NATURAL := 12; -- number of input streams + g_data_w : NATURAL := 14 -- data with of input data vectors + ); + PORT ( + clk : IN STD_LOGIC := '0'; + rst : IN STD_LOGIC; + in_sosi_arr : IN t_dp_sosi_arr; -- input data + out_of : OUT NATURAL; -- amount of internal overflow this output + out_sosi : OUT t_dp_sosi; -- output data + out_adr : OUT NATURAL + ); +END ddrctrl_input; + + +ARCHITECTURE str OF ddrctrl_input IS + + -- constant for readability + CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- the input data with for ddrctrl_repack + + + -- signals for connecting the components + SIGNAL data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); + SIGNAL sosi : t_dp_sosi := c_dp_sosi_init; + SIGNAL a_of : NATURAL := 0; + +BEGIN + + -- makes one data vector out of all the data from the t_dp_sosi_arr + u_pack : ENTITY work.ddrctrl_pack + GENERIC MAP( + + g_nof_streams => g_nof_streams, -- number of input streams + g_data_w => g_data_w -- data with of input data vectors + + ) + PORT MAP( + + in_sosi_arr => in_sosi_arr, -- input data + out_data => data -- output data + + ); + + -- resizes the input data vector so that the output data vector can be stored into the ddr memory + u_repack : ENTITY work.ddrctrl_repack + GENERIC MAP( + g_tech_ddr => g_tech_ddr, -- type of memory + g_in_data_w => c_out_data_w -- the input data with + ) + PORT MAP( + clk => clk, + rst => rst, + in_data => data, -- input data + out_of => a_of, -- amount of internal overflow + out_sosi => sosi -- output data + ); + + -- creates address by counting input valids + u_address_counter : ENTITY work.ddrctrl_address_counter + GENERIC MAP( + g_tech_ddr => g_tech_ddr, -- type of memory + g_sim_model => g_sim_model -- determens if this is a simulation + ) + PORT MAP( + clk => clk, + rst => rst, + in_sosi => sosi, -- input data + in_of => a_of, + out_sosi => out_sosi, -- output data + out_of => out_of, + out_adr => out_adr + ); + +END str; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd index ff2f25739c6e171f8d4739cbab2604826d7f58a9..9bd01e39ea8cbf727db27d456a615d9ae2feffa3 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -31,6 +31,7 @@ USE tech_ddr_lib.tech_ddr_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; ENTITY tb_ddrctrl IS GENERIC ( @@ -39,10 +40,10 @@ ENTITY tb_ddrctrl IS g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation g_nof_streams : POSITIVE := 12; -- number of input streams g_data_w : NATURAL := 14; -- data with of input data vectors - g_sim_length : NATURAL := 52 + g_sim_length : NATURAL := 1052; g_technology : NATURAL := c_tech_select_default; - g_wr_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 and independent of wr burst size, default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K - g_rd_fifo_depth : NATURAL := 256 -- defined at DDR side of the FIFO, >=16 AND > max number of rd burst sizes (so > c_rd_fifo_af_margin), default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K + g_tech_ddr3 : t_c_tech_ddr := c_tech_ddr3_4g_800m_master; + g_tech_ddr4 : t_c_tech_ddr := c_tech_ddr4_4g_1600m ); END tb_ddrctrl; @@ -51,7 +52,17 @@ ARCHITECTURE tb OF tb_ddrctrl IS -- constants for testbench CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns + CONSTANT c_mm_clk_freq : NATURAL := 100; + CONSTANT c_mm_clk_period : TIME := (10**6 / c_mm_clk_freq) * 1 ps; + -- Select DDR3 or DDR4 dependent on the technology and sim model + CONSTANT c_mem_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_technology, g_tech_ddr3, g_tech_ddr4); + CONSTANT c_sim_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_technology, c_tech_ddr3_sim_16k, c_tech_ddr4_sim_16k); + CONSTANT c_tech_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_sim_model, c_sim_ddr, c_mem_ddr); + + CONSTANT c_wr_fifo_depth : NATURAL := 16; -- defined at DDR side of the FIFO + CONSTANT c_rd_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO + -- constants for readability CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576 @@ -75,13 +86,16 @@ ARCHITECTURE tb OF tb_ddrctrl IS -- input signals for ddrctrl.vhd SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC := '0'; + SIGNAL mm_clk : STD_LOGIC := '0'; + SIGNAL mm_rst : STD_LOGIC := '0'; SIGNAL q_rst : STD_LOGIC := '0'; SIGNAL q_q_rst : STD_LOGIC := '0'; SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input data signal for ddrctrl_pack.vhd + SIGNAL wr_not_rd : STD_LOGIC; -- output singals from ddrctrl.vhd SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is - SIGNAL out_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- output signal from ddrctrl_pack.vhd + SIGNAL out_adr : NATURAL := 0; -- testbench signal SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off @@ -96,10 +110,17 @@ ARCHITECTURE tb OF tb_ddrctrl IS SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest SIGNAL q_lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest with a delay of 1 clockcycle + -- PHY + SIGNAL phy3_io : t_tech_ddr3_phy_io; + SIGNAL phy3_ou : t_tech_ddr3_phy_ou; + SIGNAL phy4_io : t_tech_ddr4_phy_io; + SIGNAL phy4_ou : t_tech_ddr4_phy_ou; + BEGIN -- generating clock clk <= NOT clk OR tb_end AFTER c_clk_period/2; + mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2; -- excecuting test p_test : PROCESS @@ -110,9 +131,12 @@ BEGIN WAIT UNTIL rising_edge(clk); -- align to rising edge WAIT FOR c_clk_period*4; rst <= '1'; + mm_rst <= '1'; WAIT FOR c_clk_period*1; rst <= '0'; + mm_rst <= '0'; test_running <= '1'; + wr_not_rd <= '1'; -- filling the input data vectors with the corresponding numbers make_data : FOR J IN 0 TO g_sim_length-1 LOOP @@ -123,14 +147,15 @@ BEGIN WAIT FOR c_clk_period*1; END LOOP; test_running <= '0'; + wr_not_rd <= '0'; -- testing reset - FOR I IN 0 TO g_sim_length-1 LOOP - rst <= '1'; - WAIT FOR c_clk_period*1; - rst <= '0'; - WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4); - END LOOP; +-- FOR I IN 0 TO g_sim_length-1 LOOP +-- rst <= '1'; +-- WAIT FOR c_clk_period*1; +-- rst <= '0'; +-- WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4); +-- END LOOP; -- stopping the testbench @@ -139,75 +164,49 @@ BEGIN ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; - -- generating compare data for out_mosi - p_out_mosi : PROCESS - BEGIN - WAIT UNTIL rising_edge(clk); - if rising_edge(clk) THEN - q_q_rst <= q_rst; - q_lag_due_reset <= lag_due_reset; - q_rst <= rst; - END IF; - IF q_rst = '1' THEN - IF lag_due_reset + TO_UINT(out_mosi.address) >= c_adr_size THEN - lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address)-c_adr_size; - ELSE - lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address); - END IF; - END IF; - END PROCESS; - - -- verifying if the address is correct by keeping track of the address - p_verify_address : PROCESS - BEGIN - FOR I IN 0 TO c_adr_size-1 LOOP - IF I >= q_lag_due_reset THEN - ASSERT I-q_lag_due_reset = TO_UINT(out_mosi.address) REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR; - ELSE - ASSERT (I-q_lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address) REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR; - END IF; - WAIT UNTIL out_mosi.wr = '1'; - IF q_q_rst = '1' THEN - WAIT UNTIL out_mosi.wr = '1'; - END IF; - END LOOP; - END PROCESS; - - -- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected - p_verify : PROCESS - VARIABLE ctr_of : NATURAL := 0; - VARIABLE out_data_cnt : NATURAL := 0; - - BEGIN - WAIT UNTIL rising_edge(clk); - IF q_q_test_running = '1' AND out_mosi.wr = '1' THEN - out_data_cnt := out_data_cnt+1; - IF out_data_cnt mod 2 = 0 THEN - ctr_of := c_in_data_w*(q_q_in_data_cnt)-c_out_data_w*out_data_cnt; - ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) & ", out_of = " & NATURAL'image(out_of) SEVERITY ERROR; - END IF; - ASSERT out_mosi.wrdata(c_out_data_w-1 DOWNTO 0) = c_total_vector(c_out_data_w*out_data_cnt-1 DOWNTO c_out_data_w*(out_data_cnt-1)) REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt) SEVERITY ERROR; - END IF; - END PROCESS; -- DUT u_ddrctrl : ENTITY work.ddrctrl GENERIC MAP ( - g_tech_ddr => g_tech_ddr, + g_tech_ddr => c_tech_ddr, g_sim_model => g_sim_model, g_technology => g_technology, g_nof_streams => g_nof_streams, g_data_w => g_data_w, - g_wr_fifo_depth => g_wr_fifo_depth, - g_rd_fifo_depth => g_rd_fifo_depth + g_wr_fifo_depth => c_wr_fifo_depth, + g_rd_fifo_depth => c_rd_fifo_depth ) PORT MAP ( clk => clk, rst => rst, + mm_clk => mm_clk, + mm_rst => mm_rst, in_sosi_arr => in_sosi_arr, + wr_not_rd => wr_not_rd, out_of => out_of, + out_adr => out_adr, + + --PHY + phy3_io => phy3_io, + phy3_ou => phy3_ou, + phy4_io => phy4_io, + phy4_ou => phy4_ou + ); + + u_tech_ddr_memory_model : ENTITY tech_ddr_lib.tech_ddr_memory_model + GENERIC MAP ( + g_tech_ddr => c_tech_ddr + ) + PORT MAP ( + -- DDR3 PHY interface + mem3_in => phy3_ou, + mem3_io => phy3_io, + + -- DDR4 PHY interface + mem4_in => phy4_ou, + mem4_io => phy4_io ); END tb; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd new file mode 100644 index 0000000000000000000000000000000000000000..5d6da7aa7c2eb069fa8d4c62e66ba1dfa195f722 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd @@ -0,0 +1,211 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2022 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- +-- Author: Job van Wee +-- Purpose: Self checking and self-stopping tb for ddrctrl_input.vhd +-- Usage: +-- > run -a + +LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE IEEE.MATH_REAL.ALL; +USE technology_lib.technology_pkg.ALL; +USE tech_ddr_lib.tech_ddr_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY tb_ddrctrl_input IS + GENERIC ( + + g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory + g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + g_nof_streams : POSITIVE := 12; -- number of input streams + g_data_w : NATURAL := 14; -- data with of input data vectors + g_sim_length : NATURAL := 52 + + ); +END tb_ddrctrl_input; + +ARCHITECTURE tb OF tb_ddrctrl_input IS + + -- constants for testbench + CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz + CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns + + -- constants for readability + CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 + CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576 + CONSTANT c_adr_w : NATURAL := 4; -- address with in simulation + CONSTANT c_adr_size : NATURAL := 2**c_adr_w; -- address size in simulation + + -- function for making total data vector + FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS + VARIABLE temp : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0); + BEGIN + FOR I IN 0 TO g_sim_length*g_nof_streams-1 LOOP + temp(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w); + END LOOP; + RETURN temp; + END FUNCTION c_total_vector_init; + + -- constant for running the test + CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector + + + -- input signals for ddrctrl_input.vhd + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '0'; + SIGNAL q_rst : STD_LOGIC := '0'; + SIGNAL q_q_rst : STD_LOGIC := '0'; + SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input data signal for ddrctrl_pack.vhd + + -- output singals from ddrctrl_input.vhd + SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is + SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- output signal from ddrctrl_pack.vhd + SIGNAL out_adr : NATURAL := 0; + + -- testbench signal + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + + -- signals for running test + SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd + SIGNAL q_in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 1 clockcycle + SIGNAL q_q_in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 2 clockcycles + SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started + SIGNAL q_test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started with a delay of 1 clockcycle + SIGNAL q_q_test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started with a delay of 2 clockcycles + SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest + SIGNAL q_lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest with a delay of 1 clockcycle + +BEGIN + + -- generating clock + clk <= NOT clk OR tb_end AFTER c_clk_period/2; + + -- excecuting test + p_test : PROCESS + BEGIN + + -- start the test + tb_end <= '0'; + WAIT UNTIL rising_edge(clk); -- align to rising edge + WAIT FOR c_clk_period*4; + rst <= '1'; + WAIT FOR c_clk_period*1; + rst <= '0'; + test_running <= '1'; + + -- filling the input data vectors with the corresponding numbers + make_data : FOR J IN 0 TO g_sim_length-1 LOOP + in_data_cnt <= in_data_cnt+1; + fill_in_sosi_arr_rest : FOR I IN 0 TO g_nof_streams-1 LOOP + in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w); + END LOOP; + WAIT FOR c_clk_period*1; + END LOOP; + test_running <= '0'; + + -- testing reset + FOR I IN 0 TO g_sim_length-1 LOOP + rst <= '1'; + WAIT FOR c_clk_period*1; + rst <= '0'; + WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4); + END LOOP; + + + -- stopping the testbench + WAIT FOR c_clk_period*4; + tb_end <= '1'; + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; + END PROCESS; + + -- generating compare data for out_sosi + p_out_sosi : PROCESS + BEGIN + WAIT UNTIL rising_edge(clk); + if rising_edge(clk) THEN + q_q_rst <= q_rst; + q_lag_due_reset <= lag_due_reset; + q_rst <= rst; + END IF; + IF q_rst = '1' THEN + IF lag_due_reset + out_adr >= c_adr_size THEN + lag_due_reset <= lag_due_reset+out_adr-c_adr_size; + ELSE + lag_due_reset <= lag_due_reset+out_adr; + END IF; + END IF; + END PROCESS; + + -- verifying if the address is correct by keeping track of the address + p_verify_address : PROCESS + BEGIN + FOR I IN 0 TO c_adr_size-1 LOOP + IF I >= q_lag_due_reset THEN + ASSERT I-q_lag_due_reset = out_adr REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; + ELSE + ASSERT (I-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; + END IF; + WAIT UNTIL out_sosi.valid = '1'; + IF q_q_rst = '1' THEN + WAIT UNTIL out_sosi.valid = '1'; + END IF; + END LOOP; + END PROCESS; + + -- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected + p_verify : PROCESS + + VARIABLE ctr_of : NATURAL := 0; + VARIABLE out_data_cnt : NATURAL := 0; + + BEGIN + WAIT UNTIL rising_edge(clk); + IF q_q_test_running = '1' AND out_sosi.valid = '1' THEN + out_data_cnt := out_data_cnt+1; + IF out_data_cnt mod 2 = 0 THEN + ctr_of := c_in_data_w*(q_q_in_data_cnt)-c_out_data_w*out_data_cnt; + ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) & ", out_of = " & NATURAL'image(out_of) SEVERITY ERROR; + END IF; + ASSERT out_sosi.data(c_out_data_w-1 DOWNTO 0) = c_total_vector(c_out_data_w*out_data_cnt-1 DOWNTO c_out_data_w*(out_data_cnt-1)) REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt) SEVERITY ERROR; + END IF; + END PROCESS; + + + -- DUT + u_ddrctrl_input : ENTITY work.ddrctrl_input + GENERIC MAP ( + g_tech_ddr => g_tech_ddr, + g_sim_model => g_sim_model, + g_nof_streams => g_nof_streams, + g_data_w => g_data_w + ) + PORT MAP ( + clk => clk, + rst => rst, + in_sosi_arr => in_sosi_arr, + out_of => out_of, + out_sosi => out_sosi, + out_adr => out_adr + ); + +END tb;