FEATUE: Modify delay & width as registers

This commit is contained in:
2019-11-29 11:48:12 +01:00
parent ffb3eb6331
commit 6b1f4fbcbc
7 changed files with 7772 additions and 6273 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -2,7 +2,7 @@
-- Paul Scherrer Institute (PSI)
-- ---------------------------------------------------------------------------
-- Unit : evr320_ifc1210_wrapper.vhd
-- Author : Patric Bucher
-- Author : Patric Bucher, Benoit Stef
-- ---------------------------------------------------------------------------
-- Copyright© PSI, Section DSV
-- ---------------------------------------------------------------------------
@ -20,371 +20,375 @@ use work.evr320_pkg.all;
use work.v6vlx_gtxe1_pkg.all;
entity evr320_ifc1210_wrapper is
generic(
g_MGT_LOCATION : string := "GTXE1_X0Y16"; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY : string := "SFEL"; -- "HIPA" | "SFEL"
g_EVENT_RECORDER : boolean := false; -- enable/disable Event Recorder functionality
g_XUSER_CLK_FREQ : natural := 125000000; -- Xuser Clk Frequency in Hz
g_EVT_DURATION : typ_arr_pos := (1, 1, 1, 1, 1); -- output extend in clock recovery clock cycles event 0,1,2,3
g_EVT_HOLDOFF : typ_arr_nat := (0, 0, 0, 0, 0); -- Minimum number of clock cycles between input pulses event sos,0,1,2,3
g_EVT_DELAY : typ_arr_pos := (4, 4, 4, 4, 4) -- delay in recovery clock cycles event sos,0,1,2,3
);
port(
tick1sec_i : in std_logic;
-- ------------------------------------------------------------------------
-- Debug interface
-- ------------------------------------------------------------------------
debug_clk : out std_logic;
debug : out std_logic_vector(127 downto 0);
-- ------------------------------------------------------------------------
-- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz)
-- ------------------------------------------------------------------------
xuser_CLK : in std_logic;
xuser_RESET : in std_logic;
xuser_TMEM_ENA : in std_logic;
xuser_TMEM_WE : in std_logic_vector(7 downto 0);
xuser_TMEM_ADD : in std_logic_vector(13 downto 3);
xuser_TMEM_DATW : in std_logic_vector(63 downto 0);
xuser_TMEM_DATR : out std_logic_vector(63 downto 0);
-- ------------------------------------------------------------------------
-- MGT Interface
-- ------------------------------------------------------------------------
mgt_refclk_i : in std_logic; -- MGT Reference Clock
mgt_sfp_los_i : in std_logic; -- SFP Loss of Signal (light on receiver)
mgt_rx_n : in std_logic; -- MGT RX N
mgt_rx_p : in std_logic; -- MGT RX P
mgt_tx_n : out std_logic; -- MGT TX N
mgt_tx_p : out std_logic; -- MGT TX P
mgt_status_o : out std_logic_vector(31 downto 0); -- MGT Status
mgt_control_i : in std_logic_vector(31 downto 0); -- MGT Control
---------------------------------------------------------------------------
-- User interface MGT clock
---------------------------------------------------------------------------
clk_evr_o : out std_logic; -- Recovered parallel clock from MGT
usr_events_o : out std_logic_vector(3 downto 0); -- User defined event pulses with one clock cycles length & no delay
sos_event_o : out std_logic; -- Start-of-Sequence Event
-- new features adjusted in delay & length
usr_events_adj_o : out std_logic_vector(3 downto 0); -- User defined event pulses adjusted in delay & length
sos_events_adj_o : out std_logic; -- Start-of-Sequence adjusted in delay & length
--------------------------------------------------------------------------
-- Decoder axi stream interface, User clock
--------------------------------------------------------------------------
stream_clk_i : in std_logic := '0';
stream_data_o : out std_logic_vector(7 downto 0);
stream_addr_o : out std_logic_vector(10 downto 0);
stream_valid_o : out std_logic
);
generic(
g_MGT_LOCATION : string := "GTXE1_X0Y16"; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY : string := "SFEL"; -- "HIPA" | "SFEL"
g_EVENT_RECORDER : boolean := false; -- enable/disable Event Recorder functionality
g_XUSER_CLK_FREQ : natural := 125000000; -- Xuser Clk Frequency in Hz
g_EVT_HOLDOFF : typ_arr_nat := (0, 0, 0, 0, 0) -- Minimum number of clock cycles between input pulses event sos,0,1,2,3
);
port(
-- ------------------------------------------------------------------------
-- Debug interface
-- ------------------------------------------------------------------------
debug_clk : out std_logic;
debug : out std_logic_vector(127 downto 0);
-- ------------------------------------------------------------------------
-- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz)
-- ------------------------------------------------------------------------
xuser_CLK : in std_logic;
xuser_RESET : in std_logic;
xuser_TMEM_ENA : in std_logic;
xuser_TMEM_WE : in std_logic_vector(7 downto 0);
xuser_TMEM_ADD : in std_logic_vector(13 downto 3);
xuser_TMEM_DATW : in std_logic_vector(63 downto 0);
xuser_TMEM_DATR : out std_logic_vector(63 downto 0);
-- ------------------------------------------------------------------------
-- MGT Interface
-- ------------------------------------------------------------------------
mgt_refclk_i : in std_logic; -- MGT Reference Clock
mgt_sfp_los_i : in std_logic; -- SFP Loss of Signal (light on receiver)
mgt_rx_n : in std_logic; -- MGT RX N
mgt_rx_p : in std_logic; -- MGT RX P
mgt_tx_n : out std_logic; -- MGT TX N
mgt_tx_p : out std_logic; -- MGT TX P
mgt_status_o : out std_logic_vector(31 downto 0); -- MGT Status
mgt_control_i : in std_logic_vector(31 downto 0); -- MGT Control
---------------------------------------------------------------------------
-- User interface MGT clock
---------------------------------------------------------------------------
clk_evr_o : out std_logic; -- Recovered parallel clock from MGT
usr_events_o : out std_logic_vector(3 downto 0); -- User defined event pulses with one clock cycles length & no delay
sos_event_o : out std_logic; -- Start-of-Sequence Event
--*** new features adjusted in delay & length ***
usr_event_width_i : in typ_arr_width; --output extend in clock recovery clock cycles event 0,1,2,3
usr_event_delay_i : in typ_arr_delay; -- delay in recovery clock cycles event sos,0,1,2,3
usr_events_adj_o : out std_logic_vector(3 downto 0); -- User defined event pulses adjusted in delay & length
sos_events_adj_o : out std_logic; -- Start-of-Sequence adjusted in delay & length
--------------------------------------------------------------------------
-- Decoder axi stream interface, User clock
--------------------------------------------------------------------------
stream_clk_i : in std_logic := '0';
stream_data_o : out std_logic_vector(7 downto 0);
stream_addr_o : out std_logic_vector(10 downto 0);
stream_valid_o : out std_logic
);
end evr320_ifc1210_wrapper;
architecture rtl of evr320_ifc1210_wrapper is
-- --------------------------------------------------------------------------
-- Parameters
-- --------------------------------------------------------------------------
constant c_TOSCA2_DATA_WIDTH : integer := 64;
constant c_EVR_REG64_COUNT : integer := 16; -- unused, only documentation
constant c_EVR_MEM_SIZE : integer := 16384; -- unused, only documentation
-- --------------------------------------------------------------------------
-- Parameters
-- --------------------------------------------------------------------------
constant c_TOSCA2_DATA_WIDTH : integer := 64;
constant c_EVR_REG64_COUNT : integer := 16; -- unused, only documentation
constant c_EVR_MEM_SIZE : integer := 16384; -- unused, only documentation
-- --------------------------------------------------------------------------
-- Signal definitions
-- --------------------------------------------------------------------------
signal clk_evr : std_logic;
--signal clk_evr_monitor : std_logic; -- for debugging
signal rst_evr : std_logic;
signal mgt_control : std_logic_vector(31 downto 0) := (others => '0');
signal mgt_status : std_logic_vector(31 downto 0);
signal mgt_rx_data : std_logic_vector(15 downto 0);
signal mgt_rx_charisk : std_logic_vector(1 downto 0);
signal mgt_lossofsync : std_logic;
signal mgt_reset_tmem_evr : std_logic; -- for legacy reasons, ifc1210 mgt control is in tmem_psi_generic part
signal mem_clk : std_logic;
signal mem_addr_evr : std_logic_vector(11 downto 0);
signal mem_addr_tosca : std_logic_vector(10 downto 0);
signal mem_data : std_logic_vector(c_TOSCA2_DATA_WIDTH - 1 downto 0);
signal evr_params : typ_evr320_params;
signal evr_params_sync : typ_evr320_params;
signal evr_params_xuser : typ_evr320_params;
signal event_recorder_status : typ_evt_rec_status;
signal event_recorder_control : typ_evt_rec_ctrl;
signal event_recorder_control_sync : typ_evt_rec_ctrl;
signal event_recorder_control_xuser : typ_evt_rec_ctrl;
signal evr_latency_measure_stat : typ_rec_latency_measure_stat;
signal evr_latency_measure_ctrl : typ_rec_latency_measure_ctrl;
signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0');
signal debug_data : std_logic_vector(127 downto 0);
signal decoder_event_valid : std_logic;
signal decoder_event : std_logic_vector(7 downto 0);
-- --------------------------------------------------------------------------
-- Signal definitions
-- --------------------------------------------------------------------------
signal clk_evr : std_logic;
--signal clk_evr_monitor : std_logic; -- for debugging
signal rst_evr : std_logic;
signal mgt_control : std_logic_vector(31 downto 0) := (others => '0');
signal mgt_status : std_logic_vector(31 downto 0);
signal mgt_rx_data : std_logic_vector(15 downto 0);
signal mgt_rx_charisk : std_logic_vector(1 downto 0);
signal mgt_lossofsync : std_logic;
signal mgt_reset_tmem_evr : std_logic; -- for legacy reasons, ifc1210 mgt control is in tmem_psi_generic part
signal mem_clk : std_logic;
signal mem_addr_evr : std_logic_vector(11 downto 0);
signal mem_addr_tosca : std_logic_vector(10 downto 0);
signal mem_data : std_logic_vector(c_TOSCA2_DATA_WIDTH - 1 downto 0);
signal evr_params : typ_evr320_params;
signal evr_params_sync : typ_evr320_params;
signal evr_params_xuser : typ_evr320_params;
signal event_recorder_status : typ_evt_rec_status;
signal event_recorder_control : typ_evt_rec_ctrl;
signal event_recorder_control_sync : typ_evt_rec_ctrl;
signal event_recorder_control_xuser : typ_evt_rec_ctrl;
signal evr_latency_measure_stat : typ_rec_latency_measure_stat;
signal evr_latency_measure_ctrl : typ_rec_latency_measure_ctrl;
signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0');
signal debug_data : std_logic_vector(127 downto 0);
signal decoder_event_valid : std_logic;
signal decoder_event : std_logic_vector(7 downto 0);
-- --------------------------------------------------------------------------
-- Attribute definitions
-- --------------------------------------------------------------------------
attribute keep : string;
attribute keep of clk_evr : signal is "TRUE";
attribute keep of debug_data : signal is "TRUE";
signal usr_events_s : std_logic_vector(3 downto 0);
signal sos_event_s : std_logic;
-- --------------------------------------------------------------------------
-- Attribute definitions
-- --------------------------------------------------------------------------
attribute keep : string;
attribute keep of clk_evr : signal is "TRUE";
attribute keep of debug_data : signal is "TRUE";
signal usr_events_s : std_logic_vector(3 downto 0);
signal sos_event_s : std_logic;
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- //////////////////// Main Body /////////////////////////
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- //////////////////// Main Body /////////////////////////
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
begin
-- --------------------------------------------------------------------------
-- static signal assignments
-- --------------------------------------------------------------------------
mgt_lossofsync <= mgt_status(15);
rst_evr <= mgt_status(15);
mem_addr_evr <= '0' & mem_addr_tosca;
-- --------------------------------------------------------------------------
-- static signal assignments
-- --------------------------------------------------------------------------
mgt_lossofsync <= mgt_status(15);
rst_evr <= mgt_status(15);
mem_addr_evr <= '0' & mem_addr_tosca;
mgt_control(c_GTXRESET) <= mgt_control_i(c_GTXRESET) or mgt_sfp_los_i or mgt_reset_tmem_evr;
mgt_control(4 downto 1) <= mgt_control_i(4 downto 1);
mgt_control(c_RXCDRRESET) <= mgt_control_i(c_RXCDRRESET);
mgt_control(31 downto 6) <= mgt_control_i(31 downto 6);
mgt_control(c_GTXRESET) <= mgt_control_i(c_GTXRESET) or mgt_sfp_los_i or mgt_reset_tmem_evr;
mgt_control(4 downto 1) <= mgt_control_i(4 downto 1);
mgt_control(c_RXCDRRESET) <= mgt_control_i(c_RXCDRRESET);
mgt_control(31 downto 6) <= mgt_control_i(31 downto 6);
-- --------------------------------------------------------------------------
-- Synchronisation to EVR Clock
-- --------------------------------------------------------------------------
prc_sync_evr : process(clk_evr)
begin
if rising_edge(clk_evr) then
---
evr_params_sync <= evr_params_xuser;
evr_params <= evr_params_sync;
---
event_recorder_control_sync <= event_recorder_control_xuser;
event_recorder_control <= event_recorder_control_sync;
---
end if;
end process;
-- --------------------------------------------------------------------------
-- Synchronisation to EVR Clock
-- --------------------------------------------------------------------------
prc_sync_evr : process(clk_evr)
begin
if rising_edge(clk_evr) then
---
evr_params_sync <= evr_params_xuser;
evr_params <= evr_params_sync;
---
event_recorder_control_sync <= event_recorder_control_xuser;
event_recorder_control <= event_recorder_control_sync;
---
end if;
end process;
-- --------------------------------------------------------------------------
-- EVR320 Decoder
-- --------------------------------------------------------------------------
evr320_decoder_inst : entity work.evr320_decoder
generic map(
EVENT_RECORDER => g_EVENT_RECORDER,
MEM_DATA_WIDTH => c_TOSCA2_DATA_WIDTH)
port map(
-- Debug interface
debug_clk => debug_clk,
debug => debug_data,
-- GTX parallel interface
i_mgt_rst => mgt_lossofsync,
i_mgt_rx_clk => clk_evr,
i_mgt_rx_data => mgt_rx_data,
i_mgt_rx_charisk => mgt_rx_charisk,
-- User interface CPU clock
i_usr_clk => mem_clk,
i_evr_params => evr_params,
o_event_recorder_stat => event_recorder_status,
i_event_recorder_ctrl => event_recorder_control,
i_mem_addr => mem_addr_evr,
o_mem_data => mem_data,
-- user stream interface, user clock
i_stream_clk => stream_clk_i,
o_stream_data => stream_data_o,
o_stream_addr => stream_addr_o,
o_stream_valid => stream_valid_o,
-- User interface MGT clock
o_usr_events => usr_events_s,
-- o_usr_events_ext => usr_events_ext_o, -- not in use anymore
o_sos_event => sos_event_s,
o_event => decoder_event,
o_event_valid => decoder_event_valid
);
-- --------------------------------------------------------------------------
-- EVR320 Decoder
-- --------------------------------------------------------------------------
evr320_decoder_inst : entity work.evr320_decoder
generic map(
EVENT_RECORDER => g_EVENT_RECORDER,
MEM_DATA_WIDTH => c_TOSCA2_DATA_WIDTH)
port map(
-- Debug interface
debug_clk => debug_clk,
debug => debug_data,
-- GTX parallel interface
i_mgt_rst => mgt_lossofsync,
i_mgt_rx_clk => clk_evr,
i_mgt_rx_data => mgt_rx_data,
i_mgt_rx_charisk => mgt_rx_charisk,
-- User interface CPU clock
i_usr_clk => mem_clk,
i_evr_params => evr_params,
o_event_recorder_stat => event_recorder_status,
i_event_recorder_ctrl => event_recorder_control,
i_mem_addr => mem_addr_evr,
o_mem_data => mem_data,
-- user stream interface, user clock
i_stream_clk => stream_clk_i,
o_stream_data => stream_data_o,
o_stream_addr => stream_addr_o,
o_stream_valid => stream_valid_o,
-- User interface MGT clock
o_usr_events => usr_events_s,
-- o_usr_events_ext => usr_events_ext_o, -- not in use anymore
o_sos_event => sos_event_s,
o_event => decoder_event,
o_event_valid => decoder_event_valid
);
usr_events_o <= usr_events_s;
sos_event_o <= sos_event_s;
usr_events_o <= usr_events_s;
sos_event_o <= sos_event_s;
-- --------------------------------------------------------------------------
-- MGT Wrapper for GTX Virtex-6
-- --------------------------------------------------------------------------
mgt_wrapper_inst : entity work.v6vlx_gtxe1_wrapper
generic map(
g_MGT_LOCATION => g_MGT_LOCATION,
g_FACILITY => g_FACILITY)
port map(
-- MGT serial interface
i_mgt_refclk => mgt_refclk_i,
o_mgt_refclk => open,
i_mgt_rx_p => mgt_rx_p,
i_mgt_rx_n => mgt_rx_n,
o_mgt_tx_p => mgt_tx_p,
o_mgt_tx_n => mgt_tx_n,
-- MGT parallel interface
o_mgt_status => mgt_status,
i_mgt_control => mgt_control,
o_mgt_recclk => clk_evr,
o_mgt_rx_data => mgt_rx_data,
o_mgt_rx_charisk => mgt_rx_charisk
);
-- --------------------------------------------------------------------------
-- MGT Wrapper for GTX Virtex-6
-- --------------------------------------------------------------------------
mgt_wrapper_inst : entity work.v6vlx_gtxe1_wrapper
generic map(
g_MGT_LOCATION => g_MGT_LOCATION,
g_FACILITY => g_FACILITY)
port map(
-- MGT serial interface
i_mgt_refclk => mgt_refclk_i,
o_mgt_refclk => open,
i_mgt_rx_p => mgt_rx_p,
i_mgt_rx_n => mgt_rx_n,
o_mgt_tx_p => mgt_tx_p,
o_mgt_tx_n => mgt_tx_n,
-- MGT parallel interface
o_mgt_status => mgt_status,
i_mgt_control => mgt_control,
o_mgt_recclk => clk_evr,
o_mgt_rx_data => mgt_rx_data,
o_mgt_rx_charisk => mgt_rx_charisk
);
-- --------------------------------------------------------------------------
-- TMEM
-- --------------------------------------------------------------------------
evr320_tmem_inst : entity work.evr320_tmem
port map(
-- TOSCA2 TMEM Interface
xuser_CLK => xuser_CLK,
xuser_RESET => xuser_RESET,
xuser_TMEM_ENA => xuser_TMEM_ENA,
xuser_TMEM_WE => xuser_TMEM_WE,
xuser_TMEM_ADD => xuser_TMEM_ADD,
xuser_TMEM_DATW => xuser_TMEM_DATW,
xuser_TMEM_DATR => xuser_TMEM_DATR,
-- EVR320 Memory/Parameter Interface
evr_params_o => evr_params_xuser,
evr_frequency_i => evr_frequency,
evr_evt_rec_status_i => event_recorder_status,
evr_evt_rec_control_o => event_recorder_control_xuser,
evr_latency_measure_stat_i => evr_latency_measure_stat,
evr_latency_measure_ctrl_o => evr_latency_measure_ctrl,
mgt_status_i => mgt_status,
mgt_reset_o => mgt_reset_tmem_evr,
mem_clk_o => mem_clk,
mem_addr_o => mem_addr_tosca,
mem_data_i => mem_data
);
-- --------------------------------------------------------------------------
-- TMEM
-- --------------------------------------------------------------------------
evr320_tmem_inst : entity work.evr320_tmem
port map(
-- TOSCA2 TMEM Interface
xuser_CLK => xuser_CLK,
xuser_RESET => xuser_RESET,
xuser_TMEM_ENA => xuser_TMEM_ENA,
xuser_TMEM_WE => xuser_TMEM_WE,
xuser_TMEM_ADD => xuser_TMEM_ADD,
xuser_TMEM_DATW => xuser_TMEM_DATW,
xuser_TMEM_DATR => xuser_TMEM_DATR,
-- EVR320 Memory/Parameter Interface
evr_params_o => evr_params_xuser,
evr_frequency_i => evr_frequency,
evr_evt_rec_status_i => event_recorder_status,
evr_evt_rec_control_o => event_recorder_control_xuser,
evr_latency_measure_stat_i => evr_latency_measure_stat,
evr_latency_measure_ctrl_o => evr_latency_measure_ctrl,
mgt_status_i => mgt_status,
mgt_reset_o => mgt_reset_tmem_evr,
mem_clk_o => mem_clk,
mem_addr_o => mem_addr_tosca,
mem_data_i => mem_data
);
-- --------------------------------------------------------------------------
-- Measure EVR Clock (based on xuser_CLK)
-- --------------------------------------------------------------------------
clock_meas_inst : entity work.psi_common_clk_meas
generic map(
MasterFrequency_g => g_XUSER_CLK_FREQ,
MaxMeasFrequency_g => 150000000
)
port map(
ClkMaster => xuser_CLK,
Rst => xuser_RESET,
ClkTest => clk_evr,
FrequencyHz => evr_frequency
);
-- --------------------------------------------------------------------------
-- Measure EVR Clock (based on xuser_CLK)
-- --------------------------------------------------------------------------
clock_meas_inst : entity work.psi_common_clk_meas
generic map(
MasterFrequency_g => g_XUSER_CLK_FREQ,
MaxMeasFrequency_g => 150000000
)
port map(
ClkMaster => xuser_CLK,
Rst => xuser_RESET,
ClkTest => clk_evr,
FrequencyHz => evr_frequency
);
-- --------------------------------------------------------------------------
-- Event Latency Measurement for SW tests
-- --------------------------------------------------------------------------
lat_meas_block : block
type state_type is (armed, count);
signal state : state_type;
signal counter : unsigned(31 downto 0);
signal event_nr_sync, event_nr : std_logic_vector(7 downto 0);
signal event_detected : std_logic_vector(3 downto 0);
signal event_detected_sync : std_logic_vector(1 downto 0);
constant MAX_COUNT : unsigned(31 downto 0) := to_unsigned(g_XUSER_CLK_FREQ / 100, 32); -- MAX 10ms
begin
-- --------------------------------------------------------------------------
-- Event Latency Measurement for SW tests
-- --------------------------------------------------------------------------
lat_meas_block : block
type state_type is (armed, count);
signal state : state_type;
signal counter : unsigned(31 downto 0);
signal event_nr_sync, event_nr : std_logic_vector(7 downto 0);
signal event_detected : std_logic_vector(3 downto 0);
signal event_detected_sync : std_logic_vector(1 downto 0);
constant MAX_COUNT : unsigned(31 downto 0) := to_unsigned(g_XUSER_CLK_FREQ / 100, 32); -- MAX 10ms
begin
-- Process: filter events for matching event_nr register:
---------------------------------------------------------
ext_event_proc : process(clk_evr)
begin
if (rising_edge(clk_evr)) then
-- sync to MGT clock domain:
event_nr_sync <= evr_latency_measure_ctrl.event_nr;
event_nr <= event_nr_sync;
-- Process: filter events for matching event_nr register:
---------------------------------------------------------
ext_event_proc : process(clk_evr)
begin
if (rising_edge(clk_evr)) then
-- sync to MGT clock domain:
event_nr_sync <= evr_latency_measure_ctrl.event_nr;
event_nr <= event_nr_sync;
-- check if event has been detected and stretch pulse:
event_detected <= event_detected(2 downto 0) & '0';
if (decoder_event_valid = '1' and decoder_event = event_nr) then
event_detected <= (others => '1');
end if;
end if;
end process;
-- check if event has been detected and stretch pulse:
event_detected <= event_detected(2 downto 0) & '0';
if (decoder_event_valid = '1' and decoder_event = event_nr) then
event_detected <= (others => '1');
end if;
end if;
end process;
-- Process: Counter when configured event has been detected:
------------------------------------------------------------
lat_meas_proc : process(xuser_CLK, counter)
begin
if rising_edge(xuser_CLK) then
-- sync to user clock domain:
event_detected_sync <= event_detected_sync(0) & event_detected(3);
-- Process: Counter when configured event has been detected:
------------------------------------------------------------
lat_meas_proc : process(xuser_CLK, counter)
begin
if rising_edge(xuser_CLK) then
-- sync to user clock domain:
event_detected_sync <= event_detected_sync(0) & event_detected(3);
-- counter FSM:
---------------
case state is
-- counter is armed:
when armed =>
counter <= (others => '0');
-- start counting when event detected (rising edge):
if (event_detected_sync(1) = '0' and event_detected_sync(0) = '1') then
state <= count;
end if;
-- counter FSM:
---------------
case state is
-- counter is armed:
when armed =>
counter <= (others => '0');
-- start counting when event detected (rising edge):
if (event_detected_sync(1) = '0' and event_detected_sync(0) = '1') then
state <= count;
end if;
-- counting:
when count =>
-- count only up to 10ms, and stop:
if (counter < MAX_COUNT) then
counter <= counter + 1;
end if;
if (evr_latency_measure_ctrl.counter_arm = '1') then
state <= armed;
end if;
end case;
end if;
-- counting:
when count =>
-- count only up to 10ms, and stop:
if (counter < MAX_COUNT) then
counter <= counter + 1;
end if;
if (evr_latency_measure_ctrl.counter_arm = '1') then
state <= armed;
end if;
end case;
end if;
evr_latency_measure_stat.counter_val <= std_logic_vector(counter);
end process;
evr_latency_measure_stat.counter_val <= std_logic_vector(counter);
end process;
end block;
end block;
-- --------------------------------------------------------------------------
-- Add delay output
-- --------------------------------------------------------------------------
output_delay_block : block
signal rst0_s, rst1_s : std_logic; -- double stage sync for reset
signal usr_evt_shaped_s : std_logic_vector(4 downto 0);
signal usr_events_adj_s : std_logic_vector(4 downto 0);
signal usr_events_concat_s : std_logic_vector(4 downto 0);
begin
--*** double stage sync for reset ***--
proc_rst : process(clk_evr)
begin
if rising_edge(clk_evr) then
rst0_s <= xuser_RESET;
rst1_s <= rst0_s;
end if;
end process;
-- --------------------------------------------------------------------------
-- Add delay output
-- --------------------------------------------------------------------------
output_delay_block : block
signal rst0_s, rst1_s : std_logic; -- double stage sync for reset
signal usr_evt_shaped_s : std_logic_vector(4 downto 0);
signal usr_events_adj_s : std_logic_vector(4 downto 0);
signal usr_events_concat_s : std_logic_vector(4 downto 0);
begin
--*** double stage sync for reset ***--
proc_rst : process(clk_evr)
begin
if rising_edge(clk_evr) then
rst0_s <= xuser_RESET;
rst1_s <= rst0_s;
end if;
end process;
usr_events_concat_s <= usr_events_s & sos_event_s;
gene_adj_out : for i in 0 to 4 generate
--*** Adjust pulse length in clk cycles EVENT 0,1,2,3 ***
inst_pulslength_evt0 : entity work.psi_common_pulse_shaper
generic map(Duration_g => g_EVT_DURATION(i),
HoldIn_g => false,
HoldOff_g => g_EVT_HOLDOFF(i))
port map(Clk => clk_evr,
Rst => rst1_s,
InPulse => usr_events_concat_s(i),
OutPulse => usr_evt_shaped_s(i));
usr_events_concat_s <= usr_events_s & sos_event_s;
--*** delay adjust EVENT 0,1,2,3***
inst_adjdelay_evt0 : entity work.psi_common_delay
generic map(Width_g => 1,
Delay_g => g_EVT_DELAY(i),
Resource_g => "AUTO",
BramThreshold_g => 128,
RstState_g => True,
RamBehavior_g => "RBW")
port map(Clk => clk_evr,
Rst => rst1_s,
InData(0) => usr_evt_shaped_s(i),
InVld => '1',
OutData(0)=> usr_events_adj_s(i));
end generate;
gene_adj_out : for i in 0 to 4 generate
usr_events_adj_o <= usr_events_adj_s(4 downto 1);
sos_events_adj_o <= usr_events_adj_s(0);
end block;
-- --------------------------------------------------------------------------
-- port mapping
-- --------------------------------------------------------------------------
clk_evr_o <= clk_evr;
mgt_status_o <= mgt_status;
debug <= debug_data;
--*** Adjust pulse length in clk cycles EVENT 0,1,2,3 ***
inst_pulslength_evt0 : entity work.psi_common_pulse_shaper2
generic map(HoldIn_g => false,
HoldOff_g => g_EVT_HOLDOFF(i),
MaxDuration_g => MaxDuration_c,
RstPol_g => '1')
port map(clk_i => clk_evr,
rst_i => rst1_s,
width_i => usr_event_width_i(i),
dat_i => usr_events_concat_s(i),
dat_o => usr_evt_shaped_s(i));
--*** delay adjust EVENT 0,1,2,3***
inst_adjdelay_evt0 : entity work.psi_common_delay2
generic map(Width_g => 1,
Resource_g => "AUTO",
BramThreshold_g => 128,
MaxDelay_g => MaxDelay_c,
RStPol_g => '1',
RstState_g => True,
RamBehavior_g => "RBW")
port map(clk_i => clk_evr,
rst_i => rst1_s,
str_i => '1',
del_i => usr_event_delay_i(i),
dat_o(0) => usr_events_adj_s(i),
dat_i(0) => usr_evt_shaped_s(i)
);
end generate;
usr_events_adj_o <= usr_events_adj_s(4 downto 1);
sos_events_adj_o <= usr_events_adj_s(0);
end block;
-- --------------------------------------------------------------------------
-- port mapping
-- --------------------------------------------------------------------------
clk_evr_o <= clk_evr;
mgt_status_o <= mgt_status;
debug <= debug_data;
end rtl;
-- ----------------------------------------------------------------------------

