diff --git a/libraries/base/diag/src/vhdl/mms_diag_data_buffer_dev.vhd b/libraries/base/diag/src/vhdl/mms_diag_data_buffer_dev.vhd new file mode 100644 index 0000000000000000000000000000000000000000..4f8c6f02c2a5807a8c13d5e33b1fbe4a14dabb66 --- /dev/null +++ b/libraries/base/diag/src/vhdl/mms_diag_data_buffer_dev.vhd @@ -0,0 +1,224 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +------------------------------------------------------------------------------- + +-- Purpose: MM data buffer and Rx seq for multiple parallel SOSI streams +-- Description: +-- . g_use_db +-- The mms_diag_data_buffer can capture data from an input stream in a data +-- buffer when g_use_db=TRUE. Dependend on g_buf_use_sync the data buffer +-- is rewritten after each in_sync or when the last word was read via MM. +-- . g_use_rx_seq +-- The mms_diag_data_buffer can continously verify a input Rx data sequence +-- when g_use_rx_seq=TRUE. The expected sequence data is typically generated +-- by an remote upstream tx_seq source. +-- . The advantage of the rx_seq is that is can continously verify the +-- correctness of all rx data in hardware, whereas the DB can only take a +-- snapshot that then needs to be examined via MM. The advandage of the DB +-- is that it can take a snapshot of the values of the received data. The +-- DB requires RAM resources and the rx_seq does not. +-- +-- Block diagram: +-- +-- g_use_db +-- g_buf_use_sync +-- . +-- . g_use_tx_seq +-- . . +-- . . +-- /-------------> Rx seq +-- | . | +-- in_sosi_arr -----*---> DB RAM | +-- in_sync -------------> DB reg | +-- || | +-- || | +-- MM ================================ +-- +-- Remark: +-- . A nice new feature would be to continuously write the DB and to stop +-- writting it on a trigger. This trigger can then eg. be when the rx_seq +-- detects an error. By delaying the trigger somewhat it the DB can then +-- capture some data before and after the trigger event. + +LIBRARY IEEE, common_lib, technology_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; +USE work.diag_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; + +ENTITY mms_diag_data_buffer_dev IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + -- Generate configurationsc_diag_db + g_use_db : BOOLEAN := TRUE; + g_use_rx_seq : BOOLEAN := FALSE; + -- General + g_nof_streams : POSITIVE := 16; -- each stream gets an data buffer + -- DB settings + g_data_type : t_diag_data_type_enum := e_data; -- define the sosi field that gets stored: e_data=data, e_complex=im&re, e_real=re, e_imag=im + g_data_w : NATURAL := 32; -- the g_data_w is the width of the data, re, im values or of the combined im&re value + g_buf_nof_data : NATURAL := 1024; -- nof words per data buffer + g_buf_use_sync : BOOLEAN := FALSE; -- when TRUE start filling the buffer at the in_sync, else after the last word was read + -- Rx_seq + g_use_steps : BOOLEAN := FALSE; + g_nof_steps : NATURAL := c_diag_seq_rx_reg_nof_steps; + g_seq_dat_w : NATURAL := 32 -- >= 1, test sequence data width. Choose g_seq_dat_w <= g_data_w + ); + PORT ( + -- System + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + -- MM interface + reg_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- DB control register (one per stream) + reg_data_buf_miso : OUT t_mem_miso; + + ram_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- DB buffer RAM (one per streams) + ram_data_buf_miso : OUT t_mem_miso; + + reg_rx_seq_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- Rx seq control register (one per streams) + reg_rx_seq_miso : OUT t_mem_miso; + + -- ST interface + in_sync : IN STD_LOGIC := '0'; -- input sync pulse in ST dp_clk domain that starts data buffer when g_use_in_sync = TRUE + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) + ); +END mms_diag_data_buffer_dev; + +ARCHITECTURE str OF mms_diag_data_buffer_dev IS + + CONSTANT c_buf_mm_factor : NATURAL := ceil_div(g_data_w, c_word_w); + CONSTANT c_buf_nof_data_mm : NATURAL := g_buf_nof_data*c_buf_mm_factor; + + CONSTANT c_buf_adr_w : NATURAL := ceil_log2(c_buf_nof_data_mm); + CONSTANT c_reg_adr_w : NATURAL := c_diag_db_dev_reg_adr_w; + + TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + + SIGNAL in_data_arr : t_data_arr(g_nof_streams-1 DOWNTO 0); + + SIGNAL ram_data_buf_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL ram_data_buf_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); + + SIGNAL reg_data_buf_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL reg_data_buf_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); + +BEGIN + + no_db : IF g_use_db=FALSE GENERATE + ram_data_buf_miso <= c_mem_miso_rst; + reg_data_buf_miso <= c_mem_miso_rst; + END GENERATE; + + gen_db : IF g_use_db=TRUE GENERATE + -- Combine the internal array of mm interfaces for the data_buf to one array that is connected to the port of the MM bus + u_mem_mux_data_buf : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => c_buf_adr_w + ) + PORT MAP ( + mosi => ram_data_buf_mosi, + miso => ram_data_buf_miso, + mosi_arr => ram_data_buf_mosi_arr, + miso_arr => ram_data_buf_miso_arr + ); + + u_mem_mux_reg : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => c_reg_adr_w + ) + PORT MAP ( + mosi => reg_data_buf_mosi, + miso => reg_data_buf_miso, + mosi_arr => reg_data_buf_mosi_arr, + miso_arr => reg_data_buf_miso_arr + ); + + gen_stream : FOR I IN 0 TO g_nof_streams-1 GENERATE + in_data_arr(I) <= in_sosi_arr(I).im(g_data_w/2-1 DOWNTO 0) & in_sosi_arr(I).re(g_data_w/2-1 DOWNTO 0) WHEN g_data_type=e_complex ELSE + in_sosi_arr(I).re(g_data_w-1 DOWNTO 0) WHEN g_data_type=e_real ELSE + in_sosi_arr(I).im(g_data_w-1 DOWNTO 0) WHEN g_data_type=e_imag ELSE + in_sosi_arr(I).data(g_data_w-1 DOWNTO 0); -- g_data_type=e_data is default + + u_diag_data_buffer : ENTITY work.diag_data_buffer_dev + GENERIC MAP ( + g_technology => g_technology, + g_data_w => g_data_w, + g_nof_data => g_buf_nof_data, + g_use_in_sync => g_buf_use_sync -- when TRUE start filling the buffer at the in_sync, else after the last word was read + ) + PORT MAP ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + + ram_mm_mosi => ram_data_buf_mosi_arr(I), + ram_mm_miso => ram_data_buf_miso_arr(I), + + reg_mm_mosi => reg_data_buf_mosi_arr(I), + reg_mm_miso => reg_data_buf_miso_arr(I), + + -- Streaming clock domain + st_rst => dp_rst, + st_clk => dp_clk, + + in_data => in_data_arr(I), + in_sync => in_sync, + in_val => in_sosi_arr(I).valid + ); + END GENERATE; + END GENERATE; + + no_rx_seq : IF g_use_rx_seq=FALSE GENERATE + reg_rx_seq_miso <= c_mem_miso_rst; + END GENERATE; + + gen_rx_seq : IF g_use_rx_seq=TRUE GENERATE + u_mms_diag_rx_seq : ENTITY work.mms_diag_rx_seq + GENERIC MAP ( + g_nof_streams => g_nof_streams, + g_use_steps => g_use_steps, + g_nof_steps => g_nof_steps, + g_seq_dat_w => g_seq_dat_w, -- >= 1, test sequence data width + g_data_w => g_data_w -- >= g_seq_dat_w, user data width + ) + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Memory Mapped Slave + reg_mosi => reg_rx_seq_mosi, -- multiplexed port for g_nof_streams MM control/status registers + reg_miso => reg_rx_seq_miso, + + -- Streaming interface + rx_snk_in_arr => in_sosi_arr + ); + END GENERATE; + +END str;