Skip to content
Snippets Groups Projects
Commit 69667ee7 authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

Merge branch 'L2SDP-1019' into 'master'

Resolve L2SDP-1019

Closes L2SDP-1019

See merge request !391
parents 4955ffcb 4e8de5e2
No related branches found
No related tags found
1 merge request!391Resolve L2SDP-1019
Pipeline #76228 passed
hdl_lib_name = unb2c_board hdl_lib_name = unb2c_board
hdl_library_clause_name = unb2c_board_lib hdl_library_clause_name = unb2c_board_lib
hdl_lib_uses_synth = common dp ppsh i2c eth remu technology tech_clkbuf tech_pll tech_fractional_pll epcs fpga_sense hdl_lib_uses_synth = common dp ppsh i2c eth remu technology tech_clkbuf tech_pll tech_fractional_pll epcs fpga_sense
hdl_lib_uses_sim = hdl_lib_uses_sim =
hdl_lib_technology = ip_arria10_e2sg hdl_lib_technology = ip_arria10_e2sg
hdl_lib_include_ip = ip_arria10_e2sg_tse_sgmii_lvds hdl_lib_include_ip = ip_arria10_e2sg_tse_sgmii_lvds
ip_arria10_e2sg_clkbuf_global ip_arria10_e2sg_clkbuf_global
...@@ -23,18 +23,20 @@ synth_files = ...@@ -23,18 +23,20 @@ synth_files =
src/vhdl/mms_unb2c_fpga_sens.vhd src/vhdl/mms_unb2c_fpga_sens.vhd
src/vhdl/unb2c_board_wdi_reg.vhd src/vhdl/unb2c_board_wdi_reg.vhd
src/vhdl/unb2c_board_qsfp_leds.vhd src/vhdl/unb2c_board_qsfp_leds.vhd
src/vhdl/unb2c_board_qsfp_leds_v2.vhd
src/vhdl/ctrl_unb2c_board.vhd src/vhdl/ctrl_unb2c_board.vhd
src/vhdl/unb2c_board_front_io.vhd src/vhdl/unb2c_board_front_io.vhd
src/vhdl/unb2c_board_back_io.vhd src/vhdl/unb2c_board_back_io.vhd
src/vhdl/unb2c_board_ring_io.vhd src/vhdl/unb2c_board_ring_io.vhd
src/vhdl/unb2c_board_peripherals_pkg.vhd src/vhdl/unb2c_board_peripherals_pkg.vhd
test_bench_files = test_bench_files =
tb/vhdl/tb_unb2c_board_clk200_pll.vhd tb/vhdl/tb_unb2c_board_clk200_pll.vhd
tb/vhdl/tb_unb2c_board_clk25_pll.vhd tb/vhdl/tb_unb2c_board_clk25_pll.vhd
tb/vhdl/tb_unb2c_board_node_ctrl.vhd tb/vhdl/tb_unb2c_board_node_ctrl.vhd
tb/vhdl/tb_unb2c_board_qsfp_leds.vhd tb/vhdl/tb_unb2c_board_qsfp_leds.vhd
tb/vhdl/tb_unb2c_board_qsfp_leds_v2.vhd
[modelsim_project_file] [modelsim_project_file]
......
-------------------------------------------------------------------------------
--
-- Copyright (C) 2024
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Author: E. Kooistra
-- Purpose: Provide visual activity information via the UniBoard2 front panel QSFP LEDs.
-- Description:
-- The testio LED on UniBoard2 is not visible via the front panel. The
-- front panel does have a dual colour LED for each QSFP lane. Therefore
-- these QSFP LEDs are used to signal some application information and lane
-- status/activity information.
--
-- Comparison unb2c_board_qsfp_leds_v2 and unb2c_board_qsfp_leds:
-- . unb2c_board_qsfp_leds_v2 does not output the internal us, ms and s pulses,
-- because they depend on the clock domain and are typically left open with
-- unb2c_board_qsfp_leds
-- . For g_factory_image = false the unb2c_board_qsfp_leds_v2 = unb2c_board_qsfp_leds
-- except use dp_clk to detect the transceiver activity strobes.
-- . For g_factory_image = true unb2c_board_qsfp_leds_v2 also shows status of dp_clk,
-- dp_pps, and ddr_I_cal_ok, ddr_II_cal_ok
--
-- LED lights:
--
-- 1) Default behaviour for all QSFP leds:
-- . off = no FPGA image is running
--
-- 2) For factory image only use the red leds:
-- . green off
-- . red[0] on = factory image is running (g_factory_image=true)
-- off = no image is running
-- . red[1] toggling every 1 s = 125 MHz clock present (= mm_clk = clk)
-- . red[2] toggling every 1 s = pps present (= dp_pps)
-- . red[3] toggling every 1 s = 200 MHz clock present (= dp_clk)
-- . red[4] on = DDR4 bank I calibrated = ctlr_tech_miso.done in io_ddr
-- off = not calibrated or no DDR4 module present
-- . red[5] on = DDR4 bank II calibrated = ctlr_tech_miso.done in io_ddr
-- off = not calibrated or no DDR4 module present
--
-- 3) For a user image only use green leds:
-- . red off
--
-- a) without Gbps lane functionality:
-- . green toggling every 1 s = user image is running (g_factory_image=FALSE and green_on_arr(I)='0' default)
--
-- b) with Gbps lane functionality:
-- . green toggling every 1 s when the lane status is not OK (green_on_arr(I)=xon='0')
-- . green on continously when the lane status is OK (green_on_arr(I)=xon='1')
-- . green led goes off briefly off when there is an Tx or Rx packet (green_evt_arr(I).sop='1')
--
-- The combined colour amber (= red + green) is not used. The factory image
-- only uses the red led and the user image only uses the green led.
--
-- Each QSFP carries c_quad = 4 lanes, therefore the green led LED can only
-- signal a combined status of the lanes. The combined status eg. be:
--
-- 'and-status' = combined status is on when all lanes are on
-- 'or-status' = combined status is on when at least 1 lane is on
--
-- Choose using 'or-status', because then the LED can give lane status
-- information when less than all 4 lane are connected.
--
library IEEE, common_lib, dp_lib;
use IEEE.std_logic_1164.all;
use common_lib.common_pkg.all;
use dp_lib.dp_stream_pkg.all;
entity unb2c_board_qsfp_leds_v2 is
generic (
g_sim : boolean := false; -- when true speed up led toggling in simulation
g_factory_image : boolean := false; -- distinguish factory image and user images
g_nof_qsfp : natural := 6; -- number of QSFP cages each with one dual led that can light red or green (or amber = red + green)
g_mm_pulse_us : natural := 125; -- nof mm_clk cycles to get us period
g_dp_pulse_us : natural := 200 -- nof dp_clk cycles to get us period
);
port (
mm_rst : in std_logic;
mm_clk : in std_logic;
dp_rst : in std_logic := '0';
dp_clk : in std_logic := '0';
dp_pps : in std_logic := '0';
-- ddr status (level signals)
ddr_I_cal_ok : in std_logic := '0';
ddr_II_cal_ok : in std_logic := '0';
-- lane status (sop strobe signals in dp_clk domain)
tx_siso_arr : in t_dp_siso_arr(g_nof_qsfp * c_quad - 1 downto 0) := (others => c_dp_siso_rst);
tx_sosi_arr : in t_dp_sosi_arr(g_nof_qsfp * c_quad - 1 downto 0) := (others => c_dp_sosi_rst);
rx_sosi_arr : in t_dp_sosi_arr(g_nof_qsfp * c_quad - 1 downto 0) := (others => c_dp_sosi_rst);
-- leds
green_led_arr : out std_logic_vector(g_nof_qsfp - 1 downto 0);
red_led_arr : out std_logic_vector(g_nof_qsfp - 1 downto 0)
);
end unb2c_board_qsfp_leds_v2;
architecture str of unb2c_board_qsfp_leds_v2 is
constant c_nof_ms : natural := sel_a_b(g_sim, 1, 100); -- force off for c_nof_ms and then on for at least c_nof_ms
constant c_nof_lanes : natural := g_nof_qsfp * c_quad; -- number of transceiver lanes, fixed 4 per Quad-SFP cage
-- internal pulses
signal mm_pulse_s : std_logic; -- pulse 1 mm_clk cycle every 1 s
signal mm_toggle_s : std_logic; -- toggle every 1 s in mm_clk domain
signal dp_pulse_ms : std_logic; -- pulse 1 dp_clk cycle every 1 ms
signal dp_pulse_s : std_logic; -- pulse 1 dp_clk cycle every 1 us
signal dp_toggle_s : std_logic; -- toggle every 1 s in dp_clk domain
signal dp_toggle_pps : std_logic; -- pulse 1 dp_clk cycle every 1 s
signal green_on_arr : std_logic_vector(g_nof_qsfp * c_quad - 1 downto 0);
signal green_evt_arr : std_logic_vector(g_nof_qsfp * c_quad - 1 downto 0);
signal qsfp_on_arr : std_logic_vector(g_nof_qsfp - 1 downto 0);
signal qsfp_evt_arr : std_logic_vector(g_nof_qsfp - 1 downto 0);
begin
-- mm_clk domain pulsers
u_mm_common_pulser_us_ms_s : entity common_lib.common_pulser_us_ms_s
generic map (
g_pulse_us => g_mm_pulse_us, -- nof mm_clk cycles to get us period
g_pulse_ms => sel_a_b(g_sim, 10, 1000), -- nof pulse_us pulses to get ms period
g_pulse_s => sel_a_b(g_sim, 10, 1000) -- nof pulse_ms pulses to get s period
)
port map (
rst => mm_rst,
clk => mm_clk,
pulse_s => mm_pulse_s
);
u_mm_common_toggle_s : entity common_lib.common_toggle
port map (
rst => mm_rst,
clk => mm_clk,
in_dat => mm_pulse_s,
out_dat => mm_toggle_s
);
-- dp_clk domain pulsers
u_dp_common_pulser_us_ms_s : entity common_lib.common_pulser_us_ms_s
generic map (
g_pulse_us => g_dp_pulse_us, -- nof dp_clk cycles to get us period
g_pulse_ms => sel_a_b(g_sim, 10, 1000), -- nof pulse_us pulses to get ms period
g_pulse_s => sel_a_b(g_sim, 10, 1000) -- nof pulse_ms pulses to get s period
)
port map (
rst => dp_rst,
clk => dp_clk,
pulse_ms => dp_pulse_ms,
pulse_s => dp_pulse_s
);
u_dp_common_toggle_s : entity common_lib.common_toggle
port map (
rst => dp_rst,
clk => dp_clk,
in_dat => dp_pulse_s,
out_dat => dp_toggle_s
);
gen_factory_image : if g_factory_image = true generate
green_led_arr <= (others => '0');
red_led_arr(0) <= '1';
red_led_arr(1) <= mm_toggle_s;
red_led_arr(2) <= dp_toggle_pps;
red_led_arr(3) <= dp_toggle_s;
red_led_arr(4) <= ddr_I_cal_ok;
red_led_arr(5) <= ddr_II_cal_ok;
u_dp_common_toggle_pps : entity common_lib.common_toggle
port map (
rst => dp_rst,
clk => dp_clk,
in_dat => dp_pps,
out_dat => dp_toggle_pps
);
end generate;
gen_user_image : if g_factory_image = false generate
red_led_arr <= (others => '0');
gen_green_ctrl_arr : for I in c_nof_lanes - 1 downto 0 generate
green_on_arr(I) <= tx_siso_arr(I).xon when rising_edge(dp_clk);
green_evt_arr(I) <= tx_sosi_arr(I).sop or rx_sosi_arr(I).sop when rising_edge(dp_clk);
end generate;
gen_green_led_arr : for I in g_nof_qsfp - 1 downto 0 generate
qsfp_on_arr(I) <= orv(green_on_arr( (I + 1) * c_quad - 1 downto + I * c_quad));
qsfp_evt_arr(I) <= orv(green_evt_arr((I + 1) * c_quad - 1 downto + I * c_quad));
u_green_led_controller : entity common_lib.common_led_controller
generic map (
g_nof_ms => c_nof_ms
)
port map (
rst => dp_rst,
clk => dp_clk,
pulse_ms => dp_pulse_ms,
-- led control
ctrl_on => qsfp_on_arr(I),
ctrl_evt => qsfp_evt_arr(I),
ctrl_input => dp_toggle_s,
-- led output
led => green_led_arr(I)
);
end generate;
end generate;
end str;
-------------------------------------------------------------------------------
--
-- Copyright (C) 2024
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Author: E. Kooistra
-- Purpose: Test bench for unb2c_board_qsfp_leds
-- Description:
-- The test bench is self-stopping but not self-checking. Manually obeserve
-- in the wave window that:
-- 1) factory image:
-- - green led is off
-- - red led toggles
-- 2) user image
-- - red led is off
-- - green led toggles when any xon='0'
-- - green led is on continously when any xon='1'
-- - green led goes briefly off when any sop='1'
-- Usage:
-- > as 3
-- > run -a
library IEEE, common_lib, dp_lib;
use IEEE.std_logic_1164.all;
use common_lib.common_pkg.all;
use common_lib.tb_common_pkg.all;
use dp_lib.dp_stream_pkg.all;
entity tb_unb2c_board_qsfp_leds_v2 is
end tb_unb2c_board_qsfp_leds_v2;
architecture tb of tb_unb2c_board_qsfp_leds_v2 is
constant c_sim_factor : natural := 100; -- same as in unb2c_board_qsfp_leds_v2.vhd
constant c_mm_clk_freq_hz : natural := 125 * 10**6;
constant c_mm_clk_period_ns : natural := 10**9 / c_mm_clk_freq_hz;
constant c_nof_mm_clk_per_us : natural := 1000 / c_mm_clk_period_ns;
constant c_dp_clk_freq_hz : natural := 125 * 10**6;
constant c_dp_clk_period_ns : natural := 10**9 / c_dp_clk_freq_hz;
constant c_nof_dp_clk_per_us : natural := 1000 / c_dp_clk_period_ns;
constant mm_clk_period : time := c_mm_clk_period_ns * 1 ns;
constant dp_clk_period : time := c_dp_clk_period_ns * 1 ns;
constant c_nof_qsfp : natural := 6;
constant c_nof_lanes : natural := c_nof_qsfp * c_quad;
signal tb_end : std_logic := '0';
signal mm_rst : std_logic := '1';
signal mm_clk : std_logic := '0';
signal mm_pulse_ms : std_logic := '0';
signal dp_rst : std_logic := '1';
signal dp_clk : std_logic := '0';
signal dp_pps : std_logic := '0';
signal ddr_I_cal_ok : std_logic := '0';
signal ddr_II_cal_ok : std_logic := '0';
signal tx_siso_arr : t_dp_siso_arr(c_nof_lanes - 1 downto 0) := (others => c_dp_siso_rst);
signal tx_sosi_arr : t_dp_sosi_arr(c_nof_lanes - 1 downto 0) := (others => c_dp_sosi_rst);
signal rx_sosi_arr : t_dp_sosi_arr(c_nof_lanes - 1 downto 0) := (others => c_dp_sosi_rst);
signal dbg_xon_arr : std_logic_vector(c_nof_lanes - 1 downto 0);
signal dbg_tx_sop_arr : std_logic_vector(c_nof_lanes - 1 downto 0);
signal dbg_rx_sop_arr : std_logic_vector(c_nof_lanes - 1 downto 0);
signal factory_green_led_arr : std_logic_vector(c_nof_qsfp - 1 downto 0);
signal factory_red_led_arr : std_logic_vector(c_nof_qsfp - 1 downto 0);
signal user_green_led_arr : std_logic_vector(c_nof_qsfp - 1 downto 0);
signal user_red_led_arr : std_logic_vector(c_nof_qsfp - 1 downto 0);
-- Cannot use proc_common_gen_pulse() to create sop in array.
-- proc_common_gen_pulse() works for dbg_sop, dbg_sosi.sop but not for dbg_sop_slv(I) or for tx_sosi_arr(I).sop.
-- The compiler then gives Error: "(vcom-1450) Actual (indexed name) for formal "pulse" is not a static signal name"
-- It does work if the array index is from a GENERATE statement, but it does not work when it is from a LOOP statement.
signal dbg_sop : std_logic;
signal dbg_sop_slv : std_logic_vector(c_nof_lanes - 1 downto 0);
signal dbg_sosi : t_dp_sosi;
begin
mm_clk <= not mm_clk or tb_end after mm_clk_period / 2;
mm_rst <= '1', '0' after mm_clk_period * 7;
dp_clk <= not dp_clk or tb_end after dp_clk_period / 2;
dp_rst <= '1', '0' after dp_clk_period * 7;
proc_common_gen_pulse(1, (c_nof_mm_clk_per_us * 10**3) / c_sim_factor, '1', mm_rst, mm_clk, mm_pulse_ms);
proc_common_gen_pulse(1, (c_nof_dp_clk_per_us * 10**6) / c_sim_factor**2, '1', dp_rst, dp_clk, dp_pps);
-- Ease observation of record fields in Wave window, by mapping them to a SLV
dbg_xon_arr <= func_dp_stream_arr_get(tx_siso_arr, "XON");
dbg_tx_sop_arr <= func_dp_stream_arr_get(tx_sosi_arr, "SOP");
dbg_rx_sop_arr <= func_dp_stream_arr_get(rx_sosi_arr, "SOP");
p_stimuli : process
begin
tx_siso_arr <= (others => c_dp_siso_rst);
tx_sosi_arr <= (others => c_dp_sosi_rst);
rx_sosi_arr <= (others => c_dp_sosi_rst);
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
-- Toggle ddr calibration status
ddr_I_cal_ok <= '1';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 5);
ddr_II_cal_ok <= '1';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
ddr_I_cal_ok <= '0';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 5);
ddr_II_cal_ok <= '0';
-- Switch on each lane
for I in 0 to c_nof_lanes - 1 loop
tx_siso_arr(I).xon <= '1';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
end loop;
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
-- Issue the sop of a Tx packet on each lane
for I in 0 to c_nof_lanes - 1 loop
-- Cannot use proc_common_gen_pulse(), because index I in a LOOP is not static
tx_sosi_arr(I).sop <= '1';
wait until rising_edge(mm_clk);
tx_sosi_arr(I).sop <= '0';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
end loop;
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
-- Issue the sop of an Rx packet on each lane
for I in 0 to c_nof_lanes - 1 loop
-- Cannot use proc_common_gen_pulse(), because index I in a LOOP is not static
rx_sosi_arr(I).sop <= '1';
wait until rising_edge(mm_clk);
rx_sosi_arr(I).sop <= '0';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
end loop;
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
-- Switch off each lane
for I in 0 to c_nof_lanes - 1 loop
tx_siso_arr(I).xon <= '0';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
end loop;
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
tb_end <= '1';
proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
wait;
end process;
u_unb2c_factory_qsfp_leds_v2 : entity work.unb2c_board_qsfp_leds_v2
generic map (
g_sim => true, -- when true speed up led toggling in simulation
g_factory_image => true, -- distinguish factory image and user images
g_nof_qsfp => c_nof_qsfp, -- number of QSFP cages each with one dual led that can light red or green (or amber = red + green)
g_mm_pulse_us => c_nof_mm_clk_per_us, -- nof mm_clk cycles to get us period<
g_dp_pulse_us => c_nof_dp_clk_per_us -- nof dp_clk cycles to get us period<
)
port map (
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
dp_pps => dp_pps,
-- ddr status
ddr_I_cal_ok => ddr_I_cal_ok,
ddr_II_cal_ok => ddr_II_cal_ok,
-- leds
green_led_arr => factory_green_led_arr,
red_led_arr => factory_red_led_arr
);
u_unb2c_user_qsfp_leds_v2 : entity work.unb2c_board_qsfp_leds_v2
generic map (
g_sim => true, -- when true speed up led toggling in simulation
g_factory_image => false, -- distinguish factory image and user images
g_nof_qsfp => c_nof_qsfp, -- number of QSFP cages each with one dual led that can light red or green (or amber = red + green)
g_mm_pulse_us => c_nof_mm_clk_per_us, -- nof mm_clk cycles to get us period<
g_dp_pulse_us => c_nof_dp_clk_per_us -- nof dp_clk cycles to get us period<
)
port map (
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
dp_pps => dp_pps,
-- lane status
tx_siso_arr => tx_siso_arr,
tx_sosi_arr => tx_sosi_arr,
rx_sosi_arr => rx_sosi_arr,
-- leds
green_led_arr => user_green_led_arr,
red_led_arr => user_red_led_arr
);
end tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment