diff --git a/applications/lofar2/libraries/ddrctrl/hdllib.cfg b/applications/lofar2/libraries/ddrctrl/hdllib.cfg index ae592e5b2967c0692c57ac50ccfaabd95b458b55..8f92d2ddd3f4d347fdfc32811cdbcefd07fe0288 100644 --- a/applications/lofar2/libraries/ddrctrl/hdllib.cfg +++ b/applications/lofar2/libraries/ddrctrl/hdllib.cfg @@ -8,11 +8,13 @@ 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 = 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..74fbb3c2d39fb5ad698ef2130303b5d501e5508f --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -0,0 +1,108 @@ +------------------------------------------------------------------------------- +-- +-- 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: Create 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 IS + GENERIC ( + g_tech_ddr : t_c_tech_ddr; + g_sim_model : BOOLEAN := TRUE; + g_nof_streams : NATURAL := 12; + g_data_w : NATURAL := 14 + ); + PORT ( + clk : IN STD_LOGIC := '0'; + rst : IN STD_LOGIC; + in_sosi_arr : IN t_dp_sosi_arr; + out_of : OUT NATURAL; + out_mosi : OUT t_mem_ctlr_mosi + ); +END ddrctrl; + + +ARCHITECTURE rtl OF ddrctrl IS + + CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; + + + SIGNAL total_data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); + SIGNAL out_sosi : t_dp_sosi; + +BEGIN + + 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( + + clk => clk, + in_sosi_arr => in_sosi_arr, + out_data => total_data + + ); + + 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, + in_data => total_data, + out_of => out_of, + out_sosi => out_sosi + ); + + u_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 => out_sosi, + out_mosi => out_mosi + ); + +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..11271b1537b61de03e096f7ee3d0cfbf0230dc58 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -0,0 +1,158 @@ +------------------------------------------------------------------------------- +-- +-- 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 IS + GENERIC ( + + g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory + g_sim_model : BOOLEAN := TRUE; + g_nof_streams : POSITIVE := 12; -- number of input streams + g_data_w : NATURAL := 14; -- data with of input data vectors + g_sim_lengt : NATURAL := 52 + + ); +END tb_ddrctrl; + +ARCHITECTURE tb OF tb_ddrctrl IS + + CONSTANT c_clk_freq : NATURAL := 200; -- MHz + CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns + + 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 + + + FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS + VARIABLE temp : STD_LOGIC_VECTOR(c_in_data_w*g_sim_lengt-1 DOWNTO 0); + BEGIN + FOR I IN 0 TO g_sim_lengt-1 LOOP + temp(c_in_data_w*(I+1)-1 DOWNTO c_in_data_w*I) := TO_UVEC(I, c_in_data_w); + END LOOP; + RETURN temp; + END FUNCTION c_total_vector_init; + CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_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 + + + + SIGNAL ctr_of : NATURAL := 0; -- signal which contains the amount of overflow for checking + SIGNAL in_data_cnt : NATURAL := 0; + + SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell when the testing has started + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + + + SIGNAL clk : STD_LOGIC := '1'; -- clock signal + SIGNAL rst : STD_LOGIC := '0'; + 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 + + SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is + SIGNAL out_mosi : t_mem_ctlr_mosi; -- output signal from ddrctrl_pack.vhd + +BEGIN + + clk <= NOT clk OR tb_end AFTER c_clk_period/2; -- generating clock signal + + p_mm : PROCESS + BEGIN + + -- Start the testbench. + tb_end <= '0'; + WAIT UNTIL rising_edge(clk); -- align to rising edge + WAIT UNTIL out_of /= 0; -- wait for out_of /= 0 to align to ddrctrl_repack properly + WAIT UNTIL out_of = 0; -- align to ddrctrl_repack + test_running <= '1'; -- start of test + + + -- The input data vectors get filled with the corresponding numbers. + make_data : FOR J IN 0 TO g_sim_lengt-1 LOOP + fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP + in_sosi_arr(I).data(c_in_data_w - 1 DOWNTO 0) <= c_total_vector(c_in_data_w*(I+1)+(J+1)-1 DOWNTO c_in_data_w*I+(J+1)); + END LOOP; + WAIT FOR c_clk_period*1; + in_data_cnt <= in_data_cnt + 1; + END LOOP; + test_running <= '0'; + + + -- Stop the testbench. + WAIT FOR c_clk_period*4; + tb_end <= '1'; + + + WAIT; + 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(out_mosi.wr); + --WAIT FOR c_clk_period*1; + IF test_running = '1' THEN + -- ASSERT FALSE REPORT "ik werk" SEVERITY NOTE; + IF out_data_cnt mod 2 = 0 THEN + ctr_of := c_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) 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)-1 DOWNTO c_out_data_w*out_data_cnt) REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt) SEVERITY ERROR; + out_data_cnt := out_data_cnt + 1; + END IF; + END PROCESS; + + + u_ddrctrl_pack : 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; + + + + +