diff --git a/applications/lofar2/libraries/ddrctrl/hdllib.cfg b/applications/lofar2/libraries/ddrctrl/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..8f92d2ddd3f4d347fdfc32811cdbcefd07fe0288 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/hdllib.cfg @@ -0,0 +1,25 @@ +hdl_lib_name = lofar2_ddrctrl +hdl_library_clause_name = lofar2_ddrctrl_lib +hdl_lib_uses_synth = technology common tech_ddr dp +hdl_lib_uses_sim = +hdl_lib_technology = + +synth_files = + src/vhdl/ddrctrl_address_counter.vhd + src/vhdl/ddrctrl_pack.vhd + src/vhdl/ddrctrl_repack.vhd + src/vhdl/ddrctrl.vhd + +test_bench_files = + tb/vhdl/tb_ddrctrl_address_counter.vhd + tb/vhdl/tb_ddrctrl_pack.vhd + tb/vhdl/tb_ddrctrl_repack.vhd + tb/vhdl/tb_ddrctrl.vhd + +regression_test_vhdl = + +[modelsim_project_file] + + +[quartus_project_file] + diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..838e8f5c89576d1b3a336d91e8d2ab180e863269 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -0,0 +1,119 @@ +------------------------------------------------------------------------------- +-- +-- 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 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_mosi : OUT t_mem_ctlr_mosi -- output data + ); +END ddrctrl; + + +ARCHITECTURE str OF ddrctrl 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_mosi => out_mosi, -- output data + out_of => out_of + ); + +END str; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd new file mode 100644 index 0000000000000000000000000000000000000000..25d43e825ad5bd8bd5babdb72071004b391f9945 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd @@ -0,0 +1,133 @@ +------------------------------------------------------------------------------- +-- +-- 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: Creates address by counting input valids +-- +-- Description: +-- The counter starts on the first valid = '1' clockcylce, the counter stops +-- when valid = '0'. +-- +-- 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_address_counter IS + GENERIC ( + g_tech_ddr : t_c_tech_ddr; -- type of memory + g_sim_model : BOOLEAN := TRUE -- determens if this is a simulation + ); + PORT ( + clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + in_sosi : IN t_dp_sosi; -- input data + in_of : IN NATURAL; + out_mosi : OUT t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- output data + out_of : OUT NATURAL + ); +END ddrctrl_address_counter; + + +ARCHITECTURE rtl OF ddrctrl_address_counter IS + + -- constants for readability + CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- the with of the input data and output data, 576 + CONSTANT c_adr_w : NATURAL := sel_a_b(g_sim_model, 4, func_tech_ddr_ctlr_address_w( g_tech_ddr )); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27 + CONSTANT c_max_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(2**(c_adr_w)-1, c_adr_w)); -- the maximal address that is possible within the vector length of the address + + -- type for statemachine + TYPE t_state IS (RESET, COUNTING, MAX, IDLE); + + -- record for readability + TYPE t_reg IS RECORD + state : t_state; + out_mosi : t_mem_ctlr_mosi; + out_of : NATURAL; + s_in_sosi : t_dp_sosi; + s_in_of : NATURAL; + END RECORD; + + CONSTANT c_t_reg_init : t_reg := (RESET, c_mem_ctlr_mosi_rst, 0, c_dp_sosi_init, 0); + + + -- signals for readability + SIGNAL d_reg : t_reg := c_t_reg_init; + SIGNAL q_reg : t_reg := c_t_reg_init; + +BEGIN + + q_reg <= d_reg WHEN rising_edge(clk); + + -- Increments the address each time in_sosi.valid = '1', if address = c_max_adr the address is reset to 0. + p_adr : PROCESS(rst, in_sosi, in_of, q_reg) + + VARIABLE v : t_reg; + + BEGIN + v := q_reg; + v.out_mosi.wrdata(c_data_w-1 DOWNTO 0) := q_reg.s_in_sosi.data(c_data_w - 1 DOWNTO 0); + v.out_mosi.wr := q_reg.s_in_sosi.valid; + v.out_of := q_reg.s_in_of; + v.s_in_sosi := in_sosi; + v.s_in_of := in_of; + + + CASE q_reg.state IS + WHEN RESET => + v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0'); + + WHEN COUNTING => + v.out_mosi.address(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(TO_UINT(q_reg.out_mosi.address)+1, c_adr_w)); + + WHEN MAX => + v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0'); + + WHEN IDLE => + + END CASE; + + IF rst = '1' THEN + v.state := RESET; + ELSIF q_reg.out_mosi.address(c_adr_w-1 DOWNTO 0) = c_max_adr(c_adr_w-1 DOWNTO 0) AND in_sosi.valid = '1' THEN + v.state := MAX; + ELSIF in_sosi.valid = '1' THEN + v.state := COUNTING; + ELSE + v.state := IDLE; + END IF; + + d_reg <= v; + END PROCESS; + + -- fill outputs + out_mosi <= q_reg.out_mosi; + out_of <= q_reg.out_of; + +END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd new file mode 100644 index 0000000000000000000000000000000000000000..5d7630a29b8c8e4b870f74ca713a0ad3622cd1a1 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd @@ -0,0 +1,58 @@ +------------------------------------------------------------------------------- +-- +-- 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: Make one data vector out of all the data from the t_dp_sosi_arr. +-- +-- Description: +-- The data from the t_dp_sosi_arr gets put into one data vector. +-- +-- Remark: +-- Use VHDL coding template from: +-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding + +LIBRARY IEEE, dp_lib; +USE IEEE.std_logic_1164.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY ddrctrl_pack IS + GENERIC ( + + g_nof_streams : POSITIVE := 12; -- number of input streams + g_data_w : NATURAL := 14 -- data with of input data vectors + + ); + PORT ( + + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- input data + out_data : OUT STD_LOGIC_VECTOR((g_nof_streams*g_data_w)-1 DOWNTO 0) -- output data + + ); +END ddrctrl_pack; + +ARCHITECTURE rtl OF ddrctrl_pack IS + +BEGIN + + -- Putting all the data from the different streams into one data vector. + gen_extract_and_pack_data : FOR I IN 0 TO g_nof_streams-1 GENERATE + out_data(g_data_w*(I+1)-1 DOWNTO g_data_w*I) <= in_sosi_arr(I).data(g_data_w-1 DOWNTO 0); + END GENERATE; + +END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e650494588ca35744b3d979d72ea214368350fe3 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd @@ -0,0 +1,137 @@ +------------------------------------------------------------------------------- +-- +-- 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: Resize the input data vector so that the output data vector can be +-- stored into the ddr memory. +-- +-- Description: +-- The input data gets resized and put into the output data vector. +-- +-- Remark: +-- Use VHDL coding template from: +-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding +-- The output vector must be larger than the input vector. + +LIBRARY IEEE, dp_lib, tech_ddr_lib; +USE IEEE.std_logic_1164.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE tech_ddr_lib.tech_ddr_pkg.ALL; + +ENTITY ddrctrl_repack IS + GENERIC ( + g_tech_ddr : t_c_tech_ddr; -- type of memory + g_in_data_w : NATURAL := 168 -- the input data with + ); + PORT ( + clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + in_data : IN STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); -- input data + out_of : OUT NATURAL := 0; -- amount of internal overflow this output + out_sosi : OUT t_dp_sosi := c_dp_sosi_init -- output data + ); +END ddrctrl_repack; + + +ARCHITECTURE rtl OF ddrctrl_repack IS + + -- constant for readability + CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- the output data with, 576 + CONSTANT k_c_v_w : NATURAL := c_out_data_w*2; -- the c_v data with, 2*576=1152 + + -- type for statemachine + TYPE t_state IS (OVERFLOW_OUTPUT, FILL_VECTOR, FIRST_OUTPUT, RESET); + + -- record for readability + TYPE t_reg IS RECORD + state : t_state; -- the state the process is currently in; + a_of : NATURAL; -- amount of overflow + c_v : STD_LOGIC_VECTOR(k_c_v_w-1 DOWNTO 0); -- the vector that stores the input data until the data is put into the output data vector + c_v_count : NATURAL; -- the amount of times the c_v vector received data from the input since the last time it was filled completely + out_data_count : NATURAL; -- the amount of times the output data vector has been filled since the last time c_v was filled completely + out_of : NATURAL; + out_sosi : t_dp_sosi; + END RECORD; + + CONSTANT c_t_reg_init : t_reg := (RESET, 0, (OTHERS => '0'), 0, 0, 0, c_dp_sosi_init); + + -- signals for readability + SIGNAL d_reg : t_reg := c_t_reg_init; + SIGNAL q_reg : t_reg := c_t_reg_init; + +BEGIN + + q_reg <= d_reg WHEN rising_edge(clk); + + -- put the input data into c_v and fill the output vector from c_v + p_state : PROCESS(q_reg, rst) + + VARIABLE v : t_reg; + + BEGIN + + v := q_reg; + + CASE q_reg.state IS + WHEN FILL_VECTOR => -- if the input data doesn't exceeds the output data vector width + v.c_v(g_in_data_w*(q_reg.c_v_count+1)+q_reg.a_of-1 DOWNTO g_in_data_w*q_reg.c_v_count+q_reg.a_of) := in_data(g_in_data_w-1 DOWNTO 0); -- fill c_v + v.c_v_count := q_reg.c_v_count+1; -- increase the counter of c_v with 1 + v.out_sosi.valid := '0'; -- out_sosi.valid 0 + + WHEN FIRST_OUTPUT => -- if the input data exceeds output data vector width but not the c_v width + v.c_v(g_in_data_w*(q_reg.c_v_count+1)+q_reg.a_of-1 DOWNTO g_in_data_w*q_reg.c_v_count+q_reg.a_of) := in_data(g_in_data_w-1 DOWNTO 0); -- fill c_v + v.c_v_count := q_reg.c_v_count + 1; -- increase the counter of c_v with 1 + v.out_sosi.data(c_out_data_w - 1 DOWNTO 0) := v.c_v(c_out_data_w - 1 DOWNTO 0); -- fill out_sosi.data with 1st part of c_v + v.out_sosi.valid := '1'; -- out_sosi.valid 1 + v.out_data_count := q_reg.out_data_count+1; -- increase the counter of out_sosi.data with 1 + + WHEN OVERFLOW_OUTPUT => -- if the input data exceeds the output data vector width and the c_v width + v.a_of := q_reg.a_of + (g_in_data_w*(q_reg.c_v_count+1)) - (c_out_data_w*(q_reg.out_data_count+1)); -- check how much overflow there is and safe it in a_of + v.out_of := v.a_of; -- set the output overflow to the overflow that maches the out_sosi.data vector + v.c_v(k_c_v_w-1 DOWNTO k_c_v_w-(g_in_data_w-v.a_of)) := in_data(g_in_data_w-v.a_of-1 DOWNTO 0); -- fill the rest of c_v untill the end + v.c_v(v.a_of-1 DOWNTO 0) := in_data(g_in_data_w-1 DOWNTO g_in_data_w-v.a_of); -- fill the start of c_v untill the a_of + v.out_sosi.data(c_out_data_w-1 DOWNTO 0) := v.c_v(k_c_v_w-1 DOWNTO c_out_data_w); -- fill out_sosi.data with 2nd part of c_v + v.out_sosi.valid := '1'; -- out_sosi.valid 1 + v.c_v_count := 0; -- reset counter + v.out_data_count := 0; -- reset counter + + WHEN RESET => + v := c_t_reg_init; + + END CASE; + + + IF rst = '1' THEN + v.state := RESET; + ELSIF ((g_in_data_w*(v.c_v_count+1))+v.a_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN + v.state := FIRST_OUTPUT; + ELSIF ((g_in_data_w*(v.c_v_count+1))+v.a_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN + v.state := OVERFLOW_OUTPUT; + ELSE + v.state := FILL_VECTOR; + END IF; + + d_reg <= v; + END PROCESS; + + -- fill outputs + out_of <= q_reg.out_of; + out_sosi <= q_reg.out_sosi; + +END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8b56c9ddcf22d7455e0099fbc19f4179ba6e526c --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -0,0 +1,209 @@ +------------------------------------------------------------------------------- +-- +-- 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.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 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; + +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 + + -- 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.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.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 + + -- 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_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_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_mosi => out_mosi + ); + +END tb; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a17f098b594c673887acdc59f982a8dd87d515f2 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd @@ -0,0 +1,193 @@ +------------------------------------------------------------------------------- +-- +-- 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_address_counter.vhd +-- Usage: +-- > run -a + +LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.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_address_counter 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_sim_length : NATURAL := 52 -- determens the length of the duration of the test + + ); +END tb_ddrctrl_address_counter; + +ARCHITECTURE tb OF tb_ddrctrl_address_counter IS + + -- constants for running the testbench + CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz + CONSTANT c_clk_period : TIME := (10**6/c_clk_freq)*1 ps; -- clock period, 5 ns + + -- constants for running the test + CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- in and 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 + + + -- input signals for ddrctrl_address_counter.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 : t_dp_sosi := c_dp_sosi_init; -- signal which is the input for ddrctrl_address_counter.vhd + SIGNAL in_of : NATURAL := 0; -- signal which contains the amount of overflow + + -- output signal from ddrctrl_address_counter.vhd + SIGNAL out_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- signal which is the output from ddrctrl_address_counter.vhd + SIGNAL out_of : NATURAL := 0; -- signal which is the output from ddrctrl_address_counter.vhd + + -- testbench signals + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + SIGNAL in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- signal which contains the data that is set as input + SIGNAL q_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- signal which contains the data that is set as input with a delay of 1 clockcycle + SIGNAL q_q_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- signal which contains the data that is set as input with a delay of 2 clockcycles + SIGNAL in_data_enable : STD_LOGIC := '0'; -- signal to determen if in_data is ready for reading + SIGNAL q_in_data_enable : STD_LOGIC := '0'; -- signal to determen if in_data is ready for reading with a delay of 1 clockcycle + SIGNAL q_q_in_data_enable: STD_LOGIC := '0'; -- signal to determen if in_data is ready for reading with a delay of 2 clockcycles + SIGNAL q_in_of : NATURAL := 0; -- signal which contains the amount of overflow with a delay of 1 clockcycle + SIGNAL q_q_in_of : NATURAL := 0; -- signal which contains the amount of overflow with a delay of 2 clockcycles + SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a reset + SIGNAL q_lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a reset with a delay of 1 clockcycle + +BEGIN + + -- wiring the input signals to the inputs of the testbench + in_sosi.data(c_data_w-1 DOWNTO 0) <= in_data(c_data_w-1 DOWNTO 0); + in_sosi.valid <= in_data_enable; + + -- generating clock + clk <= NOT clk OR tb_end AFTER c_clk_period/2; + + -- excecuting the test + p_test : PROCESS + BEGIN + + -- initialize inputs + tb_end <= '0'; + in_data <= (OTHERS => '0'); + in_data_enable <= '0'; + WAIT UNTIL rising_edge(clk); + + -- changing inputs to start the address counting + FOR I IN 0 TO g_sim_length-1 LOOP + in_data_enable <= '1'; + in_data <= NOT in_data; + in_of <= in_of + 1; + WAIT FOR c_clk_period*1; + in_data_enable <= '0'; + WAIT FOR c_clk_period*2; + END LOOP; + + -- stopping the test + WAIT FOR c_clk_period*4; + tb_end <= '1'; + 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_in_data_enable <= q_in_data_enable; + q_q_in_data <= q_in_data; + q_q_in_of <= q_in_of; + q_q_rst <= q_rst; + q_in_data_enable <= in_data_enable; + q_in_data <= in_data; + q_in_of <= in_of; + 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 data is correct and if valid is correct + p_verify_data_valid : PROCESS + BEGIN + WAIT UNTIL rising_edge(clk); + IF rising_edge(clk) THEN + ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_mosi.wrdata(c_data_w-1 DOWNTO 0) REPORT "in_sosi.data does not match out_mosi.wrdata" SEVERITY ERROR; + ASSERT q_q_in_data_enable = out_mosi.wr REPORT "in_sosi.valid does not match out_mosi.wr" SEVERITY ERROR; + ASSERT q_q_in_of = out_of REPORT "in_of does not match out_of" SEVERITY ERROR; + END IF; + END PROCESS; + + -- excecuting the reset test + p_test_reset : PROCESS + BEGIN + rst <= '0'; + WAIT FOR c_clk_period*((c_adr_size*4)+3); + rst <= '1'; + WAIT FOR c_clk_period*1; + 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; + + + -- DUT + u_ddrctrl_address_counter : ENTITY work.ddrctrl_address_counter + GENERIC MAP ( + g_tech_ddr => g_tech_ddr, + g_sim_model => g_sim_model + ) + PORT MAP ( + clk => clk, + rst => rst, + in_sosi => in_sosi, + in_of => in_of, + + out_mosi => out_mosi, + out_of => out_of + ); + +END tb; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd new file mode 100644 index 0000000000000000000000000000000000000000..6f81b6cb22c88159a2153680f467c39799fa06fe --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------- +-- +-- 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_pack.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_pack IS + GENERIC ( + + 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 -- determens the lengt of the duration of the test + + ); +END tb_ddrctrl_pack; + +ARCHITECTURE tb OF tb_ddrctrl_pack IS + + -- constants for running the 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 for readability + CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- output data with, 168 + + -- function for making test vector + FUNCTION c_testv_init RETURN STD_LOGIC_VECTOR IS + VARIABLE temp : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); + BEGIN + FOR I IN 0 TO 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_testv_init; + + -- constants for running the test + CONSTANT c_testv : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0) := c_testv_init; -- testvector which contains a number for each stream, so the data of stream 6 will look like ...00110 + + + -- input signals for ddrctrl_pack.vhd + SIGNAL clk : STD_LOGIC := '1'; -- clock signal + SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input signal for ddrctrl_pack.vhd + + -- output singal from ddrctrl_pack.vhd + SIGNAL out_data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); -- output signal from ddrctrl_pack.vhd + + -- testbench signal + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + +BEGIN + + -- generating clock + clk <= NOT clk OR tb_end AFTER c_clk_period/2; + + -- excecuting the test + p_test : PROCESS + BEGIN + + -- starting the test + tb_end <= '0'; + WAIT UNTIL rising_edge(clk); + WAIT FOR c_clk_period*2; + + + -- the input data vectors get filled with the corresponding number + fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP + in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= c_testv(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I); + END LOOP; + + + -- the numbers get cycled trough the input vectors + change_in_sosi_arr : FOR J IN 0 TO g_sim_length-1 LOOP + WAIT FOR c_clk_period*1; + in_sosi_arr(0).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(g_nof_streams-1).data(g_data_w - 1 DOWNTO 0); + loop_switch_data : FOR I IN 1 TO g_nof_streams-1 LOOP + in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(I-1).data(g_data_w - 1 DOWNTO 0); + END LOOP; + END LOOP; + + -- stopping the testbench + WAIT FOR c_clk_period*4; + tb_end <= '1'; + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; + END PROCESS; + + -- verification by checking if the input vectors equel the corresponding index of the output vector + p_verify : PROCESS + BEGIN + WAIT UNTIL rising_edge(clk); + IF rising_edge(clk) THEN + check_data : FOR I IN 0 TO g_nof_streams - 1 LOOP + ASSERT out_data(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I) = in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) REPORT "Data does not match, I = " & NATURAL'image(I) SEVERITY ERROR; + END LOOP; + END IF; + END PROCESS; + + -- DUT + u_ddrctrl_pack : ENTITY work.ddrctrl_pack + GENERIC MAP ( + g_nof_streams => g_nof_streams, + g_data_w => g_data_w + ) + PORT MAP ( + in_sosi_arr => in_sosi_arr, + + out_data => out_data + ); + +END tb; + + + + + diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd new file mode 100644 index 0000000000000000000000000000000000000000..395cb8896128ab33aa01da54733982f8a855e143 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd @@ -0,0 +1,152 @@ +------------------------------------------------------------------------------- +-- +-- 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_repack.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_repack IS + GENERIC ( + + g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory + g_in_data_w : NATURAL := 168; -- input data vector with + g_sim_lengt : NATURAL := 52 -- amount of times there wil be input data for ddrctrl_repack in this testbench + + ); +END tb_ddrctrl_repack; + +ARCHITECTURE tb OF tb_ddrctrl_repack IS + + -- constants for running testbench + CONSTANT c_clk_freq : NATURAL := 200; -- clock freqency in MHz + CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock period, 5 ns + + -- constant for readability + CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576 + + -- function for making total data vector + FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS + VARIABLE temp : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0); + BEGIN + FOR I IN 0 TO g_sim_lengt-1 LOOP + temp(g_in_data_w*(I+1)-1 DOWNTO g_in_data_w*I) := TO_UVEC(I, g_in_data_w); + END LOOP; + RETURN temp; + END FUNCTION c_total_vector_init; + + -- constant for running the test + CONSTANT c_total_vector : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-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_repack.vhd + SIGNAL clk : STD_LOGIC := '1'; -- clock signal + SIGNAL rst : STD_LOGIC := '0'; -- reset signal + SIGNAL in_data : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- input data signal for ddrctrl_repack + + -- output signals from ddrctrl_repack.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 data signal form ddrctrl_repack + + -- testbench signal + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + + -- singals for running the test + SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd + SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started + +BEGIN + + -- Generating clock + clk <= NOT clk OR tb_end AFTER c_clk_period/2; + + -- Excecuting the 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*5; + rst <= '1'; + WAIT FOR c_clk_period*1; + rst <= '0'; + WAIT FOR c_clk_period*1; + test_running <= '1'; -- start of test + + -- filling the input vector g_sim_lengt amount of times + make_in_data : FOR I IN 0 TO g_sim_lengt-1 LOOP + in_data(g_in_data_w-1 DOWNTO 0) <= TO_UVEC(I, g_in_data_w); + WAIT FOR c_clk_period*1; + in_data_cnt <= in_data_cnt + 1; + END LOOP; + test_running <= '0'; + + -- stopping the testbench + WAIT FOR c_clk_period*5; + tb_end <= '1'; + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; + 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 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 := g_in_data_w*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_repack : ENTITY work.ddrctrl_repack + GENERIC MAP ( + g_tech_ddr => g_tech_ddr, + g_in_data_w => g_in_data_w + ) + PORT MAP ( + clk => clk, + rst => rst, + in_data => in_data, + + out_of => out_of, + out_sosi => out_sosi + ); + +END tb; +