View File

@ -12,6 +12,7 @@
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.psi_common_math_pkg.all;
package evr320_pkg is
@ -61,8 +62,12 @@ package evr320_pkg is
counter_val : std_logic_vector(31 downto 0);
end record;
--*** Type record and constant for new feature pulse width & delay ***
constant MaxDuration_c : positive := 64; -- defines maximum pulse width to add on user events pulse output, in recovery clock cycles
constant MaxDelay_c : positive := 32; -- defines maximum delay to add on user events pulse output, in recovery clock cycles
type typ_arr_width is array (4 downto 0) of std_logic_vector(log2ceil(MaxDuration_c)-1 downto 0);
type typ_arr_delay is array (4 downto 0) of std_logic_vector(log2ceil(MaxDelay_c)-1 downto 0);
type typ_arr_nat is array (4 downto 0) of natural;
type typ_arr_pos is array (4 downto 0) of positive;
-- --------------------------------------------------------------------------

View File

@ -33,8 +33,8 @@ add_sources $LibPath/Firmware/VHDL/psi_common/hdl {
psi_common_pulse_cc.vhd \
psi_common_async_fifo.vhd \
psi_common_clk_meas.vhd \
psi_common_pulse_shaper.vhd \
psi_common_delay.vhd \
psi_common_pulse_shaper2.vhd \
psi_common_delay2.vhd \
} -tag psi_common
# EVR320 Decoder

