Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
data_serializer.vhd 4.17 KiB
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library desy;
use desy.ram_tdp;

library desyrdl;
use desyrdl.pkg_corr_matrixpi.t_mem_PSCIDTABLE_out;
use desyrdl.pkg_corr_matrixpi.t_mem_PSCIDTABLE_in;

use work.pkg_corr_matrixpi.all;

entity data_serializer is
    port(
        clk             : in std_logic;
        rst_n           : in std_logic;

        -- PSCID memory
        pscid_table_i   : in t_mem_PSCIDTABLE_out;
        pscid_table_o   : out t_mem_PSCIDTABLE_in;

        -- Status
        overrun         : out std_logic;

        -- Corr parallel input
        corrout_valid   : in std_logic;
        corrout_seq     : in std_logic_vector(C_W_BPMSEQ-1 downto 0);
        corrout         : in signed_array(0 to C_N_MM_PSC-1)(C_W_COR-1 downto 0);

        -- AXIS serial output
        m_axis_tdata    : out std_logic_vector(C_W_COR+C_W_PSCID-1 downto 0);
        m_axis_tuser    : out std_logic_vector(C_W_BPMSEQ-1 downto 0);
        m_axis_tvalid   : out std_logic;
        m_axis_tready   : in std_logic
    );
end entity data_serializer;

architecture rtl of data_serializer is


    ------------------------
    -- SIGNAL DECLARATION --
    ------------------------
    signal cnt              : unsigned(C_W_SER_CNT-1 downto 0);
    signal run_serial       : std_logic;

    signal pscid            : std_logic_vector(C_W_PSCID-1 downto 0);

    signal r_corr           : signed_array(0 to C_N_MM_PSC-1)(C_W_COR-1 downto 0);
    signal r_seq            : std_logic_vector(C_W_BPMSEQ-1 downto 0);

begin

    ------------------------
    -- SERIALIZER COUNTER --
    ------------------------
    p_cnt:process(clk, rst_n)
    begin
        if rst_n = '0' then
            cnt         <= (others => '0');
            run_serial  <= '0';
            overrun     <= '0';
        elsif rising_edge(clk) then

            if run_serial = '1' then
                if cnt = 0 then
                    -- stop at the end
                    run_serial <= '0';
                else
                    if m_axis_tready = '1' then
                        cnt <= cnt-1;
                    end if;
                end if;

                -- Transmit overrun if a valid comes here
                overrun <= corrout_valid;

            else
                if corrout_valid= '1' then
                    -- start on valid
                    run_serial <= '1';
                    cnt <= to_unsigned(C_N_MM_PSC-1, cnt'length);

                end if;

                -- No overrun possible here
                overrun <= '0';
            end if;
        end if;
    end process;

    ---------------------
    -- SHIFT REGISTERS --
    ---------------------
    p_shiftreg:process(clk, rst_n)
    begin
        if rst_n = '0' then
            r_corr  <= (others => (others => '0'));
            r_seq   <= (others => '0');
        elsif rising_edge(clk) then
            if run_serial = '1' then
                if m_axis_tready = '1' then
                    for I in 0 to C_N_MM_PSC-2 loop
                        r_corr(I) <= r_corr(I+1);
                    end loop;
                end if;
            else
                r_corr  <= corrout;
                r_seq   <= corrout_seq;
            end if;
        end if;
    end process;

    -----------------
    -- PSCID TABLE --
    ------------------
    -- Port A is read write from AXI controller, Port B is read only from logic
    inst_refx_table: entity desy.ram_tdp
    generic map(
        G_ADDR      => C_W_SER_CNT,
        G_DATA      => C_W_PSCID
    )
    port map(
        pi_clk_a    => clk,
        pi_en_a     => pscid_table_i.en,
        pi_we_a     => pscid_table_i.we,
        pi_addr_a   => pscid_table_i.addr(C_W_SER_CNT-1 downto 0),
        pi_data_a   => pscid_table_i.data,
        po_data_a   => pscid_table_o.data,
        pi_clk_b    => clk,
        pi_en_b     => '1',
        pi_we_b     => '0',
        pi_addr_b   => std_logic_vector(cnt),
        pi_data_b   => (others => '0'),
        po_data_b   => pscid
    );

    -----------------------
    -- OUTPUT CONNEXIONS --
    -----------------------
    m_axis_tdata    <= pscid & std_logic_vector(r_corr(0));
    m_axis_tuser    <= r_seq;
    m_axis_tvalid   <= run_serial;


end architecture;