From d344895a457aa98acf9ef209094db2c532c85f2a Mon Sep 17 00:00:00 2001 From: Rene Hagdorn Date: Mon, 3 Dec 2018 15:40:19 +0100 Subject: [PATCH] PixelAddressDecoder and ToT/TS GrayDecoder added to readout --- mupix/Mupix8/sources/Datapath/DataDecoder.vhd | 128 ++++++++++++ .../sources/Datapath/MupixTRBReadout.vhd | 95 +++++++-- .../sources/Datapath/PixelAddressDecode.vhd | 2 +- mupix/Mupix8/tb/DataDecoder_TB.vhd | 190 ++++++++++++++++++ mupix/Mupix8/tb/DataFilterTest.vhd | 8 +- mupix/Mupix8/tb/GrayDecoder_TB.vhd | 75 +++++++ mupix/Mupix8/tb/MupixTRBReadoutTest.vhd | 4 +- 7 files changed, 480 insertions(+), 22 deletions(-) create mode 100644 mupix/Mupix8/sources/Datapath/DataDecoder.vhd create mode 100644 mupix/Mupix8/tb/DataDecoder_TB.vhd create mode 100644 mupix/Mupix8/tb/GrayDecoder_TB.vhd diff --git a/mupix/Mupix8/sources/Datapath/DataDecoder.vhd b/mupix/Mupix8/sources/Datapath/DataDecoder.vhd new file mode 100644 index 0000000..9f1415d --- /dev/null +++ b/mupix/Mupix8/sources/Datapath/DataDecoder.vhd @@ -0,0 +1,128 @@ +---------------------------------------------------------------------------------- +-- MuPix8 Column and Row Address Decoder +-- and ToT and Timestamp Gray Decoder +-- René Hagdorn +-- Ruhr-University Bochum +---------------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity DataDecoder is + generic ( + D_W : integer := 32; -- width of full data word + Pix_W : integer := 8; -- col/row address width + ToT_W : integer := 6; -- time over threshold width + TS_W : integer := 10; -- timestamp width + LINKS : integer := 4 -- number of links (data + counters) + ); + port ( + clk : in std_logic; + reset : in std_logic; + bypass : in std_logic; + datain : in std_logic_vector(D_W - 1 downto 0); -- incoming data word + datain_valid : in std_logic; -- valid signal for input data + counterA_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link A + counterB_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link B + counterC_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link B + + dataout : out std_logic_vector(D_W - 1 downto 0); -- decoded data word + dataout_valid : out std_logic; -- valid output data + counterA_out : out std_logic_vector(D_W - 1 downto 0); -- last counter value link A + counterB_out : out std_logic_vector(D_W - 1 downto 0); -- last counter value link B + counterC_out : out std_logic_vector(D_W - 1 downto 0) -- last counter value link B + ); +end DataDecoder; + +architecture RTL of DataDecoder is + +component PixelAddressDecode is + generic ( + column_width : integer := 8; -- column bits + row_width : integer := 8); -- row bits + port ( + clk : in std_logic; -- clock in + reset : in std_logic; -- reset in + bypass : in std_logic; -- bypass logic + ena : in std_logic; -- enable in + col_in : in std_logic_vector(column_width - 1 downto 0); -- mupix col addr. + row_in : in std_logic_vector(row_width - 1 downto 0); -- mupix row addr. + valid_o : out std_logic; -- valid output + col_out : out std_logic_vector(column_width - 1 downto 0); -- phys. col addr. + row_out : out std_logic_vector(row_width - 1 downto 0)); -- phys row addr. +end component; + +component gray_to_binary is + generic(NBITS : integer := 10); + port ( + clk : in std_logic; -- clk input + reset : in std_logic; -- reset input + bypass : in std_logic; -- bypass logic + gray_in : in std_logic_vector (NBITS - 1 downto 0); -- gray counter input + bin_out : out std_logic_vector (NBITS - 1 downto 0) -- binary counter output + ); +end component; + +signal datain_i : std_logic_vector(LINKS*D_W - 1 downto 0); -- data channel and counters +signal dataout_i : std_logic_vector(LINKS*D_W - 1 downto 0); -- data channel and counters +signal validin_i : std_logic_vector(LINKS - 1 downto 0); +signal validout_i : std_logic_vector(LINKS - 1 downto 0); -- valid signals + +begin + + -- combine datain and counters to single stream for easier decoder generation + datain_i <= datain & counterA_in & counterB_in & counterC_in; + validin_i <= datain_valid & b"111"; + + Decode_J : for J in 1 to LINKS generate + address_decoder : PixelAddressDecode + generic map ( + column_width => Pix_W, + row_width => Pix_W + ) + port map ( + clk => clk, + reset => reset, + bypass => bypass, + ena => validin_i(J - 1), + col_in => datain_i(J*D_W - Pix_W - 1 downto J*D_W - 2*Pix_W), + row_in => datain_i(J*D_W - 1 downto J*D_W - Pix_W), + valid_o => validout_i(J - 1), + col_out => dataout_i(J*D_W - Pix_W - 1 downto J*D_W - 2*Pix_W), + row_out => dataout_i(J*D_W - 1 downto J*D_W - Pix_W) + ); + + ToT_decoder : gray_to_binary + generic map ( + NBITS => ToT_W + ) + port map ( + clk => clk, + reset => reset, + bypass => bypass, + gray_in => datain_i(J*D_W - 2*Pix_W - 1 downto (J-1)*D_W + TS_W), + bin_out => dataout_i(J*D_W - 2*Pix_W - 1 downto (J-1)*D_W + TS_W) + ); + + Timestamp_decoder : gray_to_binary + generic map ( + NBITS => TS_W + ) + port map ( + clk => clk, + reset => reset, + bypass => bypass, + gray_in => datain_i((J-1)*D_W + TS_W - 1 downto (J-1)*D_W), + bin_out => dataout_i((J-1)*D_W + TS_W - 1 downto (J-1)*D_W) + ); + end generate Decode_J; + + -- split datastream back up to individual outputs + dataout_valid <= validout_i(LINKS - 1); + dataout <= dataout_i(LINKS*D_W - 1 downto (LINKS - 1)*D_W); + counterA_out <= dataout_i((LINKS - 1)*D_W - 1 downto (LINKS - 2)*D_W); + counterB_out <= dataout_i((LINKS - 2)*D_W - 1 downto (LINKS - 3)*D_W); + counterC_out <= dataout_i((LINKS - 3)*D_W - 1 downto (LINKS - 4)*D_W); + +end RTL; diff --git a/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd b/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd index 67020b1..69f02ce 100644 --- a/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd +++ b/mupix/Mupix8/sources/Datapath/MupixTRBReadout.vhd @@ -88,16 +88,42 @@ architecture rtl of MupixTRBReadout is component MupixDataFilter port( - clk : in std_logic; - reset : in std_logic; - datain : in std_logic_vector(39 downto 0); - datain_valid : in std_logic; - dataout : out std_logic_vector(31 downto 0); - dataout_valid : out std_logic; - counterA : out std_logic_vector(31 downto 0); - counterB : out std_logic_vector(31 downto 0); - counterC : out std_logic_vector(31 downto 0)); -end component MupixDataFilter; + clk : in std_logic; + reset : in std_logic; + datain : in std_logic_vector(39 downto 0); + datain_valid : in std_logic; + dataout : out std_logic_vector(31 downto 0); + dataout_valid : out std_logic; + counterA : out std_logic_vector(31 downto 0); + counterB : out std_logic_vector(31 downto 0); + counterC : out std_logic_vector(31 downto 0)); + end component MupixDataFilter; + + component DataDecoder + generic ( + D_W : integer := 32; -- width of full data word + Pix_W : integer := 8; -- col/row address width + ToT_W : integer := 6; -- time over threshold width + TS_W : integer := 10; -- timestamp width + LINKS : integer := 4 -- number of links (data + counters) + ); + port ( + clk : in std_logic; + reset : in std_logic; + bypass : in std_logic; + datain : in std_logic_vector(D_W - 1 downto 0); -- incoming data word + datain_valid : in std_logic; -- valid signal for input data + counterA_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link A + counterB_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link B + counterC_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link C + + dataout : out std_logic_vector(D_W - 1 downto 0); -- decoded data word + dataout_valid : out std_logic; -- valid output data + counterA_out : out std_logic_vector(D_W - 1 downto 0); -- last counter value link A + counterB_out : out std_logic_vector(D_W - 1 downto 0); -- last counter value link B + counterC_out : out std_logic_vector(D_W - 1 downto 0) -- last counter value link C + ); + end component DataDecoder component ReadoutController generic( @@ -149,6 +175,13 @@ end component MupixDataFilter; signal mupix_filter_counterB_i : std_logic_vector(g_datawidthtrb - 1 downto 0); signal mupix_filter_counterC_i : std_logic_vector(g_datawidthtrb - 1 downto 0); + signal decoder_bypass_i : std_logic := '0'; + signal decoder_dataout_valid_i : std_logic; + signal decoder_dataout_i : std_logic_vector(g_datawidthtrb - 1 downto 0); + signal decoder_counterA_i : std_logic_vector(g_datawidthtrb - 1 downto 0); + signal decoder_counterB_i : std_logic_vector(g_datawidthtrb - 1 downto 0); + signal decoder_counterC_i : std_logic_vector(g_datawidthtrb - 1 downto 0); + signal start_readout_slow_to_buffer : std_logic := '0'; signal start_readout : std_logic := '0'; signal readout_controller_data_in : std_logic_vector(g_datawidthtrb - 1 downto 0); @@ -211,6 +244,31 @@ begin counterB => mupix_filter_counterB_i, counterC => mupix_filter_counterC_i); + DataDecoder_1 : DataDecoder + generic map ( + D_W => g_datawidthtrb, + Pix_W => 8, + ToT_W => 6, + TS_W => 10, + LINKS => g_mupix_links + ) + port map ( + clk => clk + reset => reset_reg, + bypass => converter_bypass_i, + datain => mupix_filter_dataout_i, + datain_valid => mupix_filter_dataout_valid_i, + counterA_in => mupix_filter_counterA_i, + counterB_in => mupix_filter_counterB_i, + counterC_in => mupix_filter_counterC_i, + + dataout => decoder_dataout_i, + dataout_valid => decoder_dataout_valid_i, + counterA_out => decoder_counterA_i, + counterB_out => decoder_counterB_i, + counterC_out => decoder_counterC_i, + ); + cycl_buffer_1 : entity work.CircularMemory generic map( g_datawidth => g_datawidthtrb, @@ -221,8 +279,8 @@ begin port map( clk => clk, rst => reset_reg, - wr_en => mupix_filter_dataout_valid_i, - data_in => mupix_filter_dataout_i, + wr_en => decoder_dataout_valid_i, + data_in => decoder_dataout_i, rd_en => readout_controller_rd_en, offset_en => readout_controller_offset_en, offset => readout_words, @@ -310,6 +368,7 @@ begin --0x10c: counter link A (read-only) --0x10d: counter link B (read-only) --0x10e: counter link C (read-only) + --0x10f: address/gray decoder bypass ----------------------------------------------------------------------------------- slv_bus_handler : process(clk) is begin @@ -363,6 +422,9 @@ begin when x"0106" => multiplexer_channel_sel <= to_integer(unsigned(SLV_DATA_IN_i)); SLV_ACK_OUT <= '1'; + when x"010f" => + decoder_bypass_i <= SLV_DATA_IN_i(0); + SLV_ACK_OUT <= '1'; when others => slv_unknown_addr_out <= '1'; end case; @@ -410,14 +472,17 @@ begin SLV_DATA_OUT(3 downto 0) <= readout_controller_busy & start_readout & start_readout_slow_to_buffer & trb_trigger; SLV_ACK_OUT <= '1'; when x"010c" => - SLV_DATA_OUT <= mupix_filter_counterA_i; + SLV_DATA_OUT <= decoder_counterA_i; SLV_ACK_OUT <= '1'; when x"010d" => - SLV_DATA_OUT <= mupix_filter_counterB_i; + SLV_DATA_OUT <= decoder_counterB_i; SLV_ACK_OUT <= '1'; when x"010e" => - SLV_DATA_OUT <= mupix_filter_counterC_i; + SLV_DATA_OUT <= decoder_counterC_i; SLV_ACK_OUT <= '1'; + when x"010f" => + SLV_DATA_OUT(0) <= decoder_bypass_i; + SLV_ACK_OUT <= '1'; when others => slv_unknown_addr_out <= '1'; end case; diff --git a/mupix/Mupix8/sources/Datapath/PixelAddressDecode.vhd b/mupix/Mupix8/sources/Datapath/PixelAddressDecode.vhd index 16fa267..d518afc 100644 --- a/mupix/Mupix8/sources/Datapath/PixelAddressDecode.vhd +++ b/mupix/Mupix8/sources/Datapath/PixelAddressDecode.vhd @@ -1,4 +1,4 @@ ------------------------------------------------------------- +----------------------------------------------------------- -- Decoding of pixel address of Mupix 8 to physical address -- T.Weber -- Ruhr University Bochum diff --git a/mupix/Mupix8/tb/DataDecoder_TB.vhd b/mupix/Mupix8/tb/DataDecoder_TB.vhd new file mode 100644 index 0000000..dd19974 --- /dev/null +++ b/mupix/Mupix8/tb/DataDecoder_TB.vhd @@ -0,0 +1,190 @@ +---------------------------------------------------------------------------------- +-- DataConverter & DataFilter Testbench +-- René Hagdorn +-- Ruhr-University Bochum +---------------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity DataDecoder_TB is + generic ( + D_W : integer := 32; + Pix_W : integer := 8; + ToT_W : integer := 6; + TS_W : integer := 10; + LINKS : integer := 4; + clkcyc: time := 10 ns + ); +end DataDecoder_TB; + +architecture Behavioral of DataDecoder_TB is + +component MupixDataFilter is + port( + clk : in std_logic; -- clock input + reset : in std_logic; -- reset input + datain : in std_logic_vector(39 downto 0); -- data in + datain_valid : in std_logic; -- data in valid signal + dataout : out std_logic_vector(31 downto 0); -- data out + dataout_valid : out std_logic; -- data out valid signal + counterA : out std_logic_vector(31 downto 0); -- last counter value link A + counterB : out std_logic_vector(31 downto 0); -- last counter value link B + counterC : out std_logic_vector(31 downto 0)); -- last counter value link C +end component; + +component DataDecoder is + generic ( + D_W : integer := 32; -- width of full data word + Pix_W : integer := 8; -- col/row address width + ToT_W : integer := 6; -- time over threshold width + TS_W : integer := 10; -- timestamp width + LINKS : integer := 4 -- number of links (data + counters) + ); + port ( + clk : in std_logic; + reset : in std_logic; + bypass : in std_logic; + datain : in std_logic_vector(D_W - 1 downto 0); -- incoming data word + datain_valid : in std_logic; -- valid signal for input data + counterA_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link A + counterB_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link B + counterC_in : in std_logic_vector(D_W - 1 downto 0); -- last counter value link B + + dataout : out std_logic_vector(D_W - 1 downto 0); -- decoded data word + dataout_valid : out std_logic; -- valid output data + counterA_out : out std_logic_vector(D_W - 1 downto 0); -- last counter value link A + counterB_out : out std_logic_vector(D_W - 1 downto 0); -- last counter value link B + counterC_out : out std_logic_vector(D_W - 1 downto 0) -- last counter value link B + ); +end component; + +signal clk : std_logic := '0'; +signal reset : std_logic := '0'; +signal bypass : std_logic := '0'; +signal datain_filter : std_logic_vector(39 downto 0) := (others => '0'); +signal datain_v_filter : std_logic := '0'; +signal datain_converter : std_logic_vector(D_W - 1 downto 0) := (others => '0'); +signal enable_converter : std_logic := '0'; +signal counterA_valid_i : std_logic := '0'; +signal counterB_valid_i : std_logic := '0'; +signal counterC_valid_i : std_logic := '0'; +signal ctrAin_converter : std_logic_vector(D_W - 1 downto 0) := (others => '0'); +signal ctrBin_converter : std_logic_vector(D_W - 1 downto 0) := (others => '0'); +signal ctrCin_converter : std_logic_vector(D_W - 1 downto 0) := (others => '0'); + +signal dataout_converter : std_logic_vector(D_W - 1 downto 0); +signal dataout_v_converter : std_logic; +signal ctrAout_converter : std_logic_vector(D_W - 1 downto 0); +signal ctrBout_converter : std_logic_vector(D_W - 1 downto 0); +signal ctrCout_converter : std_logic_vector(D_W - 1 downto 0); + +begin + + filter : MupixDataFilter + port map( + clk => clk, + reset => reset, + datain => datain_filter, + datain_valid => datain_v_filter, + dataout => datain_converter, + dataout_valid => enable_converter, + counterA => ctrAin_converter, + counterB => ctrBin_converter, + counterC => ctrCin_converter + ); + + decoder : DataDecoder + generic map( + D_W => D_W, + Pix_W => Pix_W, + ToT_W => ToT_W, + TS_W => TS_W, + LINKS => LINKS + ) + port map ( + clk => clk, + reset => reset, + bypass => bypass, + datain => datain_converter, + datain_valid => enable_converter, + counterA_in => ctrAin_converter, + counterB_in => ctrBin_converter, + counterC_in => ctrCin_converter, + dataout => dataout_converter, + dataout_valid => dataout_v_converter, + counterA_out => ctrAout_converter, + counterB_out => ctrBout_converter, + counterC_out => ctrCout_converter + ); + + takt : process + begin + wait for clkcyc/2; + clk <= not clk; + end process takt; + + stim : process + begin + wait for 100 ns; + -- first w/ converter + bypass <= '0'; + wait for 2*clkcyc; + -- writing hit data + datain_v_filter <= '1'; + datain_filter <= x"AAC0FEBABE"; + wait for clkcyc; + datain_filter <= x"BBFABEABBA"; + wait for clkcyc; + datain_filter <= x"CCBEEFBEEF"; + wait for clkcyc; + datain_filter <= x"DDBABEC0FE"; + wait for clkcyc; + datain_v_filter <= '0'; + wait for 50 ns; + -- writing counter data + datain_v_filter <= '1'; + datain_filter <= x"3AC0FEBABE"; + wait for clkcyc; + datain_filter <= x"3BFABEABBA"; + wait for clkcyc; + datain_filter <= x"3CBEEFBEEF"; + wait for clkcyc; + datain_filter <= x"3DBABEC0FE"; + wait for clkcyc; + datain_v_filter <= '0'; + wait for 10*clkcyc; + + reset <= '1', '0' after 2*clkcyc; + wait for 4*clkcyc; + + -- now w/o converter + bypass <= '1'; + wait for 2*clkcyc; + -- writing hit data + datain_v_filter <= '1'; + datain_filter <= x"AAC0FEBABE"; + wait for clkcyc; + datain_filter <= x"BBFABEABBA"; + wait for clkcyc; + datain_filter <= x"CCBEEFBEEF"; + wait for clkcyc; + datain_filter <= x"DDBABEC0FE"; + wait for clkcyc; + datain_v_filter <= '0'; + wait for 50 ns; + -- writing counter data + datain_v_filter <= '1'; + datain_filter <= x"3AC0FEBABE"; + wait for clkcyc; + datain_filter <= x"3BFABEABBA"; + wait for clkcyc; + datain_filter <= x"3CBEEFBEEF"; + wait for clkcyc; + datain_filter <= x"3DBABEC0FE"; + wait for clkcyc; + datain_v_filter <= '0'; + end process stim; + +end Behavioral; diff --git a/mupix/Mupix8/tb/DataFilterTest.vhd b/mupix/Mupix8/tb/DataFilterTest.vhd index 1d2883d..8e1f125 100644 --- a/mupix/Mupix8/tb/DataFilterTest.vhd +++ b/mupix/Mupix8/tb/DataFilterTest.vhd @@ -17,8 +17,8 @@ architecture sim of MupixDataFilterTest is dataout_valid : out std_logic; -- data out valid signal counterA : out std_logic_vector(31 downto 0); -- last counter value link A counterB : out std_logic_vector(31 downto 0); -- last counter value link B - counterC : out std_logic_vector(31 downto 0); -- last counter value link C - counterD : out std_logic_vector(31 downto 0) -- last counter value link D + counterC : out std_logic_vector(31 downto 0) -- last counter value link C +-- counterD : out std_logic_vector(31 downto 0) -- last counter value link D ); end component MupixDataFilter; @@ -47,8 +47,8 @@ begin dataout_valid => dataout_valid, counterA => counterA, counterB => counterB, - counterC => counterC, - counterD => counterD); + counterC => counterC); +-- counterD => counterD); clk_gen : process begin diff --git a/mupix/Mupix8/tb/GrayDecoder_TB.vhd b/mupix/Mupix8/tb/GrayDecoder_TB.vhd new file mode 100644 index 0000000..8f89564 --- /dev/null +++ b/mupix/Mupix8/tb/GrayDecoder_TB.vhd @@ -0,0 +1,75 @@ +---------------------------------------------------------------------------------- +-- Testbench for Gray Decoder by Tobias Weber +-- René Hagdorn, Ruhr-University Bochum +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + + +entity GrayDecoder_TB is + generic ( + N_BITS : integer := 10; + clkcnt : time := 10 ns + ); +end GrayDecoder_TB; + +architecture Behavioral of GrayDecoder_TB is + +component gray_to_binary is + generic(NBITS : integer := 10); + port ( + clk : in std_logic; -- clk input + reset : in std_logic; -- reset input + bypass : in std_logic; -- bypass logic + gray_in : in std_logic_vector (NBITS - 1 downto 0); -- gray counter input + bin_out : out std_logic_vector (NBITS - 1 downto 0) -- binary counter output + ); +end component; + +signal CLK1 : std_logic := '0'; +signal RST1 : std_logic := '0'; +signal BPS1 : std_logic := '0'; +signal GRY1 : std_logic_vector(N_BITS - 1 downto 0); +signal BIN1 : std_logic_vector(N_BITS - 1 downto 0); +signal GRYCNT : unsigned(N_BITS - 1 downto 0) := (others => '0'); + +begin + + GRAY_DECODER: gray_to_binary + generic map( + NBITS => N_BITS + ) + port map( + clk => CLK1, + reset => RST1, + bypass => BPS1, + gray_in => GRY1, + bin_out => BIN1 + ); + + TAKT: process + begin + wait for clkcnt/2; + CLK1 <= not CLK1; + end process TAKT; + + COUNTER: process(CLK1) + begin + if rising_edge(CLK1) then + GRYCNT <= GRYCNT + 1; + end if; + end process COUNTER; + + GRY1 <= std_logic_vector(GRYCNT); + + STIM: process + begin + RST1 <= '1' after 10*clkcnt, '0' after 15*clkcnt; + BPS1 <= '1' after 25*clkcnt, '0' after 40*clkcnt; + wait; + end process STIM; + +end Behavioral; diff --git a/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd b/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd index 199892b..1731f5d 100644 --- a/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd +++ b/mupix/Mupix8/tb/MupixTRBReadoutTest.vhd @@ -88,7 +88,7 @@ architecture sim of MupixTRBReadoutTest is begin - dut : entity work.MupixTRBReadout + dut : MupixTRBReadout generic map( g_mupix_links => c_mupix_links, g_cyc_mem_address_width => c_cyc_mem_address_width, @@ -117,7 +117,7 @@ begin ); gen_input_fifo : for i in 0 to 3 generate - serdes_fifo : entity work.serdes_fifo + serdes_fifo_1 : serdes_fifo port map ( Data => fifo_datain((i + 1)*c_datawidthfifo - 1 downto i*c_datawidthfifo), WrClock => wrclk, -- 2.43.0