View File

@ -21,459 +21,475 @@ context uvvm_util.uvvm_util_context;
-- Work library (application) --------------------------------------------------
library work;
use work.evr320_pkg.all;
use work.psi_common_math_pkg.all;
entity evr320_ifc1210_wrapper_tb is
end entity;
architecture testbench of evr320_ifc1210_wrapper_tb is
---------------------------------------------------------------------------
-- System
---------------------------------------------------------------------------
constant C_RXUSRCLK_CYCLE : time := 7 ns;
constant C_USRCLK_CYCLE : time := 8 ns;
constant C_EVT_NR : integer := 4;
constant C_MEM_DATA_WIDTH : integer := 32; -- 32|64 (64 bit used for tosca2 on ifc1210)
constant C_EVENT_RECORDER : boolean := true;
constant C_EVENT_REC_FLAGS : std_logic_vector(11 downto 6) := B"1101_11";
constant g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#;
constant g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
constant g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
constant g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
constant g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
---------------------------------------------------------------------------
-- System
---------------------------------------------------------------------------
constant C_RXUSRCLK_CYCLE : time := 7 ns;
constant C_USRCLK_CYCLE : time := 8 ns;
constant C_EVT_NR : integer := 4;
constant C_MEM_DATA_WIDTH : integer := 32; -- 32|64 (64 bit used for tosca2 on ifc1210)
constant C_EVENT_RECORDER : boolean := true;
constant C_EVENT_REC_FLAGS : std_logic_vector(11 downto 6) := B"1101_11";
constant g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#;
constant g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
constant g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
constant g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
constant g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
---------------------------------------------------------------------------
-- MGT stream
---------------------------------------------------------------------------
type mgt_stream_sample_type is record
data : std_logic_vector(7 downto 0);
data_k : std_logic_vector(0 downto 0);
event : std_logic_vector(7 downto 0);
event_k : std_logic_vector(0 downto 0);
end record mgt_stream_sample_type;
---------------------------------------------------------------------------
-- MGT stream
---------------------------------------------------------------------------
type mgt_stream_sample_type is record
data : std_logic_vector(7 downto 0);
data_k : std_logic_vector(0 downto 0);
event : std_logic_vector(7 downto 0);
event_k : std_logic_vector(0 downto 0);
end record mgt_stream_sample_type;
type mgt_stream_type is array (natural range <>) of mgt_stream_sample_type;
type mgt_stream_type is array (natural range <>) of mgt_stream_sample_type;
signal mgt_stream_index : integer range 0 to 511 := 0;
signal mgt_stream : mgt_stream_type(511 downto 0) := (others => (others => (others => '0')));
signal mgt_stream_index : integer range 0 to 511 := 0;
signal mgt_stream : mgt_stream_type(511 downto 0) := (others => (others => (others => '0')));
-----------------------------------------------------------------------------
-- Timing decoder interface
-----------------------------------------------------------------------------
signal usr_clk : std_logic := '0';
signal evr_params : typ_evr320_params;
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
-----------------------------------------------------------------------------
-- Timing decoder interface
-----------------------------------------------------------------------------
signal usr_clk : std_logic := '0';
signal evr_params : typ_evr320_params;
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
-- Decoder stream
type dec_stream_type is record
data : std_logic_vector(7 downto 0);
addr : std_logic_vector(10 downto 0);
end record dec_stream_type;
type dec_stream_check_arr is array (natural range <>) of dec_stream_type;
-- Decoder stream
type dec_stream_type is record
data : std_logic_vector(7 downto 0);
addr : std_logic_vector(10 downto 0);
end record dec_stream_type;
type dec_stream_check_arr is array (natural range <>) of dec_stream_type;
signal dec_stream_data : std_logic_vector(7 downto 0) := (others => '0');
signal dec_stream_addr : std_logic_vector(10 downto 0) := (others => '0');
signal dec_stream_valid : std_logic;
signal dec_stream_check : dec_stream_check_arr(0 to 2047);
signal dec_stream_recv_bytes : integer range 0 to 2047;
signal dec_stream_data : std_logic_vector(7 downto 0) := (others => '0');
signal dec_stream_addr : std_logic_vector(10 downto 0) := (others => '0');
signal dec_stream_valid : std_logic;
signal dec_stream_check : dec_stream_check_arr(0 to 2047);
signal dec_stream_recv_bytes : integer range 0 to 2047;
type segment_data_arr is array (natural range <>) of std_logic_vector(7 downto 0);
signal segment_addr : std_logic_vector(7 downto 0);
signal segment_data : segment_data_arr(0 to 2047);
signal segment_length : natural range 0 to 2047;
type segment_data_arr is array (natural range <>) of std_logic_vector(7 downto 0);
signal segment_addr : std_logic_vector(7 downto 0);
signal segment_data : segment_data_arr(0 to 2047);
signal segment_length : natural range 0 to 2047;
constant FILTER_ADDRESS : std_logic_vector(11 downto 0) := x"028";
constant FILTER_NUM_BYTES : integer := 8;
constant STIMULI_RUNS : integer := 2;
constant FILTER_ADDRESS : std_logic_vector(11 downto 0) := x"028";
constant FILTER_NUM_BYTES : integer := 8;
constant STIMULI_RUNS : integer := 2;
signal filter_data, filter_data_check : std_logic_vector(63 downto 0) := (others => '0');
signal filter_valid : std_logic := '0';
signal filter_data, filter_data_check : std_logic_vector(63 downto 0) := (others => '0');
signal filter_valid : std_logic := '0';
signal tmem_i : tmem_bus_in_t;
signal tmem_o : tmem_bus_out_t;
signal tmem_clk : std_logic;
signal tmem_rst : std_logic;
signal tmem_data_rd : std_logic_vector(63 downto 0);
signal tmem_i : tmem_bus_in_t;
signal tmem_o : tmem_bus_out_t;
signal tmem_clk : std_logic;
signal tmem_rst : std_logic;
signal tmem_data_rd : std_logic_vector(63 downto 0);
signal tick1sec : std_logic;
signal tick1sec : std_logic;
alias rxlos is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rst : std_logic>>;
alias clk_evr is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.clk_evr : std_logic>>;
alias rxdata is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_data : std_logic_vector(15 downto 0)>>;
alias rxcharisk is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_charisk : std_logic_vector(1 downto 0)>>;
alias sos_event is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_sos_event : std_logic>>;
alias usr_events is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_usr_events : std_logic_vector(3 downto 0)>>;
alias evr_stable is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.evr_stable : std_logic>>;
alias rxlos is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rst : std_logic>>;
alias clk_evr is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.clk_evr : std_logic>>;
alias rxdata is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_data : std_logic_vector(15 downto 0)>>;
alias rxcharisk is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_charisk : std_logic_vector(1 downto 0)>>;
alias sos_event is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_sos_event : std_logic>>;
alias usr_events is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_usr_events : std_logic_vector(3 downto 0)>>;
alias evr_stable is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.evr_stable : std_logic>>;
--*** stimuli for delay & pulse width ***
signal usr_event_width_sti : typ_arr_width := (to_uslv(2, log2ceil(MaxDuration_c)), --sos set to 2
to_uslv(3, log2ceil(MaxDuration_c)), --0
to_uslv(4, log2ceil(MaxDuration_c)), --1
to_uslv(5, log2ceil(MaxDuration_c)), --2
to_uslv(6, log2ceil(MaxDuration_c)) --3
);
signal usr_event_delay_sti : typ_arr_delay := (to_uslv(2, log2ceil(MaxDelay_c)), --sos set to 2
to_uslv(3, log2ceil(MaxDelay_c)), --0
to_uslv(4, log2ceil(MaxDelay_c)), --1
to_uslv(5, log2ceil(MaxDelay_c)), --2
to_uslv(6, log2ceil(MaxDelay_c)) --3
);
begin
tmem_o.TMEM_BUSY_o <= '0';
tmem_o.TMEM_PIPE_o <= "10";
tmem_o.TMEM_BUSY_o <= '0';
tmem_o.TMEM_PIPE_o <= "10";
-----------------------------------------------------------------------------
-- Timing decoder
-----------------------------------------------------------------------------
evr320_ifc1210_wrapper_inst : entity work.evr320_ifc1210_wrapper
generic map(
g_EVT_DURATION => (1, 1, 1, 1, 1),
g_EVT_HOLDOFF => (0, 0, 0, 0, 0),
g_EVT_DELAY => (1, 1, 1, 1, 1),
g_MGT_LOCATION => "GTXE1_X0Y16", -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY => "SFEL", -- "HIPA" | "SFEL"
g_EVENT_RECORDER => C_EVENT_RECORDER, -- enable/disable Event Recorder functionality
g_XUSER_CLK_FREQ => 125000000 -- Xuser Clk Frequency in Hz
)
port map(
tick1sec_i => tick1sec,
--------------------------------------------------------------------------
-- Debug interface
--------------------------------------------------------------------------
debug_clk => open,
debug => open,
--------------------------------------------------------------------------
-- TOSCA2 TMEM interface
--------------------------------------------------------------------------
xuser_CLK => tmem_clk,
xuser_RESET => tmem_rst,
xuser_TMEM_ENA => tmem_i.TMEM_ENA_i,
xuser_TMEM_WE => tmem_i.TMEM_WE_i,
xuser_TMEM_ADD => tmem_i.TMEM_ADD_i(13 downto 3),
xuser_TMEM_DATW => tmem_i.TMEM_DATW_i,
xuser_TMEM_DATR => tmem_o.TMEM_DATR_o,
-- ------------------------------------------------------------------------
-- MGT Interface
-- ------------------------------------------------------------------------
mgt_refclk_i => '0',
mgt_sfp_los_i => '0',
mgt_rx_n => '0',
mgt_rx_p => '0',
mgt_tx_n => open,
mgt_tx_p => open,
mgt_status_o => open,
mgt_control_i => (others => '0'),
---------------------------------------------------------------------------
-- User interface MGT clock
---------------------------------------------------------------------------
clk_evr_o => open,
usr_events_o => open,
sos_event_o => open,
usr_events_adj_o => open,
sos_events_adj_o => open,
--------------------------------------------------------------------------
-- Decoder axi stream interface, User clock
--------------------------------------------------------------------------
stream_clk_i => '1',
stream_data_o => open,
stream_addr_o => open,
stream_valid_o => open
);
-----------------------------------------------------------------------------
-- Timing decoder
-----------------------------------------------------------------------------
evr320_ifc1210_wrapper_inst : entity work.evr320_ifc1210_wrapper
generic map(
g_EVT_HOLDOFF => (0,0,0,0,0),
g_MGT_LOCATION => "GTXE1_X0Y16", -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY => "SFEL", -- "HIPA" | "SFEL"
g_EVENT_RECORDER => C_EVENT_RECORDER, -- enable/disable Event Recorder functionality
g_XUSER_CLK_FREQ => 125000000 -- Xuser Clk Frequency in Hz
)
port map(
--------------------------------------------------------------------------
-- Debug interface
--------------------------------------------------------------------------
usr_event_width_i => usr_event_width_sti,
usr_event_delay_i => usr_event_delay_sti,
debug_clk => open,
debug => open,
--------------------------------------------------------------------------
-- TOSCA2 TMEM interface
--------------------------------------------------------------------------
xuser_CLK => tmem_clk,
xuser_RESET => tmem_rst,
xuser_TMEM_ENA => tmem_i.TMEM_ENA_i,
xuser_TMEM_WE => tmem_i.TMEM_WE_i,
xuser_TMEM_ADD => tmem_i.TMEM_ADD_i(13 downto 3),
xuser_TMEM_DATW => tmem_i.TMEM_DATW_i,
xuser_TMEM_DATR => tmem_o.TMEM_DATR_o,
-- ------------------------------------------------------------------------
-- MGT Interface
-- ------------------------------------------------------------------------
mgt_refclk_i => '0',
mgt_sfp_los_i => '0',
mgt_rx_n => '0',
mgt_rx_p => '0',
mgt_tx_n => open,
mgt_tx_p => open,
mgt_status_o => open,
mgt_control_i => (others => '0'),
---------------------------------------------------------------------------
-- User interface MGT clock
---------------------------------------------------------------------------
clk_evr_o => open,
usr_events_o => open,
sos_event_o => open,
usr_events_adj_o => open,
sos_events_adj_o => open,
--------------------------------------------------------------------------
-- Decoder axi stream interface, User clock
--------------------------------------------------------------------------
stream_clk_i => '1',
stream_data_o => open,
stream_addr_o => open,
stream_valid_o => open
);
gen_pulse(tick1sec, '1', usr_clk, 1, "");
-----------------------------------------------------------------------------
-- MGT / User clock
-----------------------------------------------------------------------------
clock_generator(usr_clk, C_USRCLK_CYCLE);
tmem_clk <= usr_clk;
gen_pulse(tick1sec, '1', usr_clk, 1, "");
-----------------------------------------------------------------------------
-- MGT / User clock
-----------------------------------------------------------------------------
clock_generator(usr_clk, C_USRCLK_CYCLE);
tmem_clk <= usr_clk;
-- Simulate MGT Clock
mgt_clk_proc : process
begin
clk_evr <= force in '0';
loop
wait for C_RXUSRCLK_CYCLE / 2;
clk_evr <= force in not (clk_evr);
end loop;
end process;
-- Simulate MGT Clock
mgt_clk_proc : process
begin
clk_evr <= force in '0';
loop
wait for C_RXUSRCLK_CYCLE / 2;
clk_evr <= force in not (clk_evr);
end loop;
end process;
-----------------------------------------------------------------------------
-- Decoder reset due to MGT main status
-----------------------------------------------------------------------------
process
begin
rxlos <= force in '1';
tmem_rst <= '1';
wait for 50 ns;
wait until (falling_edge(clk_evr));
rxlos <= force in '0';
tmem_rst <= '0';
wait;
end process;
-----------------------------------------------------------------------------
-- Decoder reset due to MGT main status
-----------------------------------------------------------------------------
process
begin
rxlos <= force in '1';
tmem_rst <= '1';
wait for 50 ns;
wait until (falling_edge(clk_evr));
rxlos <= force in '0';
tmem_rst <= '0';
wait;
end process;
-----------------------------------------------------------------------------
-- Read stimuli file
-----------------------------------------------------------------------------
file_blk : block
file file_stimuli : text;
type parse_fsm_state is (idle, seg_start, seg_addr, seg_Wait, seg_payload, seg_payload_wait, seg_done);
begin
process
variable file_line : line;
variable data, event : std_logic_vector(7 downto 0);
variable data_k, event_k : std_logic_vector(0 downto 0);
variable space : character;
variable i : integer;
variable parse_fsm : parse_fsm_state := idle;
variable payload_cnt : integer range 0 to 2047;
variable event_cnt_total : integer := 0;
variable event_cnt_0 : integer := 0;
variable event_cnt_1 : integer := 0;
variable event_cnt_2 : integer := 0;
variable event_cnt_3 : integer := 0;
variable event_cnt_user : integer := 0;
begin
file_open(file_stimuli, "../tb/stimuli_mgt.dat", read_mode);
readline(file_stimuli, file_line); -- comment
readline(file_stimuli, file_line); -- comment
i := 0;
-- read line by line from .dat file:
while not endfile(file_stimuli) loop
readline(file_stimuli, file_line);
hread(file_line, event);
read(file_line, event_k);
read(file_line, space);
read(file_line, space);
hread(file_line, data);
read(file_line, space);
read(file_line, data_k);
-- write to array:
mgt_stream(i).data <= data;
mgt_stream(i).data_k <= data_k;
mgt_stream(i).event <= event;
mgt_stream(i).event_k <= event_k;
mgt_stream_index <= i;
--debug output:
--log(ID_SEGMENT_DATA, "stimuli file: i=" & integer'image(i) & " event=0x" & to_string(event, HEX) & " k=" & to_string(event_k, HEX)
-- & " data=0x" & to_string(data, HEX) & " k=" & to_string(data_k, HEX) & " ");
-----------------------------------------------------------------------------
-- Read stimuli file
-----------------------------------------------------------------------------
file_blk : block
file file_stimuli : text;
type parse_fsm_state is (idle, seg_start, seg_addr, seg_Wait, seg_payload, seg_payload_wait, seg_done);
begin
process
variable file_line : line;
variable data, event : std_logic_vector(7 downto 0);
variable data_k, event_k : std_logic_vector(0 downto 0);
variable space : character;
variable i : integer;
variable parse_fsm : parse_fsm_state := idle;
variable payload_cnt : integer range 0 to 2047;
variable event_cnt_total : integer := 0;
variable event_cnt_0 : integer := 0;
variable event_cnt_1 : integer := 0;
variable event_cnt_2 : integer := 0;
variable event_cnt_3 : integer := 0;
variable event_cnt_user : integer := 0;
begin
file_open(file_stimuli, "../tb/stimuli_mgt.dat", read_mode);
readline(file_stimuli, file_line); -- comment
readline(file_stimuli, file_line); -- comment
i := 0;
-- read line by line from .dat file:
while not endfile(file_stimuli) loop
readline(file_stimuli, file_line);
hread(file_line, event);
read(file_line, event_k);
read(file_line, space);
read(file_line, space);
hread(file_line, data);
read(file_line, space);
read(file_line, data_k);
-- write to array:
mgt_stream(i).data <= data;
mgt_stream(i).data_k <= data_k;
mgt_stream(i).event <= event;
mgt_stream(i).event_k <= event_k;
mgt_stream_index <= i;
--debug output:
--log(ID_SEGMENT_DATA, "stimuli file: i=" & integer'image(i) & " event=0x" & to_string(event, HEX) & " k=" & to_string(event_k, HEX)
-- & " data=0x" & to_string(data, HEX) & " k=" & to_string(data_k, HEX) & " ");
-- Parse only segment:
----------------------
case (parse_fsm) is
when idle =>
if (data = x"5C" and data_k = "1") then -- check if frame start
parse_fsm := seg_start;
end if;
when seg_start =>
parse_fsm := seg_addr;
when seg_addr =>
segment_addr <= data;
parse_fsm := seg_wait;
when seg_wait =>
parse_fsm := seg_payload;
payload_cnt := 0;
when seg_payload =>
if (data = x"3C" and data_k = "1") then -- check if frame end
parse_fsm := seg_done;
else
segment_data(payload_cnt) <= data;
parse_fsm := seg_payload_wait;
segment_length <= payload_cnt + 1;
end if;
when seg_payload_wait =>
payload_cnt := payload_cnt + 1;
parse_fsm := seg_payload;
when seg_done =>
-- done
end case;
i := i + 1;
end loop;
file_close(file_stimuli);
wait;
end process;
end block;
-- Parse only segment:
----------------------
case (parse_fsm) is
when idle =>
if (data = x"5C" and data_k = "1") then -- check if frame start
parse_fsm := seg_start;
end if;
when seg_start =>
parse_fsm := seg_addr;
when seg_addr =>
segment_addr <= data;
parse_fsm := seg_wait;
when seg_wait =>
parse_fsm := seg_payload;
payload_cnt := 0;
when seg_payload =>
if (data = x"3C" and data_k = "1") then -- check if frame end
parse_fsm := seg_done;
else
segment_data(payload_cnt) <= data;
parse_fsm := seg_payload_wait;
segment_length <= payload_cnt + 1;
end if;
when seg_payload_wait =>
payload_cnt := payload_cnt + 1;
parse_fsm := seg_payload;
when seg_done =>
-- done
end case;
i := i + 1;
end loop;
file_close(file_stimuli);
wait;
end process;
end block;
---------------------------------------------------------
-- Wait for Start of Sequence Event
---------------------------------------------------------
process
begin
wait until rising_edge(sos_event);
log(ID_CTRL, "Start of Sequence Event Received: " & to_string(std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8)), HEX, AS_IS, INCL_RADIX)); -- change to await_value
end process;
---------------------------------------------------------
-- Wait for Start of Sequence Event
---------------------------------------------------------
process
begin
wait until rising_edge(sos_event);
log(ID_CTRL, "Start of Sequence Event Received: " & to_string(std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8)), HEX, AS_IS, INCL_RADIX)); -- change to await_value
end process;
--------------------------------------------------------------------------
-- Stimuli MGT
--------------------------------------------------------------------------
process
begin
wait until rising_edge(clk_evr);
for b in 0 to STIMULI_RUNS - 1 loop
log(ID_LOG_HDR, "Send stimuli stream to MGT - RUN " & to_string(b + 1));
for idx in 0 to mgt_stream_index loop
--log(ID_FRAME_DATA, to_string(mgt_stream(idx).data, HEX), to_string(mgt_stream(idx).event, HEX));
wait until rising_edge(clk_evr);
rxdata <= force out mgt_stream(idx).data & mgt_stream(idx).event;
rxcharisk <= force out mgt_stream(idx).data_k & mgt_stream(idx).event_k;
end loop;
wait for 3 us;
end loop;
wait;
end process;
--------------------------------------------------------------------------
-- Stimuli MGT
--------------------------------------------------------------------------
process
begin
wait until rising_edge(clk_evr);
for b in 0 to STIMULI_RUNS - 1 loop
log(ID_LOG_HDR, "Send stimuli stream to MGT - RUN " & to_string(b + 1));
for idx in 0 to mgt_stream_index loop
--log(ID_FRAME_DATA, to_string(mgt_stream(idx).data, HEX), to_string(mgt_stream(idx).event, HEX));
wait until rising_edge(clk_evr);
rxdata <= force out mgt_stream(idx).data & mgt_stream(idx).event;
rxcharisk <= force out mgt_stream(idx).data_k & mgt_stream(idx).event_k;
end loop;
wait for 3 us;
end loop;
wait;
end process;
-----------------------------------------------------------------------------
-- Main Process
-----------------------------------------------------------------------------
process
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
constant c_TB_NAME : string := "evr320_decoder_tb";
variable latency_cnt_val : unsigned(31 downto 0);
-----------------------------------------------------------------------------
-- Main Process
-----------------------------------------------------------------------------
process
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
constant c_TB_NAME : string := "evr320_decoder_tb";
variable latency_cnt_val : unsigned(31 downto 0);
begin
disable_log_msg(ID_GEN_PULSE);
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Start Simulation of evr320 decoder", C_SCOPE);
--------------------------------------------------------------------------
begin
disable_log_msg(ID_GEN_PULSE);
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Start Simulation of evr320 decoder", C_SCOPE);
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- Get out of reset, enable events
--------------------------------------------------------------------------
evr_params.event_enable(0) <= '0' when g_EVENT_NR_0 = 0 else '1';
evr_params.event_enable(1) <= '0' when g_EVENT_NR_1 = 0 else '1';
evr_params.event_enable(2) <= '0' when g_EVENT_NR_2 = 0 else '1';
evr_params.event_enable(3) <= '0' when g_EVENT_NR_3 = 0 else '1';
evr_params.event_numbers(0) <= std_logic_vector(to_unsigned(g_EVENT_NR_0, 8));
evr_params.event_numbers(1) <= std_logic_vector(to_unsigned(g_EVENT_NR_1, 8));
evr_params.event_numbers(2) <= std_logic_vector(to_unsigned(g_EVENT_NR_2, 8));
evr_params.event_numbers(3) <= std_logic_vector(to_unsigned(g_EVENT_NR_3, 8));
evr_params.cs_min_cnt <= X"00000000";
evr_params.cs_min_time <= X"00000000";
mem_addr <= x"000";
await_value(rxlos, '0', 0 ns, 10 us, FAILURE, "wait for release RX LOS");
--------------------------------------------------------------------------
-- Get out of reset, enable events
--------------------------------------------------------------------------
evr_params.event_enable(0) <= '0' when g_EVENT_NR_0 = 0 else '1';
evr_params.event_enable(1) <= '0' when g_EVENT_NR_1 = 0 else '1';
evr_params.event_enable(2) <= '0' when g_EVENT_NR_2 = 0 else '1';
evr_params.event_enable(3) <= '0' when g_EVENT_NR_3 = 0 else '1';
evr_params.event_numbers(0) <= std_logic_vector(to_unsigned(g_EVENT_NR_0, 8));
evr_params.event_numbers(1) <= std_logic_vector(to_unsigned(g_EVENT_NR_1, 8));
evr_params.event_numbers(2) <= std_logic_vector(to_unsigned(g_EVENT_NR_2, 8));
evr_params.event_numbers(3) <= std_logic_vector(to_unsigned(g_EVENT_NR_3, 8));
evr_params.cs_min_cnt <= X"00000000";
evr_params.cs_min_time <= X"00000000";
mem_addr <= x"000";
await_value(rxlos, '0', 0 ns, 10 us, FAILURE, "wait for release RX LOS");
-- overwrite evr_stable flag:
evr_stable <= force '1';
-- overwrite evr_stable flag:
evr_stable <= force '1';
-- enable sos event and set event number:
TMEM_BUS_WRITE(seqid => "A00_001",
tmem_add => x"00_0040",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_2001",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
-- enable sos event and set event number:
TMEM_BUS_WRITE(seqid => "A00_001",
tmem_add => x"00_0040",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_2001",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
wait for 20 ns;
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_001",
tmem_add => x"00_0040",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_001",
tmem_add => x"00_0040",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
wait for 20 ns;
check_value(tmem_data_rd, x"0000_0000_0000_2001", ERROR, "TMEM Write/Read check: EVR SOS Event Cfg");
check_value(tmem_data_rd, x"0000_0000_0000_2001", ERROR, "TMEM Write/Read check: EVR SOS Event Cfg");
-- latency measurement: set event nr:
TMEM_BUS_WRITE(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_0020",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
-- latency measurement: set event nr:
TMEM_BUS_WRITE(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_0020",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
wait for 20 ns;
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
wait for 20 ns;
check_value(tmem_data_rd, x"0000_0000_0000_0020", ERROR, "TMEM Write/Read check: lat. meas. event nr");
check_value(tmem_data_rd, x"0000_0000_0000_0020", ERROR, "TMEM Write/Read check: lat. meas. event nr");
-- 1. check latency measurement counter:
----------------------------------------
await_value(sos_event, '1', 0 ns, 2 us, ERROR, "wait for sos event");
wait for 2000 ns;
latency_cnt_val := x"00000000";
-- 1. check latency measurement counter:
----------------------------------------
await_value(sos_event, '1', 0 ns, 2 us, ERROR, "wait for sos event");
wait for 2000 ns;
latency_cnt_val := x"00000000";
-- read latency measurement counter without rearm:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(63 downto 32));
-- read latency measurement counter without rearm:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(63 downto 32));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"000000F5", x"000000FE", ERROR, "Latency Counter Value (no-rearm) Check after 2us");
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"000000F5", x"000000FE", ERROR, "Latency Counter Value (no-rearm) Check after 2us");
-- 2. read latency measurement counter again with rearm:
--------------------------------------------------------
latency_cnt_val := x"00000000";
-- 2. read latency measurement counter again with rearm:
--------------------------------------------------------
latency_cnt_val := x"00000000";
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"000000FA", x"00000102", ERROR, "Latency Counter Value (rearm) Check directly after first read");
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"000000FA", x"00000102", ERROR, "Latency Counter Value (rearm) Check directly after first read");
-- read 2. time rearm latency counter which should be cleared now:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
check_value(latency_cnt_val, x"00000000", ERROR, "Check if counter is cleared");
-- read 2. time rearm latency counter which should be cleared now:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
check_value(latency_cnt_val, x"00000000", ERROR, "Check if counter is cleared");
-- 4. read latency measurement counter with rearm:
--------------------------------------------------
await_value(sos_event, '1', 0 ns, 3 us, ERROR, "wait for sos event");
wait for 1 us;
-- 4. read latency measurement counter with rearm:
--------------------------------------------------
await_value(sos_event, '1', 0 ns, 3 us, ERROR, "wait for sos event");
wait for 1 us;
-- read counter and rearm:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"0000007A", x"00000080", ERROR, "Latency Counter Value (rearm) Check after 1us");
-- read counter and rearm:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"0000007A", x"00000080", ERROR, "Latency Counter Value (rearm) Check after 1us");
--------------------------------------------------------------------------
-- Test Done
--------------------------------------------------------------------------
wait for 1000 ns; -- to allow some time for completion
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
-- ------------------------------------------------------------------------
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
-- ------------------------------------------------------------------------
-- assert error if UVVM mismatch flag is 1 => upstream info for scripts/jenkins
assert shared_uvvm_status.mismatch_on_expected_simulation_errors_or_worse = 0 report "###ERROR### - UVVM Mismatch Errors with Expected Errors -> Check Log for details" severity ERROR;
std.env.stop(0);
wait; -- stop simulation
--------------------------------------------------------------------------
-- Test Done
--------------------------------------------------------------------------
wait for 1000 ns; -- to allow some time for completion
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
-- ------------------------------------------------------------------------
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
-- ------------------------------------------------------------------------
-- assert error if UVVM mismatch flag is 1 => upstream info for scripts/jenkins
assert shared_uvvm_status.mismatch_on_expected_simulation_errors_or_worse = 0 report "###ERROR### - UVVM Mismatch Errors with Expected Errors -> Check Log for details" severity ERROR;
std.env.stop(0);
wait; -- stop simulation
end process;
end process;
end architecture testbench;