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

Added unb2_board_qsfp_leds.vhd plus test bench.

parent f84e9a0d
No related branches found
No related tags found
No related merge requests found
......@@ -22,6 +22,7 @@ synth_files =
src/vhdl/unb2_board_sens_reg.vhd
src/vhdl/mms_unb2_board_sens.vhd
src/vhdl/unb2_board_wdi_reg.vhd
src/vhdl/unb2_board_qsfp_leds.vhd
src/vhdl/ctrl_unb2_board.vhd
src/vhdl/unb2_board_front_io.vhd
src/vhdl/unb2_board_back_io.vhd
......@@ -35,6 +36,7 @@ test_bench_files =
tb/vhdl/tb_unb2_board_clk200_pll.vhd
tb/vhdl/tb_unb2_board_clk25_pll.vhd
tb/vhdl/tb_unb2_board_node_ctrl.vhd
tb/vhdl/tb_unb2_board_qsfp_leds.vhd
# vsim -L ... -L ... ...
modelsim_search_libraries =
......
-------------------------------------------------------------------------------
--
-- Copyright (C) 2015
-- 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/>.
--
-------------------------------------------------------------------------------
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;
-- 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.
--
-- LED lights:
--
-- 1) Default behaviour for all QSFP leds:
-- . off = no FPGA image is running
--
-- 2) For factory image:
-- . green off
-- . red toggling every 1 s = factory image is running (g_factory_image=TRUE)
--
-- 3) For a user image without Gbps lane functionality:
-- . red off
-- . green toggling every 1 s = user image is running (g_factory_image=FALSE and green_on_arr(I)='0' default)
--
-- 4) For a user image with Gbps lane functionality:
-- . red off
-- . 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.
--
ENTITY unb2_board_qsfp_leds 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_pulse_us : NATURAL := 200 -- nof clk cycles to get us period
);
PORT (
rst : IN STD_LOGIC;
clk : IN STD_LOGIC;
-- internal pulser outputs
pulse_us : OUT STD_LOGIC;
pulse_ms : OUT STD_LOGIC;
pulse_s : OUT STD_LOGIC;
-- lane status
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 unb2_board_qsfp_leds;
ARCHITECTURE str OF unb2_board_qsfp_leds 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
SIGNAL i_pulse_ms : STD_LOGIC;
SIGNAL i_pulse_s : STD_LOGIC;
SIGNAL toggle_s : STD_LOGIC;
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
pulse_ms <= i_pulse_ms;
pulse_s <= i_pulse_s;
-- Also output the pulses, because they could be useful for other purposes in the clk clock domain as well
u_common_pulser_us_ms_s : ENTITY common_lib.common_pulser_us_ms_s
GENERIC MAP (
g_pulse_us => g_pulse_us, -- nof 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 => rst,
clk => clk,
pulse_us => pulse_us,
pulse_ms => i_pulse_ms,
pulse_s => i_pulse_s
);
u_common_toggle_s : ENTITY common_lib.common_toggle
PORT MAP (
rst => rst,
clk => clk,
in_dat => i_pulse_s,
out_dat => toggle_s
);
gen_factory_image : IF g_factory_image=TRUE GENERATE
green_led_arr <= (OTHERS=>'0');
gen_red_led_arr : FOR I IN g_nof_qsfp-1 DOWNTO 0 GENERATE
u_red_led_controller : ENTITY common_lib.common_led_controller
GENERIC MAP (
g_nof_ms => c_nof_ms
)
PORT MAP (
rst => rst,
clk => clk,
-- led control
ctrl_input => toggle_s,
-- led output
led => red_led_arr(I)
);
END GENERATE;
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(clk);
green_evt_arr(I) <= tx_sosi_arr(I).sop OR rx_sosi_arr(I).sop WHEN rising_edge(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 => rst,
clk => clk,
pulse_ms => i_pulse_ms,
-- led control
ctrl_on => qsfp_on_arr(I),
ctrl_evt => qsfp_evt_arr(I),
ctrl_input => toggle_s,
-- led output
led => green_led_arr(I)
);
END GENERATE;
END GENERATE;
END str;
-------------------------------------------------------------------------------
--
-- Copyright (C) 2010
-- 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/>.
--
-------------------------------------------------------------------------------
-- Purpose: Test bench for unb2_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_unb2_board_qsfp_leds IS
END tb_unb2_board_qsfp_leds;
ARCHITECTURE tb OF tb_unb2_board_qsfp_leds IS
CONSTANT c_clk_freq_hz : NATURAL := 200 * 10**6;
CONSTANT c_clk_period_ns : NATURAL := 10**9 / c_clk_freq_hz;
CONSTANT c_nof_clk_per_us : NATURAL := 1000 / c_clk_period_ns;
CONSTANT clk_period : TIME := c_clk_period_ns * 1 ns;
CONSTANT c_nof_qsfp : NATURAL := 2;
CONSTANT c_nof_lanes : NATURAL := c_nof_qsfp*c_quad;
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL rst : STD_LOGIC;
SIGNAL clk : STD_LOGIC := '0';
SIGNAL pulse_us : STD_LOGIC;
SIGNAL pulse_ms : STD_LOGIC;
SIGNAL pulse_s : STD_LOGIC;
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
clk <= NOT clk OR tb_end AFTER clk_period/2;
rst <= '1', '0' AFTER clk_period*7;
-- 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(clk, pulse_ms, 50);
-- 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(clk, pulse_ms, 10);
END LOOP;
proc_common_wait_some_pulses(clk, 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(clk);
tx_sosi_arr(I).sop <= '0';
proc_common_wait_some_pulses(clk, pulse_ms, 10);
END LOOP;
proc_common_wait_some_pulses(clk, 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(clk);
rx_sosi_arr(I).sop <= '0';
proc_common_wait_some_pulses(clk, pulse_ms, 10);
END LOOP;
proc_common_wait_some_pulses(clk, 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(clk, pulse_ms, 10);
END LOOP;
proc_common_wait_some_pulses(clk, pulse_ms, 50);
tb_end <= '1';
proc_common_wait_some_pulses(clk, pulse_ms, 10);
WAIT;
END PROCESS;
u_unb2_factory_qsfp_leds : ENTITY work.unb2_board_qsfp_leds
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_pulse_us => c_nof_clk_per_us -- nof clk cycles to get us period
)
PORT MAP (
rst => rst,
clk => clk,
-- internal pulser outputs
pulse_us => pulse_us,
pulse_ms => pulse_ms,
pulse_s => pulse_s,
-- lane status
tx_siso_arr => tx_siso_arr,
tx_sosi_arr => tx_sosi_arr,
rx_sosi_arr => rx_sosi_arr,
-- leds
green_led_arr => factory_green_led_arr,
red_led_arr => factory_red_led_arr
);
u_unb2_user_qsfp_leds : ENTITY work.unb2_board_qsfp_leds
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_pulse_us => c_nof_clk_per_us -- nof clk cycles to get us period
)
PORT MAP (
rst => rst,
clk => clk,
-- internal pulser outputs
pulse_us => pulse_us,
pulse_ms => pulse_ms,
pulse_s => pulse_s,
-- 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.
Please register or to comment