diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 49811810201ec2f9fdc82d583e57fe3355bda0ec..b36341d13bbe15efec73325da5db95dd0be947ee 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -263,6 +263,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_fifo_sc.vhd tb/vhdl/tb_tb_dp_fifo_fill.vhd tb/vhdl/tb_tb_dp_fifo_fill_sc.vhd + tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd tb/vhdl/tb_tb_dp_fifo_dc.vhd tb/vhdl/tb_tb_dp_fifo_dc_mixed_widths.vhd tb/vhdl/tb_tb_dp_frame_scheduler.vhd @@ -318,6 +319,7 @@ regression_test_vhdl = tb/vhdl/tb_tb_dp_fifo_dc_mixed_widths.vhd tb/vhdl/tb_tb_dp_fifo_fill.vhd tb/vhdl/tb_tb_dp_fifo_fill_sc.vhd + tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd tb/vhdl/tb_tb_dp_fifo_info.vhd tb/vhdl/tb_tb_dp_fifo_sc.vhd tb/vhdl/tb_tb_dp_flush.vhd diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd index 47427a6d14f68477f41b1c7e7407a1183427be71..955bb5968ff5487340784c8025c9f4f5c1667e7e 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd @@ -119,18 +119,24 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS SIGNAL i_src_out : t_dp_sosi; SIGNAL nxt_src_out : t_dp_sosi; + -- EOP clock domain crossing signals + SIGNAL reg_wr_eop_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL reg_rd_eop_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL wr_eop_done : STD_LOGIC; + SIGNAL wr_eop_new : STD_LOGIC; + SIGNAL rd_eop_new : STD_LOGIC; + SIGNAL wr_eop_busy : STD_LOGIC; + SIGNAL wr_eop_cnt : NATURAL := 0; + SIGNAL rd_eop_cnt : NATURAL := 0; + + -- EOP count can be negative when a packet is sent out without having received the eop. This can be the case when g_fifo_fill has been reached. + SIGNAL eop_cnt : INTEGER := 0; + SIGNAL nxt_eop_cnt : INTEGER := 0; + -- Signals for g_fifo_rl=1 SIGNAL hold_src_in : t_dp_siso; SIGNAL pend_src_out : t_dp_sosi; - - SIGNAL received_eop : BOOLEAN := FALSE; - SIGNAL nxt_received_eop : BOOLEAN := FALSE; - SIGNAL expecting_eop : BOOLEAN := FALSE; - SIGNAL nxt_expecting_eop : BOOLEAN := FALSE; - SIGNAL common_spulse_clken : STD_LOGIC_VECTOR(c_nof_spulse DOWNTO 0) := (OTHERS => '1'); - SIGNAL common_spulse_out_pulse : STD_LOGIC_VECTOR(c_nof_spulse-1 DOWNTO 0); - SIGNAL common_spulse_busy : STD_LOGIC_VECTOR(c_nof_spulse-1 DOWNTO 0); - SIGNAL crossed_domain_snk_in_eop : STD_LOGIC := '0'; + BEGIN -- Output monitor FIFO filling @@ -144,7 +150,6 @@ BEGIN rd_fill_ctrl <= rd_fill_32b(c_fifo_size_w-1 DOWNTO 0); gen_dp_fifo_sc : IF g_use_dual_clock=FALSE GENERATE - crossed_domain_snk_in_eop <= snk_in.eop; -- No need to transfer eop across clock domains u_dp_fifo_sc : ENTITY work.dp_fifo_sc GENERIC MAP ( g_technology => g_technology, @@ -180,26 +185,27 @@ BEGIN ); wr_fifo_usedw <= rd_fifo_usedw; + + -- No need to transfer eop counter across clock domains + rd_eop_cnt <= wr_eop_cnt; + rd_eop_new <= '1'; + p_sc: PROCESS(wr_clk, wr_rst) + BEGIN + IF wr_rst='1' THEN + wr_eop_cnt <= 0; + ELSIF rising_edge(wr_clk) THEN + IF snk_in.eop = '1' THEN + wr_eop_cnt <= 1; + ELSE + wr_eop_cnt <= 0; + END IF; + END IF; + END PROCESS; + + END GENERATE; gen_dp_fifo_dc : IF g_use_dual_clock=TRUE GENERATE - -- Transfer eop across clock domain - crossed_domain_snk_in_eop <= vector_or(common_spulse_out_pulse); - gen_spulse : FOR I IN 0 TO c_nof_spulse-1 GENERATE - common_spulse_clken(I+1) <= vector_and(common_spulse_busy(I DOWNTO 0)); - u_common_spulse : ENTITY common_lib.common_spulse - PORT MAP ( - in_rst => wr_rst, - in_clk => wr_clk, - in_clken => common_spulse_clken(I), - in_pulse => snk_in.eop, - in_busy => common_spulse_busy(I), - out_rst => rd_rst, - out_clk => rd_clk, - out_pulse => common_spulse_out_pulse(I) - ); - END GENERATE; - u_dp_fifo_dc : ENTITY work.dp_fifo_dc GENERIC MAP ( g_technology => g_technology, @@ -236,6 +242,52 @@ BEGIN src_in => rd_siso, -- for RL = 0 rd_siso.ready acts as read acknowledge, -- for RL = 1 rd_siso.ready acts as read request src_out => rd_sosi ); + + -- Transfer eop counter across clock domains + reg_wr_eop_cnt <= TO_UVEC(wr_eop_cnt, c_word_w); + rd_eop_cnt <= TO_UINT(reg_rd_eop_cnt); + u_common_reg_cross_domain : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => wr_rst, + in_clk => wr_clk, + in_dat => reg_wr_eop_cnt, + in_new => wr_eop_new, + in_done => wr_eop_done, + out_rst => rd_rst, + out_clk => rd_clk, + out_dat => reg_rd_eop_cnt, + out_new => rd_eop_new + ); + + p_dc: PROCESS(wr_clk, wr_rst) + VARIABLE v_wr_eop_cnt: NATURAL; + BEGIN + IF wr_rst='1' THEN + wr_eop_busy <= '0'; + wr_eop_cnt <= 0; + wr_eop_new <= '0'; + ELSIF rising_edge(wr_clk) THEN + v_wr_eop_cnt := wr_eop_cnt; + IF wr_eop_done = '1' THEN + wr_eop_busy <= '0'; + END IF; + + IF wr_eop_busy = '0' THEN + wr_eop_busy <= '1'; + wr_eop_new <= '1'; + END IF; + + IF wr_eop_new = '1' THEN + wr_eop_new <= '0'; + v_wr_eop_cnt := 0; + END IF; + + IF snk_in.eop = '1' THEN + v_wr_eop_cnt := v_wr_eop_cnt + 1; + END IF; + wr_eop_cnt <= v_wr_eop_cnt; + END IF; + END PROCESS; END GENERATE; no_fill : IF g_fifo_fill=0 GENERATE @@ -246,40 +298,28 @@ BEGIN gen_fill : IF g_fifo_fill>0 GENERATE src_out <= i_src_out; - + p_rd_clk: PROCESS(rd_clk, rd_rst) BEGIN IF rd_rst='1' THEN xon_reg <= '0'; state <= s_idle; i_src_out <= c_dp_sosi_rst; - received_eop <= FALSE; - expecting_eop <= FALSE; + eop_cnt <= 0; ELSIF rising_edge(rd_clk) THEN xon_reg <= nxt_xon_reg; state <= nxt_state; i_src_out <= nxt_src_out; - IF crossed_domain_snk_in_eop = '1' THEN - IF expecting_eop THEN - expecting_eop <= FALSE; - ELSE - received_eop <= TRUE; - END IF; - ELSE - expecting_eop <= nxt_expecting_eop; - received_eop <= nxt_received_eop; - END IF; + eop_cnt <= nxt_eop_cnt; END IF; END PROCESS; - + nxt_xon_reg <= src_in.xon; -- register xon to easy timing closure gen_rl_0 : IF g_fifo_rl=0 GENERATE - p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop, expecting_eop) + p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, rd_eop_cnt, eop_cnt, rd_eop_new) BEGIN nxt_state <= state; - nxt_received_eop <= received_eop; - nxt_expecting_eop <= expecting_eop; rd_siso <= src_in; -- default acknowledge (RL=1) this input when output is ready -- The output register stage increase RL=0 to 1, so it matches RL = 1 for src_in.ready @@ -288,6 +328,10 @@ BEGIN nxt_src_out.sop <= '0'; nxt_src_out.eop <= '0'; nxt_src_out.sync <= '0'; + nxt_eop_cnt <= eop_cnt; + IF rd_eop_new = '1' THEN + nxt_eop_cnt <= eop_cnt + rd_eop_cnt; + END IF; CASE state IS WHEN s_idle => @@ -307,17 +351,17 @@ BEGIN nxt_state <= s_xoff; ELSE -- stop reading until the FIFO has been filled sufficiently - IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND NOT received_eop THEN + IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND eop_cnt <= 0 THEN rd_siso <= c_dp_siso_hold; -- stop the input, hold the pend_src_out.sop ELSE -- if the output is ready, then start outputting the frame IF src_in.ready='1' THEN nxt_src_out <= rd_sosi; -- output sop that is still at FIFO output (RL=0) nxt_state <= s_output; - IF received_eop THEN - nxt_received_eop <= FALSE; + IF rd_eop_new = '1' THEN + nxt_eop_cnt <= eop_cnt + rd_eop_cnt - 1; ELSE - nxt_expecting_eop <= TRUE; + nxt_eop_cnt <= eop_cnt -1; END IF; END IF; END IF; @@ -361,11 +405,9 @@ BEGIN src_out_reg => i_src_out ); - p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop, expecting_eop) + p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, rd_eop_cnt, eop_cnt, rd_eop_new) BEGIN nxt_state <= state; - nxt_received_eop <= received_eop; - nxt_expecting_eop <= expecting_eop; hold_src_in <= src_in; -- default request (RL=1) new input when output is ready @@ -375,6 +417,10 @@ BEGIN nxt_src_out.sop <= '0'; nxt_src_out.eop <= '0'; nxt_src_out.sync <= '0'; + nxt_eop_cnt <= eop_cnt; + IF rd_eop_new = '1' THEN + nxt_eop_cnt <= eop_cnt + rd_eop_cnt; + END IF; CASE state IS WHEN s_idle => @@ -394,17 +440,17 @@ BEGIN nxt_state <= s_xoff; ELSE -- stop reading until the FIFO has been filled sufficiently - IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND NOT received_eop THEN + IF UNSIGNED(rd_fifo_usedw)<UNSIGNED(rd_fill_ctrl) AND eop_cnt <= 0 THEN hold_src_in <= c_dp_siso_hold; -- stop the input, hold the pend_src_out.sop ELSE -- if the output is ready, then start outputting the input frame IF src_in.ready='1' THEN nxt_src_out <= pend_src_out; -- output sop that is still pending in dp_hold_input nxt_state <= s_output; - IF received_eop THEN - nxt_received_eop <= FALSE; + IF rd_eop_new = '1' THEN + nxt_eop_cnt <= eop_cnt + rd_eop_cnt - 1; ELSE - nxt_expecting_eop <= TRUE; + nxt_eop_cnt <= eop_cnt -1; END IF; END IF; END IF; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd b/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd index b13ef2a3a54f8fb66878f9347c5d32a808c71717..f4cdef3d2f04a248b6adc1ec808472daa621080e 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd @@ -47,6 +47,7 @@ USE work.tb_dp_pkg.ALL; ENTITY tb_dp_fifo_fill_eop IS GENERIC ( -- Try FIFO settings + g_dut_use_dual_clock : BOOLEAN := TRUE; g_dut_use_bsn : BOOLEAN := FALSE; g_dut_use_empty : BOOLEAN := FALSE; g_dut_use_channel : BOOLEAN := FALSE; @@ -54,7 +55,7 @@ ENTITY tb_dp_fifo_fill_eop IS g_dut_fifo_rl : NATURAL := 1; -- internal RL, use 0 for look ahead FIFO, default 1 for normal FIFO g_dut_fifo_size : NATURAL := 128; g_dut_fifo_fill : NATURAL := 100; -- selectable >= 0 for dp_fifo_fill - g_dut_use_rd_fill_32b : BOOLEAN := False + g_dut_use_rd_fill_32b : BOOLEAN := FALSE ); END tb_dp_fifo_fill_eop; @@ -131,7 +132,7 @@ ARCHITECTURE tb OF tb_dp_fifo_fill_eop IS SIGNAL out_val : STD_LOGIC; SIGNAL out_sop : STD_LOGIC; SIGNAL out_eop : STD_LOGIC; - SIGNAL prev_out_data : STD_LOGIC_VECTOR(out_data'RANGE); + SIGNAL prev_out_data : STD_LOGIC_VECTOR(out_data'RANGE) := (OTHERS=>'0'); SIGNAL state : t_dp_state_enum; @@ -204,22 +205,14 @@ BEGIN proc_dp_verify_value(e_at_least, clk, verify_done, exp_data, out_data); -- Verify fill level - p_verify_fifo_fill : PROCESS + p_tb_end : PROCESS BEGIN IF g_dut_fifo_fill>0 THEN -- Use rd_fill_32b /= g_dut_fifo_fill to verify dynamic control IF g_dut_use_rd_fill_32b=TRUE THEN rd_fill_32b <= TO_UVEC(g_dut_fifo_size/5, c_word_w); END IF; - - -- Check fill level at first output - proc_common_wait_until_high(clk, out_val); - ASSERT UNSIGNED(rd_usedw)=UNSIGNED(rd_fill_32b) REPORT "Usedw is not equal to fill level at start" SEVERITY ERROR; - - -- Check fill level after last output (account for block length given by c_tx_period_sop) - proc_common_wait_until_high(clk, verify_done); - proc_common_wait_some_cycles(clk, g_dut_fifo_size); - ASSERT UNSIGNED(rd_usedw)>=UNSIGNED(rd_fill_32b)-c_tx_period_sop REPORT "Usedw does not match fill level at end" SEVERITY ERROR; + END IF; proc_common_wait_until_high(clk, tb_done); @@ -255,19 +248,20 @@ BEGIN dut : ENTITY work.dp_fifo_fill_eop GENERIC MAP ( - g_data_w => c_dp_data_w, - g_bsn_w => c_dp_bsn_w, - g_empty_w => c_dp_empty_w, - g_channel_w => c_dp_channel_w, - g_error_w => 1, - g_use_bsn => g_dut_use_bsn, - g_use_empty => g_dut_use_empty, - g_use_channel => g_dut_use_channel, - g_use_error => FALSE, - g_use_sync => g_dut_use_sync, - g_fifo_fill => g_dut_fifo_fill, - g_fifo_size => g_dut_fifo_size, - g_fifo_rl => g_dut_fifo_rl + g_use_dual_clock => g_dut_use_dual_clock, + g_data_w => c_dp_data_w, + g_bsn_w => c_dp_bsn_w, + g_empty_w => c_dp_empty_w, + g_channel_w => c_dp_channel_w, + g_error_w => 1, + g_use_bsn => g_dut_use_bsn, + g_use_empty => g_dut_use_empty, + g_use_channel => g_dut_use_channel, + g_use_error => FALSE, + g_use_sync => g_dut_use_sync, + g_fifo_fill => g_dut_fifo_fill, + g_fifo_size => g_dut_fifo_size, + g_fifo_rl => g_dut_fifo_rl ) PORT MAP ( rd_rst => rst, diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f4b4106cbc87fedc54cf9fafefc95f3ee48d8af9 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd @@ -0,0 +1,52 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- 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: R. van der Walle + +-- Purpose: +-- Multi test bench for dp_fifo_fill_eop +-- Description: +-- Runs two tb_dp_fifo_fill_eop testbenches, one for single clock and one for +-- dual clock. +-- Remark: +-- Usage: +-- > as 10 +-- > run -all +-- . signal tb_end will stop the simulation by stopping the clk +-- . the tb is self checking +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + + +ENTITY tb_tb_dp_fifo_fill_eop IS +END tb_tb_dp_fifo_fill_eop; + + +ARCHITECTURE tb OF tb_tb_dp_fifo_fill_eop IS + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' +BEGIN + -- Try FIFO settings : GENERIC MAP (g_dut_use_dual_clock, g_dut_use_bsn, g_dut_use_empty, g_dut_use_channel, g_dut_use_sync, g_dut_fifo_rl, g_dut_fifo_size, g_dut_fifo_fill, g_dut_use_rd_fill_32b) + u_dut_sc : ENTITY work.tb_dp_fifo_fill_eop GENERIC MAP (g_dut_use_dual_clock => FALSE); + u_dut_dc : ENTITY work.tb_dp_fifo_fill_eop GENERIC MAP (g_dut_use_dual_clock => TRUE); + +END tb; diff --git a/libraries/io/fpga_sense/src/vhdl/fpga_sense.vhd b/libraries/io/fpga_sense/src/vhdl/fpga_sense.vhd index aeb5774000abc8e4b1c21b6e9d7a8c2b9d8fcbc9..a03a8b77815e3eaf75827c842d94e0193119c9db 100644 --- a/libraries/io/fpga_sense/src/vhdl/fpga_sense.vhd +++ b/libraries/io/fpga_sense/src/vhdl/fpga_sense.vhd @@ -169,7 +169,7 @@ BEGIN sample_store_irq_irq => open ); - PROCESS(eoc, mm_rst) + PROCESS(mm_clk, mm_rst) BEGIN IF mm_rst = '1' THEN controller_csr_write <= '0'; diff --git a/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd b/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd index 9ecaa256899c7fbafa32bf0ad8754e4b09ea9bb4..035afc0814a95683106888cdb0aa4e5d4371c9cc 100644 --- a/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd +++ b/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd @@ -95,7 +95,7 @@ ARCHITECTURE rtl of nw_ping_response IS BEGIN -- Combinational Process - p_comb : PROCESS(r, rst, snk_in, dp_pipeline_src_out, dp_fifo_sc_rd_emp) + p_comb : PROCESS(r, rst, snk_in, dp_pipeline_src_out, dp_fifo_sc_rd_emp, eth_src_mac) VARIABLE v : t_reg; BEGIN v := r; diff --git a/libraries/io/tr_10GbE/src/vhdl/tr_10GbE_ip_checksum.vhd b/libraries/io/tr_10GbE/src/vhdl/tr_10GbE_ip_checksum.vhd index 13ff5211de7fc90eeaff0e190c3d2cc142c46a0d..63fd88d4c78c36a5d3417418a6e3be8289119861 100644 --- a/libraries/io/tr_10GbE/src/vhdl/tr_10GbE_ip_checksum.vhd +++ b/libraries/io/tr_10GbE/src/vhdl/tr_10GbE_ip_checksum.vhd @@ -64,7 +64,7 @@ BEGIN ------------------------------------------------- -- process to calculate the ip_header_checksum -- ------------------------------------------------- - p_calc_chksum : PROCESS(clk) + p_calc_chksum : PROCESS(clk, rst) BEGIN IF rst = '1' THEN sum <= (OTHERS => '0'); @@ -99,7 +99,7 @@ BEGIN -- process to insert checksum in outgoing stream -- --------------------------------------------------- checksum <= NOT(STD_LOGIC_VECTOR(sum(c_halfword_w-1 DOWNTO 0)+sum(sum'HIGH DOWNTO c_halfword_w))); -- checksum = inverted (sum + carry) - p_insert_chksum : PROCESS(dp_pipeline_src_out, checksum, count) + p_insert_chksum : PROCESS(dp_pipeline_src_out, checksum, count_p) BEGIN src_out <= dp_pipeline_src_out; IF TO_UINT(count_p) = 2 THEN