An error occurred while loading code owners.
-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ring_rx.vhd 8.76 KiB
-------------------------------------------------------------------------------
--
-- Copyright 2021
-- 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: Handle RX side of ring design.
-- Description: See https://support.astron.nl/confluence/x/jyu7Ag
-------------------------------------------------------------------------------
library IEEE, common_lib, mm_lib, dp_lib;
use IEEE.std_logic_1164.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.all;
use common_lib.common_field_pkg.all;
use dp_lib.dp_stream_pkg.all;
use work.ring_pkg.all;
entity ring_rx is
generic (
g_use_dp_layer : boolean := true;
g_lane_direction : natural := 1;
g_total_nof_packets_w : natural := 48; -- <= c_longword_w = 64
g_data_w : natural := 64;
g_nof_rx_monitors : natural := 1;
g_err_bi : natural := 0;
g_block_size : natural := 1024;
g_nof_err_counts : natural := 1;
g_check_channel : natural := 1;
g_sync_timeout : natural := 220 * 10**6 -- 10% margin
);
port (
-- Clocks and reset
mm_rst : in std_logic; -- reset synchronous with mm_clk
mm_clk : in std_logic; -- memory-mapped bus clock
dp_clk : in std_logic;
dp_rst : in std_logic;
from_lane_sosi : out t_dp_sosi;
lane_rx_cable_sosi : in t_dp_sosi;
lane_rx_board_sosi : in t_dp_sosi;
bs_sosi : in t_dp_sosi;
reg_bsn_monitor_v2_copi : in t_mem_copi;
reg_bsn_monitor_v2_cipo : out t_mem_cipo;
reg_dp_block_validate_err_copi : in t_mem_copi;
reg_dp_block_validate_err_cipo : out t_mem_cipo;
reg_dp_block_validate_bsn_at_sync_copi : in t_mem_copi;
reg_dp_block_validate_bsn_at_sync_cipo : out t_mem_cipo;
ref_sync : in std_logic;
rx_select : in std_logic;
this_rn : in std_logic_vector(c_byte_w - 1 downto 0);
N_rn : in std_logic_vector(c_byte_w - 1 downto 0)
);
end ring_rx;
architecture str of ring_rx is
constant c_nof_hdr_fields : natural := sel_a_b(g_use_dp_layer, c_ring_dp_nof_hdr_fields, c_ring_eth_nof_hdr_fields);
constant c_hdr_field_arr : t_common_field_arr(c_nof_hdr_fields - 1 downto 0) := sel_a_b(g_use_dp_layer, c_ring_dp_hdr_field_arr, c_ring_eth_hdr_field_arr);
constant c_hdr_field_size : natural := sel_a_b(g_use_dp_layer, c_ring_dp_hdr_field_size, c_ring_eth_hdr_field_size);
constant c_packet_size : natural := g_block_size + c_hdr_field_size;
signal lane_rx_sosi : t_dp_sosi;
signal packet_sosi : t_dp_sosi;
signal validated_sosi : t_dp_sosi;
signal offload_rx_sosi : t_dp_sosi;
signal decoded_sosi : t_dp_sosi;
signal monitor_sosi : t_dp_sosi;
signal piped_monitor_sosi : t_dp_sosi;
signal demux_sosi_arr : t_dp_sosi_arr(0 to g_nof_rx_monitors - 1); -- using 0 TO ... as that is the output of the demux
signal monitor_sosi_arr : t_dp_sosi_arr(g_nof_rx_monitors - 1 downto 0);
signal hdr_fields_out : std_logic_vector(1023 downto 0);
signal hdr_fields_raw : std_logic_vector(1023 downto 0);
begin
-- Select input based on rx_select
lane_rx_sosi <= lane_rx_cable_sosi when rx_select = '1' else lane_rx_board_sosi;
-- Validate length
u_dp_block_validate_length : entity dp_lib.dp_block_validate_length
generic map (
g_err_bi => g_err_bi,
g_expected_length => c_packet_size
)
port map (
rst => dp_rst,
clk => dp_clk,
snk_in => lane_rx_sosi,
src_out => packet_sosi
);
-- Validate error field
-- . Use ref_sync as capture moment for the running MM total counts in dp_block_validate_err.
-- The rx_packet_sosi does not have rx_packet_sosi.sync, because it carries encoded packets
-- and because the rx_packet_sosi can carry packets from multiple sources (so multiple sync
-- intervals multiplexed on one lane).
u_dp_block_validate_err : entity dp_lib.dp_block_validate_err
generic map (
g_cnt_w => c_word_w, -- <= c_word_w = 32
g_blk_cnt_w => g_total_nof_packets_w, -- <= c_longword_w = 64
g_max_block_size => c_packet_size,
g_min_block_size => c_packet_size,
g_nof_err_counts => g_nof_err_counts,
g_fifo_note_is_ful=> false, -- use false, because g_fifo_size = c_packet_size
g_fifo_size => c_packet_size, -- can be same as g_max_block_size as src_in.ready = '1'
g_use_sync => false, -- no need to pass on ref_sync
g_data_w => g_data_w
)
port map (
dp_rst => dp_rst,
dp_clk => dp_clk,
ref_sync => ref_sync,
snk_in => packet_sosi,
src_out => validated_sosi,
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_dp_block_validate_err_copi,
reg_miso => reg_dp_block_validate_err_cipo
);
-- Removing ETH/DP header
u_dp_offload_rx: entity dp_lib.dp_offload_rx
generic map (
g_nof_streams => 1,
g_data_w => g_data_w,
g_hdr_field_arr => c_hdr_field_arr
)
port map (
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
snk_in_arr(0) => validated_sosi,
src_out_arr(0) => offload_rx_sosi,
hdr_fields_out_arr(0) => hdr_fields_out,
hdr_fields_raw_arr(0) => hdr_fields_raw
);
-- Use dp layer
gen_dp_layer : if g_use_dp_layer generate
p_set_meta: process(offload_rx_sosi, hdr_fields_out, hdr_fields_raw)
begin
decoded_sosi <= offload_rx_sosi;
decoded_sosi.sync <= sl(hdr_fields_out(field_hi(c_hdr_field_arr, "dp_sync" ) downto field_lo(c_hdr_field_arr, "dp_sync" )));
decoded_sosi.bsn <= RESIZE_DP_BSN( hdr_fields_raw(field_hi(c_hdr_field_arr, "dp_bsn" ) downto field_lo(c_hdr_field_arr, "dp_bsn" )));
decoded_sosi.channel <= RESIZE_DP_CHANNEL(hdr_fields_raw(field_hi(c_hdr_field_arr, "dp_channel" ) downto field_lo(c_hdr_field_arr, "dp_channel" )));
end process;
-- Validate bsn at sync
u_dp_block_validate_bsn_at_sync : entity dp_lib.dp_block_validate_bsn_at_sync
generic map (
g_check_channel => g_check_channel
)
port map (
dp_rst => dp_rst,
dp_clk => dp_clk,
in_sosi => decoded_sosi,
bs_sosi => bs_sosi,
out_sosi => from_lane_sosi,
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_dp_block_validate_bsn_at_sync_copi,
reg_miso => reg_dp_block_validate_bsn_at_sync_cipo
);
-- Convert nof_hops to source RN
p_hop_to_src_rn: process(dp_rst, dp_clk)
begin
if dp_rst = '1' then
monitor_sosi <= c_dp_sosi_rst;
piped_monitor_sosi <= c_dp_sosi_rst;
elsif rising_edge(dp_clk) then
-- Pipe monitor sosi to ease timing.
piped_monitor_sosi <= monitor_sosi;
-- Convert nof_hops to source RN
monitor_sosi <= decoded_sosi;
monitor_sosi.channel <= func_ring_nof_hops_to_source_rn(decoded_sosi.channel, this_rn, N_rn, g_lane_direction);
end if;
end process;
u_dp_demux : entity dp_lib.dp_demux
generic map (
g_nof_output => g_nof_rx_monitors
)
port map (
rst => dp_rst,
clk => dp_clk,
snk_in => piped_monitor_sosi,
src_out_arr => demux_sosi_arr
);
monitor_sosi_arr <= func_dp_stream_arr_reverse_range(demux_sosi_arr); -- Fix reversed bus.
-- BSN Monitors
u_mms_dp_bsn_monitor_v2 : entity dp_lib.mms_dp_bsn_monitor_v2
generic map (
g_nof_streams => g_nof_rx_monitors,
g_sync_timeout => g_sync_timeout
)
port map (
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_bsn_monitor_v2_copi,
reg_miso => reg_bsn_monitor_v2_cipo,
dp_rst => dp_rst,
dp_clk => dp_clk,
in_sosi_arr => monitor_sosi_arr,
ref_sync => ref_sync
);
end generate;
-- Do not use dp layer
gen_no_dp_layer : if not g_use_dp_layer generate
from_lane_sosi <= offload_rx_sosi;
end generate;
end str;