diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 12fec289c03515515ec61df6cfc36a27b47d0442..357e9279a401035adc5e658b98fb201b1a8c4c40 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -83,10 +83,30 @@ END ddrctrl; ARCHITECTURE str OF ddrctrl IS -- constant for readability - CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); - CONSTANT c_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 - CONSTANT c_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 - CONSTANT c_rd_fifo_uw_w : NATURAL := ceil_log2(c_rd_fifo_depth*(func_tech_ddr_ctlr_data_w(g_tech_ddr)/c_io_ddr_data_w)); + CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- 576 + CONSTANT c_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 + CONSTANT c_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 + CONSTANT c_rd_fifo_uw_w : NATURAL := ceil_log2(c_rd_fifo_depth*(func_tech_ddr_ctlr_data_w(g_tech_ddr)/c_io_ddr_data_w)); + + CONSTANT c_adr_w : NATURAL := 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 : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address + CONSTANT c_bim : NATURAL := (c_max_adr*c_io_ddr_data_w)/(g_block_size*g_nof_streams*g_data_w); -- the amount of whole blocks that fit in memory. + CONSTANT c_nof_adr : NATURAL := (c_bim*g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w; -- rounding error removes the amount of extra addresses. + CONSTANT c_of_pb : NATURAL := (g_block_size*g_nof_streams*g_data_w)-(((g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w)*c_io_ddr_data_w); -- amount of overflow after one block is written to memory + + FUNCTION c_of_after_nof_adr_init RETURN NATURAL IS + VARIABLE temp : NATURAL := 0; + BEGIN + FOR I IN 0 TO c_bim-1 LOOP + IF temp+c_of_pb < c_io_ddr_data_w THEN + temp := temp+c_of_pb; + ELSE + temp := temp+c_of_pb-c_io_ddr_data_w; + END IF; + END LOOP; + RETURN temp; + END FUNCTION c_of_after_nof_adr_init; + CONSTANT c_of_after_nof_adr : NATURAL := c_of_after_nof_adr_init; -- signals for connecting the components SIGNAL ctrl_clk : STD_LOGIC; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd index 6ed2ce9a94fc6a6e7aa84a8fbd1203d66a9e68df..44ff8241aca97501ef26d3a1b6dd73d9d105d491 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd @@ -72,10 +72,9 @@ ARCHITECTURE str OF ddrctrl_input IS -- 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 sosi_p_rp : t_dp_sosi := c_dp_sosi_init; + SIGNAL sosi_rp_ac : t_dp_sosi := c_dp_sosi_init; SIGNAL a_of : NATURAL := 0; - SIGNAL bsn_p_rp : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); - SIGNAL bsn_rp_ac : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); SIGNAL adr : NATURAL := 0; SIGNAL bsn_wr : STD_LOGIC := '0'; SIGNAL bsn_ds : NATURAL := 0; @@ -93,9 +92,7 @@ BEGIN ) PORT MAP( in_sosi_arr => in_sosi_arr, -- input data - out_data => data, -- output data - out_bsn => bsn_p_rp, -- output bsn - out_valid => valid + out_sosi => sosi_p_rp -- output data ); -- resizes the input data vector so that the output data vector can be stored into the ddr memory @@ -107,15 +104,13 @@ BEGIN PORT MAP( clk => clk, rst => rst, - in_data => data, -- input data - in_bsn => bsn_p_rp, + in_sosi => sosi_p_rp, -- input data in_stop => in_stop, in_adr => adr, in_valid => valid, out_of => a_of, -- amount of internal overflow - out_sosi => sosi, -- output data + out_sosi => sosi_rp_ac, -- output data out_bsn_ds => bsn_ds, -- amount of bits between adr [0] and sosi_arr[0][0] where bsn is assigned to - out_bsn => bsn_rp_ac, out_bsn_wr => bsn_wr ); @@ -132,7 +127,6 @@ BEGIN in_of => a_of, in_bsn_wr => bsn_wr, in_bsn_ds => bsn_ds, - in_bsn => bsn_rp_ac, out_sosi => out_sosi, -- output data out_of => out_of, out_adr => adr, diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_pack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_pack.vhd index 8dfb6a752b9271c0cd7b873e42e2fde2edbb11a1..e54d291adfc6bc68b51293ca4144d47e6f5aae7e 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_pack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_pack.vhd @@ -37,10 +37,8 @@ ENTITY ddrctrl_input_pack IS 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 - out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- output bsn - out_valid : OUT STD_LOGIC + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- input data + out_sosi : OUT t_dp_sosi := c_t_dp_sosi_init -- output data ); END ddrctrl_input_pack; @@ -51,7 +49,7 @@ BEGIN gen_extract_and_pack_data : FOR I IN 0 TO g_nof_streams-1 GENERATE p_generate : PROCESS(in_sosi_arr) IS BEGIN - out_data(g_data_w*(I+1)-1 DOWNTO g_data_w*I) <= in_sosi_arr(I).data(g_data_w-1 DOWNTO 0); + out_sosi.data(g_data_w*(I+1)-1 DOWNTO g_data_w*I) <= in_sosi_arr(I).data(g_data_w-1 DOWNTO 0); END PROCESS; END GENERATE; @@ -59,16 +57,63 @@ BEGIN -- check if the input data is valid bij doing a and operation on all of them p_valid : PROCESS(in_sosi_arr) IS - VARIABLE valid : STD_LOGIC := '1'; + VARIABLE valid : STD_LOGIC; BEGIN valid := '1'; FOR I IN 0 TO g_nof_streams-1 LOOP valid := valid AND in_sosi_arr(I).valid; END LOOP; - out_valid <= valid; + out_sosi.valid <= valid; END PROCESS; - out_bsn <= in_sosi_arr(0).bsn(c_dp_stream_bsn_w-1 DOWNTO 0); + + -- check for sop + p_sop : PROCESS(in_sosi_arr) IS + + VARIABLE sop : STD_LOGIC; + + BEGIN + sop := '1' + FOR I IN 0 TO g_nof_streams-1 LOOP + sop := sop AND in_sosi_arr(I).sop; + END LOOP; + out_sosi.sop <= sop; + END PROCESS; + + + -- check for eop + p_eop : PROCESS(in_sosi_arr) IS + + VARIABLE eop : STD_LOGIC; + + BEGIN + eop := '1' + FOR I IN 0 TO g_nof_streams-1 LOOP + eop := eop AND in_sosi_arr(I).eop; + END LOOP; + out_sosi.eop <= eop; + END PROCESS; + + + -- check for bsn + p_bsn : PROCESS(in_sosi_arr) IS + + VARIABLE correct_bsn : STD_LOGIC; + + BEGIN + correct_bsn := '1'; + FOR I IN 1 TO g_nof_streams-1 LOOP + IF in_sosi_arr(I-1).bsn = in_sosi_arr(I).bsn THEN + correct_bsn := correct_bsn AND '1'; + ELSE + correct_bsn := correct_bsn AND '0'; + END IF; + END LOOP; + IF correct_bsn = '1' THEN + out_sosi.bsn <= in_sosi_arr(0).bsn(c_dp_stream_bsn_w-1 DOWNTO 0); + ELSE + out_sosi.bsn <= (OTHERS => '0'); + END IF; END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd index d47b4278c46d4ff79f8948e2a7e8ce29f74b53a1..e529aece8148a2ff0365d4cb3f0a7e7dd4eac327 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd @@ -42,15 +42,10 @@ ENTITY ddrctrl_input_repack IS PORT ( clk : IN STD_LOGIC; rst : IN STD_LOGIC; - in_data : IN STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); -- input data - in_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- input bsn + in_sosi : IN t_dp_sosi; -- input data in_stop : IN STD_LOGIC := '0'; - in_adr : IN NATURAL; - in_valid : IN STD_LOGIC; - out_of : OUT NATURAL := 0; -- amount of internal overflow this output out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data out_bsn_ds : OUT NATURAL := 0; - out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); out_bsn_wr : OUT STD_LOGIC := '0' ); END ddrctrl_input_repack; @@ -70,18 +65,18 @@ ARCHITECTURE rtl OF ddrctrl_input_repack IS state : t_state; -- the state the process is currently in; 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 + a_of : NATURAL; -- this is the amount of bits that the first data word(168) is shifted from the first bit in the data word(576) s_out_bsn_ds : NATURAL; s_out_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); output_passed : STD_LOGIC; -- this signal is to make sure that out_bsn_written only gets low after a write cycle, this is so that ddrctrl_address_counter can save the address at which the data corresponding to the bsn is saved 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_bsn_written : STD_LOGIC; -- this signal gets high ones the out_bsn signal is updated, this is so in ddrctrl_input_address_counter the right address can be linked with the out_bsn signal - out_of : NATURAL; -- this is the amount of bits that the first data word(168) is shifted from the first bit in the data word(576) out_sosi : t_dp_sosi; -- this is the sosi stream that contains the data out_bsn_ds : NATURAL; -- this is the amount of bits that the data corresponding to out_bsn is shifted from the first bit in that data word out_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- this is the bsn corresponding to the data in memory END RECORD; - CONSTANT c_t_reg_init : t_reg := (RESET, (OTHERS => '0'), 0, 0, (OTHERS => '0'), '0', 0, '0', 0, c_dp_sosi_init, 0, (OTHERS => '0')); + CONSTANT c_t_reg_init : t_reg := (RESET, (OTHERS => '0'), 0, 0, 0, (OTHERS => '0'), '0', 0, '0', c_dp_sosi_init, 0, (OTHERS => '0')); -- signals for readability diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd index 445f8d98fd2e6e3f5ff6b5b68e3249e17e4fc2c4..6e9a19c5497e6593617b73323728631d4aa94a0d 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -51,35 +51,51 @@ END tb_ddrctrl; ARCHITECTURE tb OF tb_ddrctrl IS - CONSTANT c_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + CONSTANT c_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation -- 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(c_sim_model, c_sim_ddr, c_mem_ddr); + 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(c_sim_model, c_sim_ddr, c_mem_ddr); -- constants for readability - CONSTANT c_ctrl_data_w : NATURAL := func_tech_ddr_ctlr_data_w( c_tech_ddr ); -- 576 - CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 + CONSTANT c_ctrl_data_w : NATURAL := func_tech_ddr_ctlr_data_w( c_tech_ddr ); -- 576 + CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 -- 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; -- mm clock frequency in MHz - CONSTANT c_mm_clk_period : TIME := (10**6/c_mm_clk_freq)*1 ps; -- mm clock period, 10 ns - CONSTANT c_sim_length : NATURAL := (g_sim_length*c_ctrl_data_w)/c_in_data_w; -- amount of input words that get put into the DUT + 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; -- mm clock frequency in MHz + CONSTANT c_mm_clk_period : TIME := (10**6/c_mm_clk_freq)*1 ps; -- mm clock period, 10 ns + CONSTANT c_sim_length : NATURAL := (g_sim_length*c_ctrl_data_w)/c_in_data_w; -- amount of input words that get put into the DUT -- constant for checking output data - CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( c_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 : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address - CONSTANT c_output_stop_adr : NATURAL := (c_max_adr+1)-((((c_max_adr+1)/64)*g_stop_percentage/100)*64); - CONSTANT c_output_ds : NATURAL := 144; - + CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( c_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 : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address + CONSTANT c_output_stop_adr : NATURAL := (c_max_adr+1)-((((c_max_adr+1)/64)*g_stop_percentage/100)*64); + CONSTANT c_output_ds : NATURAL := 144; + CONSTANT c_bim : NATURAL := (c_max_adr*c_io_ddr_data_w)/(g_block_size*g_nof_streams*g_data_w); -- the amount of whole blocks that fit in memory. + CONSTANT c_nof_adr : NATURAL := (c_bim*g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w; -- rounding error removes the amount of extra addresses. + CONSTANT c_of_pb : NATURAL := (g_block_size*g_nof_streams*g_data_w)-(((g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w)*c_io_ddr_data_w); -- amount of overflow after one block is written to memory + + FUNCTION c_of_after_nof_adr_init RETURN NATURAL IS + VARIABLE temp : NATURAL := 0; + BEGIN + FOR I IN 0 TO c_bim-1 LOOP + IF temp+c_of_pb < c_io_ddr_data_w THEN + temp := temp+c_of_pb; + ELSE + temp := temp+c_of_pb-c_io_ddr_data_w; + END IF; + END LOOP; + RETURN temp; + END FUNCTION c_of_after_nof_adr_init; + CONSTANT c_of_after_nof_adr : NATURAL := c_of_after_nof_adr_init; -- 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*c_sim_length-1 DOWNTO 0); - VARIABLE conv : STD_LOGIC_VECTOR(32-1 DOWNTO 0) := (OTHERS => '0'); -- removes a warning + VARIABLE temp : STD_LOGIC_VECTOR(c_in_data_w*c_sim_length-1 DOWNTO 0); + VARIABLE conv : STD_LOGIC_VECTOR(32-1 DOWNTO 0) := (OTHERS => '0'); -- removes a warning BEGIN FOR I IN 0 TO c_sim_length-1 LOOP conv := TO_UVEC(I, 32);