diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd index 9cb94c2351bc68cc4f82aa09ea63c78c7a17ecca..264621588a079b31683f91d7b7175b2fb57b197d 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd @@ -127,11 +127,7 @@ BEGIN q_reg <= d_reg WHEN rising_edge(clk); -- put the input data into c_v and fill the output vector from c_v -<<<<<<< HEAD - p_state : PROCESS(q_reg, rst, out_of, out_sosi, out_adr, dvr_miso, rd_fifo_usedw) -======= - p_state : PROCESS(q_reg, rst, inp_of, inp_sosi, inp_adr) ->>>>>>> L2SDP-667 + p_state : PROCESS(q_reg, rst, inp_of, inp_sosi, inp_adr, dvr_miso, rd_fifo_usedw) VARIABLE v : t_reg := c_t_reg_init; @@ -147,7 +143,7 @@ BEGIN v.state := RESET; ELSIF stop_in = '1' THEN v.state := SET_STOP; - ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + ELSIF v.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN v.state := STOP_WRITING; ELSIF v.stopped = '1' THEN v.state := IDLE; @@ -178,7 +174,7 @@ BEGIN v.state := RESET; ELSIF stop_in = '1' THEN v.state := SET_STOP; - ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + ELSIF v.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN v.state := STOP_WRITING; ELSIF v.stopped = '1' THEN v.state := IDLE; @@ -218,7 +214,7 @@ BEGIN v.state := RESET; ELSIF stop_in = '1' THEN v.state := SET_STOP; - ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + ELSIF v.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN v.state := STOP_WRITING; ELSIF v.stopped = '1' THEN v.state := IDLE; @@ -272,7 +268,7 @@ BEGIN IF TO_UINT(rd_fifo_usedw) = 0 AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN IF TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt >= c_max_adr THEN - v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)-c_max_adr, c_adr_w); + v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)-c_max_adr-1, c_adr_w); --assert false report "1. address: " & natural'image((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)-c_max_adr) severity note; ELSE v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt, c_adr_w); @@ -306,7 +302,7 @@ BEGIN v.state := RESET; ELSIF stop_in = '1' THEN v.state := SET_STOP; - ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + ELSIF v.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN v.state := STOP_WRITING; ELSIF v.stopped = '1' THEN v.state := IDLE; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd index 2fe5ca51622eaf4a22327207c0755e14f6aa7325..c566a4cbf00338419ae8f5107862b7c61c532f87 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd @@ -53,6 +53,7 @@ BEGIN gen_repack_data : FOR I IN 0 TO g_nof_streams-1 GENERATE out_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= in_sosi.data(g_data_w*(I+1)-1 DOWNTO g_data_w*I); out_sosi_arr(I).bsn(c_dp_stream_bsn_w-1 DOWNTO 0) <= in_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0); + out_sosi_arr(I).valid <= in_sosi.valid; END GENERATE; END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd index a7c644d2ace800f26f6bcefc19bbb55fbcdd0a35..eb14a3b4bde41e97c8d08b7f365c2694c6734b7a 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd @@ -56,18 +56,20 @@ END ddrctrl_output_unpack; ARCHITECTURE rtl OF ddrctrl_output_unpack IS -- type for statemachine - TYPE t_state IS ( READING, FH_READ, SH_READ, RESET, IDLE); + TYPE t_state IS ( READING, FH_READ, SH_READ, RESET, IDLE, OFF); -- record for readability TYPE t_reg IS RECORD state : t_state; a_of : NATURAL; op_data_cnt : NATURAL; + inp_vect : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); + fh_done : STD_LOGIC; out_sosi : t_dp_sosi; out_ready : STD_LOGIC; END RECORD; - CONSTANT c_t_reg_init : t_reg := (RESET, 0, 0, c_dp_sosi_init, '0'); + CONSTANT c_t_reg_init : t_reg := (RESET, 0, 0, (OTHERS => '0'), '0', c_dp_sosi_init, '0'); -- signals for readability @@ -89,49 +91,57 @@ BEGIN CASE q_reg.state IS WHEN READING => - v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := in_sosi.data((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); + v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.inp_vect((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); v.out_sosi.valid := '1'; v.out_sosi.bsn := ADD_UVEC(q_reg.out_sosi.bsn, "0001", c_dp_stream_bsn_w); v.op_data_cnt := q_reg.op_data_cnt+1; + IF (g_out_data_w*(v.op_data_cnt+2))+q_reg.a_of >= g_in_data_w AND (g_out_data_w*(v.op_data_cnt+2))+q_reg.a_of <= g_in_data_w+g_out_data_w THEN + v.out_ready := '1'; + ELSE + v.out_ready:= '0'; + END IF; + IF rst = '1' THEN v.state := RESET; - ELSIF in_sosi.valid = '1' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w THEN v.state := FH_READ; - ELSIF in_sosi.valid = '1' THEN - v.state := READING; ELSE - v.state := IDLE; + v.state := READING; END IF; WHEN FH_READ => v.a_of := (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-g_in_data_w; - v.out_sosi.data(g_out_data_w-v.a_of-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); + v.out_sosi.data(g_out_data_w-v.a_of-1 DOWNTO 0) := q_reg.inp_vect(g_in_data_w-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); v.out_sosi.valid := '0'; v.op_data_cnt := 0; - v.out_ready := '1'; + v.fh_done := '1'; + v.out_ready := '0'; IF rst = '1' THEN v.state := RESET; - ELSE + ELSIF in_sosi.valid = '1' THEN v.state := SH_READ; + v.inp_vect(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); + ELSE + v.state := IDLE; END IF; WHEN SH_READ => - v.out_sosi.data(g_out_data_w-1 DOWNTO g_out_data_w-q_reg.a_of) := in_sosi.data((g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of-1 DOWNTO 0); + v.out_sosi.data(g_out_data_w-1 DOWNTO g_out_data_w-q_reg.a_of) := q_reg.inp_vect((g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of-1 DOWNTO 0); v.out_sosi.valid := '1'; v.out_sosi.bsn := ADD_UVEC(q_reg.out_sosi.bsn, "0001", c_dp_stream_bsn_w); v.op_data_cnt := 0; v.out_ready := '0'; + v.fh_done := '0'; IF rst = '1' THEN v.state := RESET; - ELSIF in_sosi.valid = '1' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w THEN v.state := FH_read; - ELSIF in_sosi.valid = '1' THEN - v.state := READING; ELSE - v.state := IDLE; + v.state := READING; + v.out_ready := '0'; END IF; WHEN RESET => @@ -139,27 +149,57 @@ BEGIN IF rst = '1' THEN v.state := RESET; - ELSIF in_sosi.valid = '1' AND (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + ELSE + v.state := OFF; + END IF; + + WHEN IDLE => + IF q_reg.out_ready = '1'THEN + v.out_ready := '0'; + ELSE + v.out_ready := '1'; + END IF; + + IF rst = '1' THEN + v.state := RESET; + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of >= g_in_data_w THEN v.state := FH_read; + v.inp_vect(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); + ELSIF in_sosi.valid = '1' AND q_reg.fh_done = '1' THEN + v.state := SH_READ; + v.out_ready := '0'; + v.fh_done := '0'; ELSIF in_sosi.valid = '1' THEN v.state := READING; + v.out_ready := '0'; + v.inp_vect(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); ELSE v.state := IDLE; END IF; - WHEN IDLE => - v.out_ready := '1'; + WHEN OFF => + IF q_reg.out_ready = '1'THEN + v.out_ready := '0'; + ELSE + v.out_ready := '1'; + END IF; + IF rst = '1' THEN v.state := RESET; - ELSIF in_sosi.valid = '1' AND (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of >= g_in_data_w THEN v.state := FH_read; + v.a_of := in_ds; + v.inp_vect(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); ELSIF in_sosi.valid = '1' THEN v.state := READING; + v.out_ready := '0'; v.a_of := in_ds; + v.inp_vect(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); ELSE - v.state := IDLE; + v.state := OFF; END IF; + END CASE; d_reg <= v; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd index e2160cbf3cbfb6affcabfaedb694f2605b4d5f05..0132c345b549820044c4706f6283a547377f73fd 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -50,31 +50,41 @@ END tb_ddrctrl; ARCHITECTURE tb OF tb_ddrctrl IS - -- constants for testbench CONSTANT c_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation - 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*576)/168; -- amount of input words that get put into the DUT -- 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); - -- 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 + -- 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 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; + + -- 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); -- removes a warning BEGIN - FOR I IN 0 TO c_sim_length*g_nof_streams-1 LOOP + FOR I IN 0 TO c_sim_length-1 LOOP conv := TO_UVEC(I, 32); - temp(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := conv(g_data_w-1 DOWNTO 0); + FOR J IN 0 TO g_nof_streams-1 LOOP + temp(g_data_w*((I*g_nof_streams)+J+1)-1 DOWNTO g_data_w*((I*g_nof_streams)+j)) := conv(g_data_w-1 DOWNTO 0); + END LOOP; END LOOP; RETURN temp; END FUNCTION c_total_vector_init; @@ -93,7 +103,6 @@ ARCHITECTURE tb OF tb_ddrctrl IS SIGNAL mm_clk : STD_LOGIC := '0'; SIGNAL mm_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; SIGNAL stop_in : STD_LOGIC := '0'; SIGNAL bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); @@ -105,12 +114,16 @@ ARCHITECTURE tb OF tb_ddrctrl IS 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 + -- signals for checking the output data + SIGNAL output_data_cnt : NATURAL := 0; + -- 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 @@ -133,7 +146,6 @@ BEGIN rst <= '0'; mm_rst <= '0'; test_running <= '1'; - wr_not_rd <= '1'; WAIT FOR c_clk_period*1; @@ -146,16 +158,15 @@ BEGIN END LOOP; in_sosi_arr(0).bsn(c_dp_stream_bsn_w-1 DOWNTO 0) <= bsn(c_dp_stream_bsn_w-1 DOWNTO 0); bsn <= INCR_UVEC(bsn, 1); + IF K = 1 AND J = 0 THEN + stop_in <= '1'; + ELSE + stop_in <= '0'; + END IF; WAIT FOR c_clk_period*1; END LOOP; - IF k = 1 THEN - stop_in <= '1'; - ELSE - stop_in <= '0'; - END IF; END LOOP; test_running <= '0'; - wr_not_rd <= '0'; -- stopping the testbench @@ -164,6 +175,22 @@ BEGIN ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; + p_checking_output_data : PROCESS + BEGIN + WAIT UNTIL rising_edge(clk); + IF out_sosi_arr(0).valid = '1' THEN + --assert false report "checking" severity note; + FOR I IN 0 TO g_nof_streams-1 LOOP + IF c_output_stop_adr+output_data_cnt <= c_max_adr THEN + ASSERT out_sosi_arr(I).data(c_in_data_w-1 DOWNTO 0) = c_total_vector(g_data_w*(I+1)+(c_output_stop_adr+output_data_cnt)*c_ctrl_data_w-1 DOWNTO g_data_w*I+(c_output_stop_adr+output_data_cnt)*c_ctrl_data_w) REPORT "wrong output data at: " & NATURAL'image(c_output_stop_adr+output_data_cnt) SEVERITY ERROR; + ELSE + ASSERT out_sosi_arr(I).data(c_in_data_w-1 DOWNTO 0) = c_total_vector(g_data_w*(I+1)+(c_output_stop_adr+output_data_cnt-c_max_adr)*c_ctrl_data_w-1 DOWNTO g_data_w*I+(c_output_stop_adr+output_data_cnt-c_max_adr)*c_ctrl_data_w) REPORT "wrong output data at: " & NATURAL'image(c_output_stop_adr+output_data_cnt) SEVERITY ERROR; + END IF; + END LOOP; + output_data_cnt <= output_data_cnt+1; + END IF; + WAIT FOR c_clk_period*1; + END PROCESS; @@ -183,7 +210,6 @@ BEGIN mm_clk => mm_clk, mm_rst => mm_rst, in_sosi_arr => in_sosi_arr, - wr_not_rd => wr_not_rd, stop_in => stop_in, out_sosi_arr => out_sosi_arr,