diff --git a/libraries/base/diag/src/vhdl/mms_diag_rx_seq.vhd b/libraries/base/diag/src/vhdl/mms_diag_rx_seq.vhd index b7a4d348a96b67a2c5edb97f15717d3196cf00d0..2105fac3e6e27dd307cfa1d86e6fe502989c6e8c 100644 --- a/libraries/base/diag/src/vhdl/mms_diag_rx_seq.vhd +++ b/libraries/base/diag/src/vhdl/mms_diag_rx_seq.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------- -- --- Copyright (C) 2010 +-- 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 @@ -20,106 +20,216 @@ -- ------------------------------------------------------------------------------- +-- Purpose: Provide MM access via slave register to diag_rx_seq +-- Description: +-- +-- Each DP stream has its own diag_rx_seq and its own MM control register. +-- The MM control registers are accessible via a single MM port thanks to +-- the common_mem_mux. Each single MM control register is defined as: +-- +-- 31 24 23 16 15 8 7 0 wi +-- |-----------------|-----------------|-----------------|-----------------| +-- | select = [1], enable = [0] | 0 +-- |-----------------------------------------------------------------------| +-- | res_val_n = [1], res_ok_n = [0] | 1 +-- |-----------------------------------------------------------------------| +-- +-- . Results +-- When res_val_n = '1' then no valid data is being received. When +-- res_val_n = '0' then at least two valid data have been received so the +-- diag_rx_seq can detect whether the subsequent data is ok. When res_ok_n +-- = '0' then indeed all data that has been received so far is correct. +-- When res_ok_n = '0' then at least 1 data word was received with errors. +-- Once res_ok_n goes high it remains high. +-- +-- . g_data_w and g_seq_dat_w +-- The DP streaming data field is c_dp_stream_data_w bits wide but only +-- g_data_w bits are used. The g_seq_dat_w must be >= 1 and <= g_data_w. +-- If g_seq_dat_w < g_data_w then the data carries replicated copies of +-- the g_seq_dat_w. The maximum g_seq_dat_w depends on the pseudo random +-- data width of the LFSR sequeces in common_lfsr_sequences_pkg and on +-- whether timing closure can still be achieved for wider g_seq_dat_w. +-- Thanks to the replication a smaller g_seq_dat_w can be used to provide +-- CNTR or LFSR data for the DP data. If the higher bits do notmatch the +-- sequence in the lower bits, then the rx data is forced to -1, and that +-- will then be detected and reported by u_diag_rx_seq as a sequence error. + + LIBRARY IEEE, common_lib, dp_lib; USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; ENTITY mms_diag_rx_seq IS GENERIC ( - g_nof_diag_inst : NATURAL := 1; - g_dat_w : NATURAL := c_word_w; -- >= 1, test data width - g_sim : BOOLEAN := FALSE + g_nof_streams : NATURAL := 1; + g_seq_dat_w : NATURAL := c_word_w; -- >= 1, test sequence data width + g_data_w : NATURAL := c_word_w -- >= g_seq_dat_w, user data width ); PORT ( -- Clocks and reset - mm_rst : IN STD_LOGIC; - mm_clk : IN STD_LOGIC; - st_clk : IN STD_LOGIC; + mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk + mm_clk : IN STD_LOGIC; -- MM bus clock + dp_rst : IN STD_LOGIC; -- reset synchronous with dp_clk + dp_clk : IN STD_LOGIC; -- DP streaming bus clock -- Memory Mapped Slave - mm_sla_in : IN t_mem_mosi; -- master out slave in - mm_sla_out : OUT t_mem_miso; -- master in slave out + reg_mosi : IN t_mem_mosi; -- multiplexed port for g_nof_streams MM control/status registers + reg_miso : OUT t_mem_miso; -- Streaming interface - rx_snk_in : IN t_dp_sosi_arr(g_nof_diag_inst-1 DOWNTO 0) -- source out sink in + rx_snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) ); END mms_diag_rx_seq; ARCHITECTURE str OF mms_diag_rx_seq IS - CONSTANT c_latency : NATURAL := 1; -- read latency - CONSTANT c_init_sl : STD_LOGIC := '0'; -- optional, init all dat words to std_logic '0', '1' or 'X' - CONSTANT c_init_reg : STD_LOGIC_VECTOR(c_mem_reg_init_w-1 DOWNTO 0) := (OTHERS => '0'); - CONSTANT c_nof_mm_regs : NATURAL := 4+g_nof_diag_inst; - CONSTANT c_mm_addr_w : NATURAL := ceil_log2(c_nof_mm_regs); - - CONSTANT c_mem_rec : t_c_mem := (c_latency, c_mm_addr_w, c_word_w, c_nof_mm_regs, c_init_sl); - - SIGNAL out_reg : STD_LOGIC_VECTOR(c_nof_mm_regs*c_word_w-1 DOWNTO 0); - SIGNAL in_reg : STD_LOGIC_VECTOR(c_nof_mm_regs*c_word_w-1 DOWNTO 0); - + -- Define the actual size of the MM slave register + CONSTANT c_mm_reg : t_c_mem := (latency => 1, + adr_w => 1, + dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers + nof_dat => 2, + init_sl => '0'); + + CONSTANT c_reg_slv_w : NATURAL := c_mm_reg.nof_dat*c_mm_reg.dat_w; + + TYPE t_reg_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_reg_slv_w-1 DOWNTO 0); + TYPE t_seq_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_seq_dat_w-1 DOWNTO 0); + TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + + -- Registers in dp_clk domain + SIGNAL ctrl_reg_arr : t_reg_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0')); + SIGNAL stat_reg_arr : t_reg_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0')); + + SIGNAL diag_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + SIGNAL diag_sel_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + + SIGNAL rx_seq_arr : t_seq_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_seq_val_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_data_arr : t_data_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_data_val_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + + SIGNAL diag_res_arr : t_seq_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL diag_res_val_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + + SIGNAL stat_res_ok_n_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + SIGNAL stat_res_val_n_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + + SIGNAL reg_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL reg_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); + BEGIN - gen_g_nof_diag_inst_times: FOR i IN 0 to g_nof_diag_inst-1 GENERATE + ASSERT g_data_w >= g_seq_dat_w REPORT "mms_diag_rx_seq: g_data_w < g_seq_dat_w is not allowed." SEVERITY FAILURE; + + gen_nof_streams: FOR I IN 0 to g_nof_streams-1 GENERATE + + -- no unreplicate needed + gen_one : IF g_data_w = g_seq_dat_w GENERATE + rx_seq_arr(I) <= rx_snk_in_arr(i).data(g_seq_dat_w-1 DOWNTO 0); + rx_seq_val_arr(I) <= rx_snk_in_arr(i).valid; + END GENERATE; + + -- unreplicate needed + gen_unreplicate : IF g_data_w > g_seq_dat_w GENERATE + -- keep sequence in low bits and set high bits to '1' if they mismatch the corresponding bit in the sequence + rx_data_arr(I) <= UNREPLICATE_DP_DATA(rx_snk_in_arr(i).data(g_data_w-1 DOWNTO 0), g_seq_dat_w); + rx_data_val_arr(I) <= rx_snk_in_arr(i).valid; + + -- keep sequence in low bits if the high bits match otherwise force low bits value to -1 to indicate the mismatch + p_rx_seq : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN -- register to ease timing closure + IF UNSIGNED(rx_data_arr(I)(g_data_w-1 DOWNTO g_seq_dat_w))=0 THEN + rx_seq_arr(I) <= rx_data_arr(I)(g_seq_dat_w-1 DOWNTO 0); + ELSE + rx_seq_arr(I) <= TO_SVEC(-1, g_seq_dat_w); + END IF; + rx_seq_val_arr(I) <= rx_data_val_arr(I); + END IF; + END PROCESS; + END GENERATE; + + -- detect rx sequence errors u_diag_rx_seq: ENTITY WORK.diag_rx_seq - GENERIC MAP ( - g_dat_w => g_dat_w, - g_diag_res_w => c_word_w+1 - ) - PORT MAP ( - rst => mm_rst, - clk => st_clk, - - -- Write and read back registers: - diag_en => out_reg( i), -- 0 to 31 (for 12 instances: 11 downto 0 used) - diag_sel => out_reg( c_word_w+i), -- 32 to 63 (for 12 instances: 43 downto 32 used) - - -- Read only registers: - orv(diag_res) => in_reg(2*c_word_w+i), -- 64 to 95 (for 12 instances: 75 downto 64 used) - diag_res_val => in_reg(3*c_word_w+i), -- 96 to 127 (for 12 instances: 107 downto 96 used) - - -- Streaming - in_dat => rx_snk_in(i).data(c_word_w-1 DOWNTO 0), - in_val => rx_snk_in(i).valid - ); - - -- Read-only registers for received data, starting from offset 4: - in_reg ( (4+i)*c_word_w+c_word_w-1 DOWNTO (4+i)*c_word_w) <= rx_snk_in(i).data(c_word_w-1 DOWNTO 0); + GENERIC MAP ( + g_dat_w => g_seq_dat_w, + g_diag_res_w => g_seq_dat_w -- do not use g_seq_dat_w+1 to include NOT diag_res_val in MSbit, instead use diag_res_val output + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, - END GENERATE; + -- Write and read back registers: + diag_en => diag_en_arr(I), + diag_sel => diag_sel_arr(I), + + -- Read only registers: + diag_res => diag_res_arr(I), + diag_res_val => diag_res_val_arr(I), - u_common_reg_r_w : ENTITY common_lib.common_reg_r_w - GENERIC MAP( - g_reg => c_mem_rec, - g_init_reg => c_init_reg + -- Streaming + in_dat => rx_seq_arr(I), + in_val => rx_seq_val_arr(I) + ); + + -- Map diag_res to single bit and register it to ease timing closure + stat_res_ok_n_arr(I) <= orv(diag_res_arr(I)) WHEN rising_edge(dp_clk); + stat_res_val_n_arr(I) <= NOT diag_res_val_arr(I) WHEN rising_edge(dp_clk); + + -- Register mapping + -- . write ctrl_reg_arr + diag_en_arr(I) <= ctrl_reg_arr(I)(0); -- address 0, data bit [0] + diag_sel_arr(I) <= ctrl_reg_arr(I)(1); -- address 0, data bit [1] + -- address 1, not used for control + -- . read stat_reg_arr + p_stat_reg_arr : PROCESS(ctrl_reg_arr, stat_res_ok_n_arr, stat_res_val_n_arr) + BEGIN + -- Default write / readback: + stat_reg_arr(I) <= ctrl_reg_arr(I); -- address 0, control read back + -- Status read only: + stat_reg_arr(I)(0+c_word_w) <= stat_res_ok_n_arr(I); -- address 1, data bit [0] + stat_reg_arr(I)(1+c_word_w) <= stat_res_val_n_arr(I); -- address 1, data bit [1] + END PROCESS; + + u_reg : ENTITY common_lib.common_reg_r_w_dc + GENERIC MAP ( + g_cross_clock_domain => TRUE, + g_readback => FALSE, -- using FALSE fits for write/read or read only register + g_reg => c_mm_reg ) - PORT MAP( - rst => mm_rst, - clk => mm_clk, - clken => '1', - -- control side - wr_en => mm_sla_in.wr, - wr_adr => mm_sla_in.address(c_mem_rec.adr_w-1 DOWNTO 0), - wr_dat => mm_sla_in.wrdata(c_mem_rec.dat_w-1 DOWNTO 0), - rd_en => mm_sla_in.rd, - rd_adr => mm_sla_in.address(c_mem_rec.adr_w-1 DOWNTO 0), - rd_dat => mm_sla_out.rddata(c_mem_rec.dat_w-1 DOWNTO 0), - rd_val => OPEN, - -- data side - out_reg => out_reg, - in_reg => in_reg + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + st_rst => dp_rst, + st_clk => dp_clk, + + -- Memory Mapped Slave in mm_clk domain + sla_in => reg_mosi_arr(I), + sla_out => reg_miso_arr(I), + + -- MM registers in dp_clk domain + in_reg => stat_reg_arr(I), + out_reg => ctrl_reg_arr(I) ); - - --Connect out_reg to in_reg for write and readback register: - in_reg(63 downto 0) <= out_reg(63 downto 0); - - --Connect unused bits to hard zeroes, otherwise SOPC-builder generated cpu0-test benches will halt - in_reg(3*c_word_w-1 DOWNTO 2*c_word_w + g_nof_diag_inst) <= (OTHERS => '0'); --Unused bits in register diag_res - in_reg(4*c_word_w-1 DOWNTO 3*c_word_w + g_nof_diag_inst) <= (OTHERS => '0'); --Unused bits in register diag_res_val - + END GENERATE; + + -- Combine the internal array of mm interfaces for the bg_data to one array that is connected to the port of the MM bus + u_mem_mux : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => c_mm_reg.adr_w + ) + PORT MAP ( + mosi => reg_mosi, + miso => reg_miso, + mosi_arr => reg_mosi_arr, + miso_arr => reg_miso_arr + ); END str; diff --git a/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd b/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd index 766955d7d15c60f37a2b026de4fa3c0aff785091..f36ac1e53b28cd14d48e1d8eff2b6a5596871546 100644 --- a/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd +++ b/libraries/base/diag/src/vhdl/mms_diag_tx_seq.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------- -- --- Copyright (C) 2010 +-- 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 @@ -20,6 +20,35 @@ -- ------------------------------------------------------------------------------- +-- Purpose: Provide MM access via slave register to diag_tx_seq +-- Description: +-- +-- Each DP stream has its own diag_tx_seq, because each stream can have its +-- own flow control. +-- +-- One MM control register sets all g_nof_streams: +-- +-- 31 24 23 16 15 8 7 0 wi +-- |-----------------|-----------------|-----------------|-----------------| +-- | select = [1], enable = [0] | 0 +-- |-----------------------------------------------------------------------| +-- | init[31: 0] | 1 +-- |-----------------------------------------------------------------------| +-- +-- . g_seq_dat_w +-- The g_seq_dat_w must be >= 1. The DP streaming data field is +-- c_dp_stream_data_w bits wide and the REPLICATE_DP_DATA() is used to wire +-- the g_seq_dat_w from the u_diag_tx_seq to fill the entire DP data width. +-- The maximum g_seq_dat_w depends on the pseudo random data width of the +-- LFSR sequeces in common_lfsr_sequences_pkg and on whether timing closure +-- can still be achieved for wider g_seq_dat_w. Thanks to the replication a +-- smaller g_seq_dat_w can be used to provide CNTR or LFSR data for the DP +-- data. +-- +-- . diag_init +-- Note that MM diag_init has c_word_w=32 bits, so if g_seq_dat_w is wider +-- then the MSbits are 0 and if it is smaller, then the MSbits are ignored. + LIBRARY IEEE, common_lib, dp_lib; USE IEEE.std_logic_1164.ALL; USE common_lib.common_pkg.ALL; @@ -28,92 +57,114 @@ USE dp_lib.dp_stream_pkg.ALL; ENTITY mms_diag_tx_seq IS GENERIC ( - g_nof_diag_inst : NATURAL := 1; - g_dat_w : NATURAL := c_word_w; -- >= 1, test data width - g_sim : BOOLEAN := FALSE + g_nof_streams : NATURAL := 1; + g_seq_dat_w : NATURAL := c_word_w -- >= 1, test sequence data width ); PORT ( -- Clocks and reset - mm_rst : IN STD_LOGIC; - mm_clk : IN STD_LOGIC; - st_clk : IN STD_LOGIC; - - -- Memory Mapped Slave - mm_sla_in : IN t_mem_mosi; -- master out slave in - mm_sla_out : OUT t_mem_miso; -- master in slave out - - -- Streaming interface - tx_src_out : OUT t_dp_sosi_arr(g_nof_diag_inst-1 DOWNTO 0); -- source out sink in - tx_src_in : IN t_dp_siso_arr(g_nof_diag_inst-1 DOWNTO 0) -- source in sink out + mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk + mm_clk : IN STD_LOGIC; -- MM bus clock + dp_rst : IN STD_LOGIC; -- reset synchronous with dp_clk + dp_clk : IN STD_LOGIC; -- DP streaming bus clock + + -- MM interface + reg_mosi : IN t_mem_mosi; -- single MM control register applied to all g_nof_streams + reg_miso : OUT t_mem_miso; + + -- DP streaming interface + tx_src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + tx_src_in_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) ); END mms_diag_tx_seq; ARCHITECTURE str OF mms_diag_tx_seq IS - CONSTANT c_latency : NATURAL := 1; -- read latency - CONSTANT c_init_sl : STD_LOGIC := '0'; -- optional, init all dat words to std_logic '0', '1' or 'X' - CONSTANT c_init_reg : STD_LOGIC_VECTOR(c_mem_reg_init_w-1 DOWNTO 0) := (OTHERS => '0'); - CONSTANT c_nof_mm_regs : NATURAL := 2+g_nof_diag_inst; - CONSTANT c_mm_addr_w : NATURAL := ceil_log2(c_nof_mm_regs); + -- Define the actual size of the MM slave register + CONSTANT c_mm_reg : t_c_mem := (latency => 1, + adr_w => 1, + dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers + nof_dat => 2, + init_sl => '0'); + + TYPE t_dat_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_seq_dat_w-1 DOWNTO 0); + TYPE t_replicate_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_data_w-1 DOWNTO 0); - CONSTANT c_mem_rec : t_c_mem := (c_latency, c_mm_addr_w, c_word_w, c_nof_mm_regs, c_init_sl); - - SIGNAL out_reg : STD_LOGIC_VECTOR(c_nof_mm_regs*c_word_w-1 DOWNTO 0); - SIGNAL in_reg : STD_LOGIC_VECTOR(c_nof_mm_regs*c_word_w-1 DOWNTO 0); + -- Registers in dp_clk domain + SIGNAL ctrl_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL diag_en : STD_LOGIC; + SIGNAL diag_sel : STD_LOGIC; + SIGNAL diag_init_mm : STD_LOGIC_VECTOR(c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL diag_init : STD_LOGIC_VECTOR(g_seq_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL tx_dat_arr : t_dat_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL tx_val_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + SIGNAL tx_req_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + SIGNAL tx_replicate_arr : t_replicate_arr(g_nof_streams-1 DOWNTO 0); + BEGIN - gen_g_nof_diag_inst_times: FOR i IN 0 to g_nof_diag_inst-1 GENERATE + gen_nof_streams: FOR I IN 0 to g_nof_streams-1 GENERATE u_diag_tx_seq: ENTITY WORK.diag_tx_seq - GENERIC MAP ( - g_dat_w => g_dat_w - ) - PORT MAP ( - rst => mm_rst, - clk => st_clk, - - -- Write and read back registers: - diag_en => out_reg( i), -- 0 to 31 - diag_sel => out_reg( c_word_w+i), -- 32 to 63 - diag_dat => out_reg(3*c_word_w+i*c_word_w-1 DOWNTO 2*c_word_w+i*c_word_w), -- downto 64 - - -- Streaming - diag_req => tx_src_in(i).ready, - out_dat => tx_src_out(i).data(c_word_w-1 DOWNTO 0), - out_val => tx_src_out(i).valid - ); - END GENERATE; - - u_common_reg_r_w : ENTITY common_lib.common_reg_r_w - GENERIC MAP( - g_reg => c_mem_rec, - g_init_reg => c_init_reg + GENERIC MAP ( + g_dat_w => g_seq_dat_w ) - PORT MAP( - rst => mm_rst, - clk => mm_clk, - clken => '1', - -- control side - wr_en => mm_sla_in.wr, - wr_adr => mm_sla_in.address(c_mem_rec.adr_w-1 DOWNTO 0), - wr_dat => mm_sla_in.wrdata(c_mem_rec.dat_w-1 DOWNTO 0), - rd_en => mm_sla_in.rd, - rd_adr => mm_sla_in.address(c_mem_rec.adr_w-1 DOWNTO 0), - rd_dat => mm_sla_out.rddata(c_mem_rec.dat_w-1 DOWNTO 0), - rd_val => OPEN, - -- data side - out_reg => out_reg, - in_reg => in_reg + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + -- Write and read back registers: + diag_en => diag_en, + diag_sel => diag_sel, + diag_dat => diag_init, + + -- Streaming + diag_req => tx_req_arr(I), + out_dat => tx_dat_arr(I), + out_val => tx_val_arr(I) ); + + tx_req_arr(I) <= tx_src_in_arr(I).ready; + + + tx_replicate_arr(I) <= REPLICATE_DP_DATA(tx_dat_arr(I)); + + -- for some reason the intermediate tx_replicate_arr() signal is needed, otherwise the assignment to the tx_src_out_arr().data field remains void in the Wave window + tx_src_out_arr(I).data <= tx_replicate_arr(I); + tx_src_out_arr(I).valid <= tx_val_arr(I); + END GENERATE; + + -- Register mapping + diag_en <= ctrl_reg( 0); -- address 0, data bit [0] + diag_sel <= ctrl_reg( 1); -- address 0, data bit [1] + diag_init_mm <= ctrl_reg(2*c_word_w-1 DOWNTO c_word_w); -- address 1, data bits [31:0] - --Connect out_reg to in_reg for write and readback register: - in_reg(63 downto 0) <= out_reg(63 downto 0); + diag_init <= RESIZE_UVEC(diag_init_mm, g_seq_dat_w); + + u_reg : ENTITY common_lib.common_reg_r_w_dc + GENERIC MAP ( + g_cross_clock_domain => TRUE, + g_readback => TRUE, -- using TRUE fits for write and readback register + g_reg => c_mm_reg + ) + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + st_rst => dp_rst, + st_clk => dp_clk, + + -- Memory Mapped Slave in mm_clk domain + sla_in => reg_mosi, + sla_out => reg_miso, + + -- MM registers in dp_clk domain + in_reg => ctrl_reg, -- connect out_reg to in_reg for write and readback register + out_reg => ctrl_reg + ); - --Connect unused bits to hard zeroes, otherwise SOPC-builder generated cpu0-test benches will halt - in_reg((2+g_nof_diag_inst)*c_word_w-1 DOWNTO 2*c_word_w) <= (OTHERS => '0'); --diag_dat - - END str; diff --git a/libraries/base/diag/tb/vhdl/tb_diag_regression.vhd b/libraries/base/diag/tb/vhdl/tb_diag_regression.vhd index 36ea670b44e2356de4aa417554614f4cde2551d5..9b225c3c546b4fc5c4739d483b40c82f1cc5eb3b 100644 --- a/libraries/base/diag/tb/vhdl/tb_diag_regression.vhd +++ b/libraries/base/diag/tb/vhdl/tb_diag_regression.vhd @@ -41,5 +41,6 @@ BEGIN u_tb_diag_block_gen : ENTITY work.tb_diag_block_gen; u_tb_mms_diag_block_gen : ENTITY work.tb_mms_diag_block_gen; + u_tb_mms_diag_seq : ENTITY work.tb_mms_diag_seq; END tb; diff --git a/libraries/base/diag/tb/vhdl/tb_mms_diag_seq.vhd b/libraries/base/diag/tb/vhdl/tb_mms_diag_seq.vhd index 1b53ce598c9bc18b7585a15bef80670c1b95e86f..51388d04a32f07daadaeaa62f2e650058046bf75 100644 --- a/libraries/base/diag/tb/vhdl/tb_mms_diag_seq.vhd +++ b/libraries/base/diag/tb/vhdl/tb_mms_diag_seq.vhd @@ -1,6 +1,6 @@ -------------------------------------------------------------------------------- -- --- Copyright (C) 2010 +-- 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 @@ -20,147 +20,394 @@ -- -------------------------------------------------------------------------------- +-- Purpose: Test bench for mms_diag_tx_seq --> mms_diag_rx_seq +-- The tb is self-stopping and self-checking. +-- Usage: +-- > as 5 +-- > run -all + + LIBRARY IEEE, common_lib, dp_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; USE IEEE.numeric_std.ALL; USE common_lib.common_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.tb_common_mem_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; ENTITY tb_mms_diag_seq IS + GENERIC ( + -- general + g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + -- specific + g_data_w : NATURAL := 40; -- >= g_seq_dat_w + g_seq_dat_w : NATURAL := 32 + ); END ENTITY tb_mms_diag_seq; ARCHITECTURE str of tb_mms_diag_seq IS - CONSTANT c_nof_diag_inst : NATURAL := 1; -- Enter number of diag instances here. Max = 32. - CONSTANT c_sim : BOOLEAN := TRUE; + CONSTANT c_nof_streams : NATURAL := 1; CONSTANT mm_clk_period : TIME := 8 ns; -- 125 MHz - CONSTANT st_clk_period : TIME := 5 ns; -- 200 MHz - - CONSTANT c_all_bits_high : INTEGER := -1; - CONSTANT c_all_bits_low : INTEGER := 0; - - CONSTANT c_offset_rx_en : NATURAL := 0; --offsets relative to MM base address - CONSTANT c_offset_rx_mode : NATURAL := 1; - CONSTANT c_offset_diag_res : NATURAL := 2; - CONSTANT c_offset_diag_res_val : NATURAL := 3; - - CONSTANT c_offset_tx_en : NATURAL := 0; - CONSTANT c_offset_tx_mode : NATURAL := 1; - CONSTANT c_offset_tx_dat : NATURAL := 2; - - SIGNAL st_clk : STD_LOGIC := '0'; + CONSTANT dp_clk_period : TIME := 5 ns; -- 200 MHz + + PROCEDURE proc_readback(SIGNAL clk : IN STD_LOGIC; + SIGNAL tx_miso : IN t_mem_miso; + SIGNAL tx_mosi : OUT t_mem_mosi; + SIGNAL rx_miso : IN t_mem_miso; + SIGNAL rx_mosi : OUT t_mem_mosi; + SIGNAL tx_init : OUT STD_LOGIC_VECTOR; + SIGNAL tx_ctrl : OUT STD_LOGIC_VECTOR; + SIGNAL rx_ctrl : OUT STD_LOGIC_VECTOR) IS + BEGIN + -- read back Tx data init + proc_mem_mm_bus_rd(1, clk, tx_miso, tx_mosi); + proc_mem_mm_bus_rd_latency(1, clk); + tx_init <= tx_miso.rddata(c_word_w-1 DOWNTO 0); + -- read back Tx control + proc_mem_mm_bus_rd(0, clk, tx_miso, tx_mosi); + proc_mem_mm_bus_rd_latency(1, clk); + tx_ctrl <= tx_miso.rddata(c_word_w-1 DOWNTO 0); + -- read back Rx control + proc_mem_mm_bus_rd(0, clk, rx_miso, rx_mosi); + proc_mem_mm_bus_rd_latency(1, clk); + rx_ctrl <= rx_miso.rddata(c_word_w-1 DOWNTO 0); + END proc_readback; + + PROCEDURE proc_enable_tx(CONSTANT c_pattern : IN STRING; -- "PSRG", "CNTR" + CONSTANT c_tx_init : IN NATURAL; + SIGNAL mm_clk : IN STD_LOGIC; + SIGNAL dp_clk : IN STD_LOGIC; + SIGNAL tx_miso : IN t_mem_miso; -- tx ctrl + SIGNAL tx_mosi : OUT t_mem_mosi; + SIGNAL rx_miso : IN t_mem_miso; -- rx ctrl + SIGNAL rx_mosi : OUT t_mem_mosi; + SIGNAL tx_init : OUT STD_LOGIC_VECTOR; -- readback + SIGNAL tx_ctrl : OUT STD_LOGIC_VECTOR; + SIGNAL rx_ctrl : OUT STD_LOGIC_VECTOR) IS + CONSTANT c_en : NATURAL := 1; + VARIABLE v_sel : NATURAL; + VARIABLE v_ctlr : NATURAL; + BEGIN + IF c_pattern="PSRG" THEN + v_sel := 0; -- pseudo random data + ELSE + v_sel := 1; -- counter data + END IF; + v_ctlr := v_sel * 2 + c_en; -- bits [1:0] + -- Enable Tx + proc_mem_mm_bus_wr(0, v_ctlr, mm_clk, tx_miso, tx_mosi); + proc_mem_mm_bus_wr(1, c_tx_init, mm_clk, tx_miso, tx_mosi); + proc_common_wait_some_cycles(mm_clk, dp_clk, 10); -- wait for clock domain crossing + proc_readback(mm_clk, tx_miso, tx_mosi, rx_miso, rx_mosi, tx_init, tx_ctrl, rx_ctrl); + END proc_enable_tx; + + PROCEDURE proc_enable_rx(CONSTANT c_pattern : IN STRING; -- "PSRG", "CNTR" + SIGNAL mm_clk : IN STD_LOGIC; + SIGNAL dp_clk : IN STD_LOGIC; + SIGNAL tx_miso : IN t_mem_miso; -- tx ctrl + SIGNAL tx_mosi : OUT t_mem_mosi; + SIGNAL rx_miso : IN t_mem_miso; -- rx ctrl + SIGNAL rx_mosi : OUT t_mem_mosi; + SIGNAL tx_init : OUT STD_LOGIC_VECTOR; -- readback + SIGNAL tx_ctrl : OUT STD_LOGIC_VECTOR; + SIGNAL rx_ctrl : OUT STD_LOGIC_VECTOR) IS + CONSTANT c_en : NATURAL := 1; + VARIABLE v_sel : NATURAL; + VARIABLE v_ctlr : NATURAL; + BEGIN + IF c_pattern="PSRG" THEN + v_sel := 0; -- pseudo random data + ELSE + v_sel := 1; -- counter data + END IF; + v_ctlr := v_sel * 2 + c_en; -- bits [1:0] + proc_mem_mm_bus_wr(0, v_ctlr, mm_clk, rx_miso, rx_mosi); + proc_common_wait_some_cycles(mm_clk, dp_clk, 10); -- wait for clock domain crossing + proc_readback(mm_clk, tx_miso, tx_mosi, rx_miso, rx_mosi, tx_init, tx_ctrl, rx_ctrl); + END proc_enable_rx; + + PROCEDURE proc_disable_tx(SIGNAL mm_clk : IN STD_LOGIC; + SIGNAL dp_clk : IN STD_LOGIC; + SIGNAL tx_miso : IN t_mem_miso; -- tx ctrl + SIGNAL tx_mosi : OUT t_mem_mosi; + SIGNAL rx_miso : IN t_mem_miso; -- rx ctrl + SIGNAL rx_mosi : OUT t_mem_mosi; + SIGNAL tx_init : OUT STD_LOGIC_VECTOR; -- readback + SIGNAL tx_ctrl : OUT STD_LOGIC_VECTOR; + SIGNAL rx_ctrl : OUT STD_LOGIC_VECTOR) IS + BEGIN + proc_mem_mm_bus_wr(0, 0, mm_clk, tx_miso, tx_mosi); + proc_common_wait_some_cycles(mm_clk, dp_clk, 10); -- wait for clock domain crossing + proc_readback(mm_clk, tx_miso, tx_mosi, rx_miso, rx_mosi, tx_init, tx_ctrl, rx_ctrl); + END proc_disable_tx; + + PROCEDURE proc_disable_rx(SIGNAL mm_clk : IN STD_LOGIC; + SIGNAL dp_clk : IN STD_LOGIC; + SIGNAL tx_miso : IN t_mem_miso; -- tx ctrl + SIGNAL tx_mosi : OUT t_mem_mosi; + SIGNAL rx_miso : IN t_mem_miso; -- rx ctrl + SIGNAL rx_mosi : OUT t_mem_mosi; + SIGNAL tx_init : OUT STD_LOGIC_VECTOR; -- readback + SIGNAL tx_ctrl : OUT STD_LOGIC_VECTOR; + SIGNAL rx_ctrl : OUT STD_LOGIC_VECTOR) IS + BEGIN + proc_mem_mm_bus_wr(0, 0, mm_clk, rx_miso, rx_mosi); + proc_common_wait_some_cycles(mm_clk, dp_clk, 10); -- wait for clock domain crossing + proc_readback(mm_clk, tx_miso, tx_mosi, rx_miso, rx_mosi, tx_init, tx_ctrl, rx_ctrl); + END proc_disable_rx; + + TYPE t_tb_mode_enum IS ( + s_off, + s_expect_ok, + s_expect_error, + s_expect_no_result + ); + + PROCEDURE proc_read_and_verify_rx_stat(SIGNAL clk : IN STD_LOGIC; + SIGNAL mm_miso : IN t_mem_miso; + SIGNAL mm_mosi : OUT t_mem_mosi; + SIGNAL tb_mode : INOUT t_tb_mode_enum; + SIGNAL tb_verify : OUT STD_LOGIC; + SIGNAL rx_stat : INOUT STD_LOGIC_VECTOR) IS + BEGIN + -- Read + proc_mem_mm_bus_rd(1, clk, mm_miso, mm_mosi); + proc_mem_mm_bus_rd_latency(1, clk); + rx_stat <= mm_miso.rddata(c_word_w-1 DOWNTO 0); + proc_common_wait_some_cycles(clk, 1); + + -- Issue tb_verify pulse eg. to easy recognition in Wave window + tb_verify <= '1'; + proc_common_wait_some_cycles(clk, 1); + tb_verify <= '0'; + + -- Verify + IF tb_mode=s_expect_ok THEN + IF rx_stat(1)/='0' THEN + REPORT "Wrong diag result: no valid result." SEVERITY ERROR; + ELSIF rx_stat(0)/='0' THEN + REPORT "Wrong diag result: one or more data errors." SEVERITY ERROR; + END IF; + ELSIF tb_mode=s_expect_error THEN + IF rx_stat(1)/='0' THEN + REPORT "Wrong diag result: no valid result." SEVERITY ERROR; + ELSIF rx_stat(0)/='1' THEN + REPORT "Wrong diag result: must detect data errors." SEVERITY ERROR; + END IF; + ELSIF tb_mode=s_expect_no_result THEN + IF rx_stat(1)/='1' THEN + REPORT "Wrong diag result: must indicate no valid result." SEVERITY ERROR; + END IF; + ELSE + REPORT "Unknown verify mode" SEVERITY FAILURE; + END IF; + END proc_read_and_verify_rx_stat; + + SIGNAL random : STD_LOGIC_VECTOR(15 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences + SIGNAL pulse : STD_LOGIC; + SIGNAL ready : STD_LOGIC; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL tb_mode : t_tb_mode_enum := s_off; + SIGNAL tb_verify : STD_LOGIC := '0'; + SIGNAL mm_rst : STD_LOGIC; SIGNAL mm_clk : STD_LOGIC := '0'; - SIGNAL sys_rst : STD_LOGIC := '1'; + SIGNAL dp_rst : STD_LOGIC := '1'; + SIGNAL dp_clk : STD_LOGIC := '0'; - SIGNAL tx_mm_mosi : t_mem_mosi; - SIGNAL tx_mm_miso : t_mem_miso; + SIGNAL reg_tx_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL reg_tx_miso : t_mem_miso; - SIGNAL rx_mm_mosi : t_mem_mosi; - SIGNAL rx_mm_miso : t_mem_miso; + SIGNAL reg_rx_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL reg_rx_miso : t_mem_miso; - SIGNAL tx_src_out : t_dp_sosi_arr(c_nof_diag_inst-1 DOWNTO 0); -- source out sink in - SIGNAL tx_src_in : t_dp_siso_arr(c_nof_diag_inst-1 DOWNTO 0); -- source in sink out + SIGNAL tx_ctrl : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL tx_init : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL rx_ctrl : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL rx_stat : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + + SIGNAL tx_src_out_arr : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0); + SIGNAL tx_src_in_arr : t_dp_siso_arr(c_nof_streams-1 DOWNTO 0); + SIGNAL force_low_error : STD_LOGIC; + SIGNAL force_replicate_error : STD_LOGIC; + + SIGNAL rx_snk_in_arr : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0); + BEGIN - sys_rst <= '0' AFTER 100 ns; + mm_rst <= '1', '0' AFTER mm_clk_period * 5; + dp_rst <= mm_rst WHEN rising_edge(dp_clk); - st_clk <= NOT mm_clk AFTER mm_clk_period/2; -- Would be generated by SOPC if there was one. - mm_clk <= NOT mm_clk AFTER mm_clk_period/2; - p_mm_wr : PROCESS + mm_clk <= NOT mm_clk OR tb_end AFTER mm_clk_period/2; + dp_clk <= NOT dp_clk OR tb_end AFTER dp_clk_period/2; + + ------------------------------------------------------------------------------ + -- STREAM CONTROL + ------------------------------------------------------------------------------ + + random <= func_common_random(random) WHEN rising_edge(dp_clk); + + ready <= '1' WHEN g_flow_control_verify=e_active ELSE + random(random'HIGH) WHEN g_flow_control_verify=e_random ELSE + pulse WHEN g_flow_control_verify=e_pulse; + + tx_src_in_arr <= func_dp_stream_arr_set(tx_src_in_arr, ready, "READY"); + + ------------------------------------------------------------------------------ + -- Stimuli + ------------------------------------------------------------------------------ + + p_stimuli : PROCESS BEGIN - - tx_mm_miso <= c_mem_miso_rst; - tx_mm_mosi <= c_mem_mosi_rst; - rx_mm_miso <= c_mem_miso_rst; - rx_mm_mosi <= c_mem_mosi_rst; + force_low_error <= '0'; + force_replicate_error <= '0'; + tb_mode <= s_off; + proc_common_wait_until_low(mm_clk, mm_rst); + proc_common_wait_some_cycles(mm_clk, 10); + + ------------------------------------------------------------------------- + -- Verify Tx and Rx on and both with the same pattern + ------------------------------------------------------------------------- + tb_mode <= s_expect_ok; + proc_disable_tx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_disable_rx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_enable_tx("CNTR", 17, mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_enable_rx("CNTR", mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); - WHILE sys_rst='1' LOOP - WAIT UNTIL rising_edge(mm_clk); - END LOOP; - - FOR I IN 0 TO 9 LOOP - WAIT UNTIL rising_edge(mm_clk); - END LOOP; - - -- Enable DIAG TX sequencer, set modes of RX and TX to PRNG - proc_mem_mm_bus_wr(c_offset_tx_mode, c_all_bits_high, mm_clk, tx_mm_mosi); - proc_mem_mm_bus_wr(c_offset_tx_en, c_all_bits_high, mm_clk, tx_mm_mosi); - proc_mem_mm_bus_wr(c_offset_rx_mode, c_all_bits_high, mm_clk, rx_mm_mosi); - - WAIT FOR 100 ns; - - -- Receivers should have aligned to the data now. Enable the DIAG RX monitor. - proc_mem_mm_bus_wr(c_offset_rx_en, c_all_bits_high, mm_clk, rx_mm_mosi); - - WAIT FOR 200 ns; - - -- Now read the diagnostics result: first put the request on the bus. - proc_mem_mm_bus_rd(c_offset_diag_res, mm_clk, rx_mm_mosi); - - -- Wait because of read latency - proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); - - -- Read data is now available in tx_mm_miso.rddata - FOR i in 0 to c_nof_diag_inst-1 LOOP -- All unconnected diag_res signals will of course be 'X' - only read the first c_nof_diag_inst bits. - ASSERT rx_mm_miso.rddata(i) = '0' - REPORT " Uniboard: ************************ MM READ DIAG RESULT NOT ZERO! ************************" SEVERITY FAILURE; - END LOOP; - - ASSERT FALSE - REPORT "Uniboard: MM read DIAG result OK." SEVERITY NOTE; - + -- Run test and read and verify Rx status + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + ------------------------------------------------------------------------- + -- Verify Tx and Rx on but with different pattern + ------------------------------------------------------------------------- + tb_mode <= s_expect_error; + proc_enable_tx("PSRG", 17, mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + + -- Run test and read and verify Rx status + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + ------------------------------------------------------------------------- + -- Verify Rx off + ------------------------------------------------------------------------- + tb_mode <= s_expect_no_result; + proc_disable_rx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + + -- Run test and read and verify Rx status + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + ------------------------------------------------------------------------- + -- Verify Tx and Rx on with error in sequence low part + ------------------------------------------------------------------------- + tb_mode <= s_expect_ok; + proc_disable_tx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_disable_rx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_enable_tx("CNTR", 17, mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_enable_rx("CNTR", mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + + -- Run test and read and verify Rx status + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + tb_mode <= s_expect_error; + proc_common_wait_some_cycles(dp_clk, 1); + force_low_error <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + force_low_error <= '0'; + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + ------------------------------------------------------------------------- + -- Verify Tx and Rx on with error in sequence replicate part + ------------------------------------------------------------------------- + tb_mode <= s_expect_ok; + proc_disable_tx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_disable_rx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_enable_tx("CNTR", 17, mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_enable_rx("CNTR", mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + + -- Run test and read and verify Rx status + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + tb_mode <= s_expect_error; + proc_common_wait_some_cycles(dp_clk, 1); + force_replicate_error <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + force_replicate_error <= '0'; + proc_common_wait_some_cycles(mm_clk, 100); + proc_read_and_verify_rx_stat(mm_clk, reg_rx_miso, reg_rx_mosi, tb_mode, tb_verify, rx_stat); + + ------------------------------------------------------------------------- + -- Both off + ------------------------------------------------------------------------- + tb_mode <= s_off; + proc_disable_tx(mm_clk, dp_clk, reg_tx_miso, reg_tx_mosi, reg_rx_miso, reg_rx_mosi, tx_init, tx_ctrl, rx_ctrl); + proc_common_wait_some_cycles(mm_clk, 10); + tb_end <= '1'; WAIT; - END PROCESS; - + u_mms_diag_tx_seq: ENTITY WORK.mms_diag_tx_seq - GENERIC MAP( - g_nof_diag_inst => c_nof_diag_inst, - g_dat_w => c_word_w, - g_sim => c_sim - ) - PORT MAP( - -- Clocks and reset - mm_rst => sys_rst, - mm_clk => mm_clk, - st_clk => st_clk, - - -- Memory Mapped Slave - mm_sla_in => tx_mm_mosi, -- master out slave in - mm_sla_out => tx_mm_miso, -- master in slave out - - -- Streaming interface - tx_src_out => tx_src_out, - tx_src_in => tx_src_in - ); - - gen_ready_signals : FOR i IN 0 TO c_nof_diag_inst-1 GENERATE -- Ready signals for all instantiated diag rx modules - tx_src_in(i).ready <= '1'; - END GENERATE; + GENERIC MAP( + g_nof_streams => c_nof_streams, + g_seq_dat_w => g_seq_dat_w + ) + PORT MAP( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- MM interface + reg_mosi => reg_tx_mosi, + reg_miso => reg_tx_miso, + + -- DP streaming interface + tx_src_out_arr => tx_src_out_arr, + tx_src_in_arr => tx_src_in_arr + ); u_mms_diag_rx_seq: ENTITY WORK.mms_diag_rx_seq - GENERIC MAP( - g_nof_diag_inst => c_nof_diag_inst, - g_dat_w => c_word_w, - g_sim => c_sim - ) - PORT MAP( - -- Clocks and reset - mm_rst => sys_rst, - mm_clk => mm_clk, - st_clk => st_clk, - - -- Memory Mapped Slave - mm_sla_in => rx_mm_mosi, -- master out slave in - mm_sla_out => rx_mm_miso, -- master in slave out - - -- Streaming interface - rx_snk_in => tx_src_out - ); - + GENERIC MAP( + g_nof_streams => c_nof_streams, + g_seq_dat_w => g_seq_dat_w, + g_data_w => g_data_w + ) + PORT MAP( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- MM interface + reg_mosi => reg_rx_mosi, + reg_miso => reg_rx_miso, + + -- DP streaming interface + rx_snk_in_arr => rx_snk_in_arr + ); + + p_connect : PROCESS(tx_src_out_arr, force_low_error, force_replicate_error) + BEGIN + rx_snk_in_arr <= tx_src_out_arr; + IF force_low_error='1' THEN + rx_snk_in_arr(0).data(0) <= NOT tx_src_out_arr(0).data(0); + END IF; + IF force_replicate_error='1' THEN + rx_snk_in_arr(0).data(g_seq_dat_w) <= NOT tx_src_out_arr(0).data(g_seq_dat_w); + END IF; + END PROCESS; + END ARCHITECTURE str;