Skip to content
Snippets Groups Projects
Commit 43f73ca0 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Merge branch 'L2SDP-275' into 'master'

Resolve L2SDP-275

Closes L2SDP-275

See merge request desp/hdl!129
parents 843157e5 09cc2f76
No related branches found
No related tags found
1 merge request!129Resolve L2SDP-275
......@@ -23,12 +23,12 @@
-- Purpose:
-- The dp_block_validate_channel.vhd can remove a block of data from a
-- multiplexed in_sosi stream based on the in_sosi.channel field.
-- If in_sosi.channel = g_remove_channel, then the in_sosi is passed on to
-- If in_sosi.channel = remove_channel, then the in_sosi is passed on to
-- remove_sosi and not passed on to keep_sosi, else vice versa.
-- Other modes can be selected by setting g_mode. g_mode options are:
-- . "=" which removes all blocks with channel = g_remove_channel
-- . "<" which removes all blocks with channel < g_remove_channel
-- . ">" which removes all blocks with channel > g_remove_channel
-- . "=" which removes all blocks with channel = remove_channel
-- . "<" which removes all blocks with channel < remove_channel
-- . ">" which removes all blocks with channel > remove_channel
-- Remarks:
LIBRARY IEEE, common_lib;
......@@ -40,7 +40,6 @@ USE common_lib.common_mem_pkg.ALL;
ENTITY dp_block_validate_channel IS
GENERIC (
g_remove_channel : NATURAL := 0;
g_mode : STRING := "=" -- can be "=", "<", ">"
);
PORT (
......@@ -50,7 +49,9 @@ ENTITY dp_block_validate_channel IS
in_sosi : IN t_dp_sosi;
-- ST source
out_keep_sosi : OUT t_dp_sosi;
out_remove_sosi : OUT t_dp_sosi
out_remove_sosi : OUT t_dp_sosi;
remove_channel : IN STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0)
);
END dp_block_validate_channel;
......@@ -65,17 +66,17 @@ ARCHITECTURE rtl OF dp_block_validate_channel IS
BEGIN
ASSERT g_mode = "=" OR g_mode = "<" OR g_mode = ">" REPORT "g_mode must be one of three options: '=', '<' or '>'" SEVERITY ERROR;
gen_equal : IF g_mode = "=" GENERATE -- remove all blocks with ch = g_remove_channel
gen_equal : IF g_mode = "=" GENERATE -- remove all blocks with ch = remove_channel
remove_blk <= remove_blk_reg WHEN in_sosi.sop = '0' ELSE
'1' WHEN TO_UINT(in_sosi.channel) = g_remove_channel ELSE '0';
'1' WHEN UNSIGNED(in_sosi.channel) = UNSIGNED(remove_channel) ELSE '0';
END GENERATE;
gen_smaller : IF g_mode = "<" GENERATE -- remove all blocks with ch < g_remove_channel
gen_smaller : IF g_mode = "<" GENERATE -- remove all blocks with ch < remove_channel
remove_blk <= remove_blk_reg WHEN in_sosi.sop = '0' ELSE
'1' WHEN TO_UINT(in_sosi.channel) < g_remove_channel ELSE '0';
'1' WHEN UNSIGNED(in_sosi.channel) < UNSIGNED(remove_channel) ELSE '0';
END GENERATE;
gen_larger : IF g_mode = ">" GENERATE -- remove all blocks with ch > g_remove_channel
gen_larger : IF g_mode = ">" GENERATE -- remove all blocks with ch > remove_channel
remove_blk <= remove_blk_reg WHEN in_sosi.sop = '0' ELSE
'1' WHEN TO_UINT(in_sosi.channel) > g_remove_channel ELSE '0';
'1' WHEN UNSIGNED(in_sosi.channel) > UNSIGNED(remove_channel) ELSE '0';
END GENERATE;
p_dp_clk : PROCESS(dp_rst, dp_clk)
......
......@@ -265,6 +265,7 @@ PACKAGE dp_stream_pkg Is
FUNCTION INCR_DP_SDATA( vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- signed vec(w-1:0) + dec
FUNCTION INCR_DP_DSP_DATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- signed vec(w-1:0) + dec
FUNCTION INCR_DP_BSN( vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- unsigned vec(w-1:0) + dec
FUNCTION INCR_DP_CHANNEL( vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- unsigned vec(w-1:0) + dec
FUNCTION REPLICATE_DP_DATA( seq : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; -- replicate seq as often as fits in c_dp_stream_data_w
FUNCTION UNREPLICATE_DP_DATA(data : STD_LOGIC_VECTOR; seq_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- unreplicate data to width seq_w, return low seq_w bits and set mismatch MSbits bits to '1'
......@@ -579,6 +580,12 @@ PACKAGE BODY dp_stream_pkg IS
RETURN RESIZE_DP_BSN(STD_LOGIC_VECTOR(UNSIGNED(vec(w-1 DOWNTO 0)) + dec));
END INCR_DP_BSN;
FUNCTION INCR_DP_CHANNEL(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN RESIZE_DP_CHANNEL(STD_LOGIC_VECTOR(UNSIGNED(vec(w-1 DOWNTO 0)) + dec));
END INCR_DP_CHANNEL;
FUNCTION REPLICATE_DP_DATA(seq : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
CONSTANT c_seq_w : NATURAL := seq'LENGTH;
CONSTANT c_nof_replications : NATURAL := ceil_div(c_dp_stream_data_w, c_seq_w);
......
......@@ -113,7 +113,6 @@ BEGIN
------------------------------------------------------------------------------
u_dut : ENTITY work.dp_block_validate_channel
GENERIC MAP (
g_remove_channel => g_remove_channel,
g_mode => g_mode
)
PORT MAP (
......@@ -124,7 +123,9 @@ BEGIN
in_sosi => stimuli_sosi,
-- ST source
out_keep_sosi => keep_sosi,
out_remove_sosi => remove_sosi
out_remove_sosi => remove_sosi,
remove_channel => TO_UVEC(g_remove_channel, 32)
);
......
......@@ -8,6 +8,7 @@ synth_files =
src/vhdl/ring_pkg.vhd
src/vhdl/ring_lane_info_reg.vhd
src/vhdl/ring_lane_info.vhd
src/vhdl/ring_tx.vhd
test_bench_files =
tb/vhdl/tb_ring_lane_info.vhd
......
......@@ -31,6 +31,7 @@ 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 common_lib.common_network_layers_pkg.ALL;
PACKAGE ring_pkg is
-- lane info, see https://support.astron.nl/confluence/x/jyu7Ag
......@@ -78,10 +79,66 @@ PACKAGE ring_pkg is
(field_name_pad("tx_select"), "RW", 1, field_default(0)),
(field_name_pad("rx_select"), "RW", 1, field_default(0)) );
CONSTANT c_ring_eth_dst_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"FFFFFFFFFFFF";
CONSTANT c_ring_eth_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"002286080000";
CONSTANT c_ring_pkt_type_bf : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FB";
CONSTANT c_ring_pkt_type_xc : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FC";
CONSTANT c_ring_pkt_type_so : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FD";
CONSTANT c_ring_pkt_type_tb : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FE";
CONSTANT c_ring_eth_nof_hdr_fields : NATURAL := 3;
CONSTANT c_ring_eth_hdr_field_sel : STD_LOGIC_VECTOR(c_ring_eth_nof_hdr_fields-1 DOWNTO 0) := "000";
CONSTANT c_ring_eth_hdr_field_arr : t_common_field_arr(c_ring_eth_nof_hdr_fields-1 DOWNTO 0) := (
( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(c_ring_eth_dst_mac) ),
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(c_ring_eth_src_mac) ),
( field_name_pad("eth_type" ), "RW", 16, field_default(0) )
);
CONSTANT c_ring_dp_nof_hdr_fields : NATURAL := 6;
CONSTANT c_ring_dp_hdr_field_sel : STD_LOGIC_VECTOR(c_ring_dp_nof_hdr_fields-1 DOWNTO 0) := "000"&"000";
CONSTANT c_ring_dp_hdr_field_arr : t_common_field_arr(c_ring_dp_nof_hdr_fields-1 DOWNTO 0) := (
( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(c_ring_eth_dst_mac) ),
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(c_ring_eth_src_mac) ),
( field_name_pad("eth_type" ), "RW", 16, field_default(0) ),
( field_name_pad("dp_channel" ), "RW", 16, field_default(0) ),
( field_name_pad("dp_sync" ), "RW", 1, field_default(0) ),
( field_name_pad("dp_bsn" ), "RW", 63, field_default(0) )
);
FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn, lane_dir : NATURAL) RETURN NATURAL;
FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn : STD_LOGIC_VECTOR; lane_dir : NATURAL) RETURN STD_LOGIC_VECTOR; -- return vector length is same as hops vector length
END PACKAGE ring_pkg;
PACKAGE BODY ring_pkg IS
FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn, lane_dir : NATURAL) RETURN NATURAL IS
VARIABLE v_source_rn : INTEGER;
VARIABLE v_source_rn_nat : NATURAL;
BEGIN
IF lane_dir > 0 THEN
v_source_rn := this_rn - hops;
ELSE
v_source_rn := this_rn + hops;
END IF;
IF v_source_rn < 0 THEN -- Cannot use MOD as N_rn is not a constant.
v_source_rn := v_source_rn + N_rn;
END IF;
IF v_source_rn > N_rn THEN
v_source_rn := v_source_rn - N_rn;
END IF;
v_source_rn_nat := v_source_rn;
RETURN v_source_rn_nat;
END;
FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn : STD_LOGIC_VECTOR; lane_dir : NATURAL) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN TO_UVEC(func_nof_hops_to_source_rn(TO_UINT(hops), TO_UINT(N_rn), TO_UINT(N_rn), lane_dir),hops'LENGTH);
END;
END ring_pkg;
-------------------------------------------------------------------------------
--
-- 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 TX side of ring design.
-- Description: See https://support.astron.nl/confluence/x/jyu7Ag
-- Remark:
-- .
-------------------------------------------------------------------------------
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_tx IS
GENERIC (
g_lane_direction : NATURAL := 1;
g_data_w : NATURAL := 64;
g_symbol_w : NATURAL := 8;
g_ring_pkt_type : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := c_ring_pkt_type_bf;
g_validate_channel : BOOLEAN := TRUE;
g_mode : STRING := ">";
g_nof_tx_monitors : NATURAL := 1
);
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;
to_lane_sosi : IN t_dp_sosi;
lane_tx_cable_sosi : OUT t_dp_sosi;
lane_tx_board_sosi : OUT t_dp_sosi;
reg_bsn_monitor_v2_mosi : IN t_mem_mosi;
reg_bsn_monitor_v2_miso : OUT t_mem_miso;
tx_select : IN STD_LOGIC;
remove_channel : IN STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0);
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_tx;
ARCHITECTURE str OF ring_tx IS
CONSTANT c_use_empty : BOOLEAN := sel_a_b(g_symbol_w = g_data_w, FALSE, TRUE);
CONSTANT c_empty_w : NATURAL := ceil_log2(g_data_w / g_symbol_w);
CONSTANT c_use_dp_layer : BOOLEAN := TRUE;
CONSTANT c_nof_hdr_fields : NATURAL := sel_a_b(c_use_dp_layer, c_ring_dp_nof_hdr_fields, c_ring_eth_nof_hdr_fields);
CONSTANT c_hdr_field_sel : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0) := sel_a_b(c_use_dp_layer, c_ring_dp_hdr_field_sel, c_ring_eth_hdr_field_sel);
CONSTANT c_hdr_field_arr : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := sel_a_b(c_use_dp_layer, c_ring_dp_hdr_field_arr, c_ring_eth_hdr_field_arr);
CONSTANT c_fifo_size : NATURAL := 5; -- Large enough to fit ETH/DP header.
SIGNAL validated_sosi : t_dp_sosi;
SIGNAL tx_sosi : t_dp_sosi;
SIGNAL tx_fifo_sosi : t_dp_sosi;
SIGNAL tx_fifo_siso : t_dp_siso;
SIGNAL lane_tx_sosi : t_dp_sosi;
SIGNAL monitor_sosi : t_dp_sosi;
SIGNAL monitor_sosi_arr : t_dp_sosi_arr(g_nof_tx_monitors-1 DOWNTO 0);
SIGNAL hdr_fields_in : STD_LOGIC_VECTOR(1023 DOWNTO 0);
SIGNAL hdr_fields_in_reg : STD_LOGIC_VECTOR(1023 DOWNTO 0);
BEGIN
-- Validate transport_nof_hops
gen_validate : IF g_validate_channel GENERATE
u_dp_block_validate_channel: ENTITY dp_lib.dp_block_validate_channel
GENERIC MAP (
g_mode => g_mode
)
PORT MAP (
dp_rst => dp_rst,
dp_clk => dp_clk,
in_sosi => to_lane_sosi,
out_keep_sosi => validated_sosi,
remove_channel => remove_channel
);
END GENERATE;
-- Don't validate transport_nof_hops
gen_no_validate : IF NOT g_validate_channel GENERATE
validated_sosi <= to_lane_sosi;
END GENERATE;
-- increase channel by 1, e.g. add 1 hop.
p_hop: PROCESS(validated_sosi)
BEGIN
tx_sosi <= validated_sosi;
IF TO_UINT(validated_sosi.channel) >= TO_UINT(N_rn)-1 THEN
tx_sosi.channel <= (OTHERS => '0');
ELSE
tx_sosi.channel <= INCR_DP_CHANNEL(validated_sosi.channel, 1, c_dp_stream_channel_w);
END IF;
END PROCESS;
-- Encode packet header
hdr_fields_in(field_hi(c_hdr_field_arr, "eth_dst_mac" ) DOWNTO field_lo(c_hdr_field_arr, "eth_dst_mac" )) <= c_ring_eth_dst_mac;
hdr_fields_in(field_hi(c_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac" )) <= c_ring_eth_src_mac;
hdr_fields_in(field_hi(c_hdr_field_arr, "eth_type" ) DOWNTO field_lo(c_hdr_field_arr, "eth_type" )) <= g_ring_pkt_type;
gen_hdr_dp : IF c_use_dp_layer GENERATE
hdr_fields_in(field_hi(c_hdr_field_arr, "dp_channel" ) DOWNTO field_lo(c_hdr_field_arr, "dp_channel" )) <= tx_sosi.channel(c_halfword_w-1 DOWNTO 0);
hdr_fields_in(field_hi(c_hdr_field_arr, "dp_sync" ) DOWNTO field_lo(c_hdr_field_arr, "dp_sync" )) <= slv(tx_sosi.sync);
hdr_fields_in(field_hi(c_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_hdr_field_arr, "dp_bsn" )) <= tx_sosi.bsn(62 DOWNTO 0);
END GENERATE;
-- Lead DP info around the FIFO via hdr_fields_in_reg, to avoid having to pass on the DP info via the FIFO, to save on block RAM.
hdr_fields_in_reg <= hdr_fields_in WHEN rising_edge(dp_clk) AND tx_sosi.sop = '1' ELSE hdr_fields_in_reg;
-- Fifo for inserting header
u_dp_fifo_sc: ENTITY dp_lib.dp_fifo_sc
GENERIC MAP (
g_data_w => g_data_w,
g_empty_w => c_empty_w,
g_use_empty => c_use_empty,
g_fifo_size => c_fifo_size
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_in => tx_sosi,
src_out => tx_fifo_sosi,
src_in => tx_fifo_siso
);
-- Inserting ETH/DP header
u_dp_offload_tx_v3: ENTITY dp_lib.dp_offload_tx_v3
GENERIC MAP (
g_nof_streams => 1,
g_data_w => g_data_w,
g_symbol_w => g_symbol_w,
g_hdr_field_arr => c_hdr_field_arr,
g_hdr_field_sel => c_hdr_field_sel
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
snk_in_arr(0) => tx_fifo_sosi,
snk_out_arr(0) => tx_fifo_siso,
src_out_arr(0) => lane_tx_sosi,
hdr_fields_in_arr(0) => hdr_fields_in_reg
);
-- Select output based on tx_select
p_sel_out : PROCESS(lane_tx_sosi, tx_select)
BEGIN
IF tx_select = '1' THEN -- transmit via cable
lane_tx_cable_sosi <= lane_tx_sosi;
lane_tx_board_sosi <= c_dp_sosi_rst;
ELSE -- transmit via board
lane_tx_cable_sosi <= c_dp_sosi_rst;
lane_tx_board_sosi <= lane_tx_sosi;
END IF;
END PROCESS;
-- BSN Monitors
gen_bsn_monitors : IF c_use_dp_layer GENERATE
-- Convert nof_hops to source RN
p_hop_to_src_rn: PROCESS(validated_sosi, this_rn, N_rn)
BEGIN
monitor_sosi <= validated_sosi;
monitor_sosi.channel <= func_nof_hops_to_source_rn(validated_sosi.channel, this_rn, N_rn, g_lane_direction);
END PROCESS;
u_dp_demux : ENTITY dp_lib.dp_demux
GENERIC MAP (
g_nof_output => g_nof_tx_monitors,
g_sel_ctrl_invert => TRUE
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_in => monitor_sosi,
src_out_arr => monitor_sosi_arr
);
u_mms_dp_bsn_monitor_v2 : ENTITY dp_lib.mms_dp_bsn_monitor_v2
GENERIC MAP (
g_nof_streams => g_nof_tx_monitors
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_bsn_monitor_v2_mosi,
reg_miso => reg_bsn_monitor_v2_miso,
dp_rst => dp_rst,
dp_clk => dp_clk,
in_sosi_arr => monitor_sosi_arr
);
END GENERATE;
END str;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment