OpenCores
URL https://opencores.org/ocsvn/viterbi_decoder_axi4s/viterbi_decoder_axi4s/trunk

Subversion Repositories viterbi_decoder_axi4s

[/] [viterbi_decoder_axi4s/] [trunk/] [src/] [ram_ctrl.vhd] - Diff between revs 2 and 6

Show entire file | Details | Blame | View Log

Rev 2 Rev 6
Line 1... Line 1...
--!
--!
--! Copyright (C) 2011 - 2012 Creonic GmbH
--! Copyright (C) 2011 - 2014 Creonic GmbH
--!
--!
--! This file is part of the Creonic Viterbi Decoder, which is distributed
--! This file is part of the Creonic Viterbi Decoder, which is distributed
--! under the terms of the GNU General Public License version 2.
--! under the terms of the GNU General Public License version 2.
--!
--!
--! @file
--! @file
Line 75... Line 75...
        --
        --
        -- Record contains runtime configuration.
        -- Record contains runtime configuration.
        -- The input configuration is stored in a register.
        -- The input configuration is stored in a register.
        -- It is received from a AXI4-Stream interface from the top entity.
        -- It is received from a AXI4-Stream interface from the top entity.
        --
        --
        -- We just receive window_length and acquisition_length from the outside. All
 
        -- other values are computed internally in order to impreove timing of the core:
 
        -- m denotes minus,
 
        -- p denotes plus.
 
        --
 
        type trec_runtime_param is record
        type trec_runtime_param is record
                window_length           : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
                window_length           : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
                acquisition_length      : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
                acquisition_length      : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
                window_p_acquisition    : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
                window_p_acquisition_m1 : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
                window_p_acquisition_m2 : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
                window_p_acquisition_m3 : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
                window_m1               : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
        end record trec_runtime_param;
        end record trec_runtime_param;
 
 
        -- Types for finite state machines
        -- Types for finite state machines
        type t_ram_ctrl is (CONFIGURE, START, BEGINNING, RUNNING, ENDING);
        type t_write_ram_fsm is (CONFIGURE, START, RUN, WAIT_FOR_TRACEBACK, WAIT_FOR_LAST_TRACEBACK);
 
        type t_read_ram_fsm is (WAIT_FOR_WINDOW, TRACEBACK, WAIT_FOR_RAM, FINISH);
 
        type t_read_ram_fsm_array is array (0 to 1) of t_read_ram_fsm;
 
 
        -- RAM controling types
        -- RAM controling types
        type t_ram_data    is array (3 downto 0) of std_logic_vector(NUMBER_TRELLIS_STATES - 1 downto 0);
        type t_ram_data    is array (3 downto 0) of std_logic_vector(NUMBER_TRELLIS_STATES - 1 downto 0);
        type t_ram_addr    is array (3 downto 0) of unsigned(BW_MAX_WINDOW_LENGTH - 1  downto 0);
        type t_ram_addr    is array (3 downto 0) of unsigned(BW_MAX_WINDOW_LENGTH - 1  downto 0);
        type t_ram_rd_addr is array (1 downto 0) of unsigned(BW_MAX_WINDOW_LENGTH - 1  downto 0);
        type t_ram_rd_addr is array (1 downto 0) of unsigned(BW_MAX_WINDOW_LENGTH - 1  downto 0);
Line 107... Line 99...
 
 
        ------------------------
        ------------------------
        -- Signal declaration
        -- Signal declaration
        ------------------------
        ------------------------
 
 
 
        signal ram_buffer   : t_ram_rd_data;
 
        signal ram_buffer_full   : std_logic_vector(1 downto 0);
 
 
        signal config          : trec_runtime_param;
        signal config          : trec_runtime_param;
        signal ram_ctrl_fsm    : t_ram_ctrl;
        signal write_ram_fsm   : t_write_ram_fsm;
        signal en_ram, wen_ram : std_logic_vector(3 downto 0);
        signal read_ram_fsm    : t_read_ram_fsm_array;
 
        signal wen_ram         : std_logic_vector(3 downto 0);
        signal addr            : t_ram_addr;
        signal addr            : t_ram_addr;
        signal d               : std_logic_vector(NUMBER_TRELLIS_STATES - 1 downto 0);
 
        signal q               : t_ram_rd_data;
 
        signal q_reg           : t_ram_data;
        signal q_reg           : t_ram_data;
 
 
        -- ram addess, number and data pointer
        -- ram addess, number and data pointer
        signal write_ram_ptr                                : unsigned(1 downto 0);
        signal write_ram_ptr                                : unsigned(1 downto 0);
        signal read_ram_ptr, read_ram_data_ptr              : t_ram_ptr;
        signal read_ram_ptr   : t_ram_ptr;
        signal read_ram_data_ptr_d1                         : t_ram_ptr;
        signal read_ram_ptr_d : t_ram_ptr;
        signal write_addr_ptr, read_addr_ptr, last_addr_ptr : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
        signal write_addr_ptr : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
        signal read_addr_ptr  : t_ram_rd_addr;
        -- control flags
 
        signal switch_ram, switch_state, ram_writing : boolean;
 
 
 
        -- internal signals of outputs
        -- internal signals of outputs
        signal m_axis_output_tvalid_int     : std_logic_vector(1 downto 0);
        signal m_axis_output_tvalid_int     : std_logic_vector(1 downto 0);
 
        signal m_axis_output_tlast_int       : std_logic_vector(1 downto 0);
 
        signal m_axis_output_window_tuser_int : std_logic_vector(1 downto 0);
        signal m_axis_output_last_tuser_int : std_logic_vector(1 downto 0);
        signal m_axis_output_last_tuser_int : std_logic_vector(1 downto 0);
        signal s_axis_input_tready_int      : std_logic;
        signal s_axis_input_tready_int      : std_logic;
 
        signal s_axis_ctrl_tready_int         : std_logic;
 
 
        -- delay signals of inputs
        signal next_traceback : std_logic_vector(1 downto 0);
        signal m_axis_output_tvalid_d1, m_axis_output_tvalid_d2  : std_logic_vector(1 downto 0);
        signal write_window_complete : std_logic;
 
        signal write_last_window_complete : std_logic;
        signal next_traceback, not_next_traceback : integer range 1 downto 0;
        signal last_of_block : std_logic;
        signal data_cnt                           : t_ram_data_cnt;
        signal read_last_addr_ptr : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
 
begin
begin
 
 
        s_axis_input_tready     <= '1' when (m_axis_output_tready = "11" or m_axis_output_tvalid_int(0) = '0'
 
                                             or m_axis_output_tvalid_int(1) = '0')
 
                                             and ram_ctrl_fsm /= CONFIGURE and ram_ctrl_fsm /= ENDING else
 
                                   '0';
 
 
 
        s_axis_input_tready_int <= '1' when (m_axis_output_tready = "11" or m_axis_output_tvalid_int(0) = '0'
 
                                             or m_axis_output_tvalid_int(1) = '0')
 
                                             and ram_ctrl_fsm /= CONFIGURE and ram_ctrl_fsm /= ENDING else
 
                                   '0';
 
 
 
        m_axis_output_last_tuser <= m_axis_output_last_tuser_int;
 
        m_axis_output_tvalid     <= m_axis_output_tvalid_int;
        m_axis_output_tvalid     <= m_axis_output_tvalid_int;
        m_axis_output_tdata      <= q;
        m_axis_output_tlast        <= m_axis_output_tlast_int;
 
        m_axis_output_window_tuser <= m_axis_output_window_tuser_int;
 
        m_axis_output_last_tuser   <= m_axis_output_last_tuser_int;
 
        m_axis_output_tdata(0)     <= q_reg(to_integer(read_ram_ptr_d(0))) when ram_buffer_full(0) = '0' else ram_buffer(0);
 
        m_axis_output_tdata(1)     <= q_reg(to_integer(read_ram_ptr_d(1))) when ram_buffer_full(1) = '0' else ram_buffer(1);
 
 
 
 
        --
        --
        -- Statemachine handles configuration, write/read to/from ram
        -- When the output port is not ready to read the output of the RAM immediately
        -- and forwarding decision vectors to corresponding traceback units
        -- we have to remember the output value of the RAM in an extra register.
 
        -- When the output is ready to read, we first use the ouput of the register
 
        -- and only then the output of the RAM again.
        --
        --
 
        pr_buf_ram_output: process(clk) is
        pr_ctrl_ram : process(clk, write_ram_ptr, read_ram_ptr) is
 
                variable v_write_ram_ptr : integer range 3 downto 0;
 
                variable v_read_ram_ptr  : t_ram_ptr_int;
 
        begin
        begin
        v_write_ram_ptr   := to_integer(write_ram_ptr);
 
        v_read_ram_ptr(0) := to_integer(read_ram_ptr(0));
 
        v_read_ram_ptr(1) := to_integer(read_ram_ptr(1));
 
        if rising_edge(clk) then
        if rising_edge(clk) then
                if rst = '1' then
                if rst = '1' then
                        ram_ctrl_fsm              <= CONFIGURE;
                        ram_buffer <= (others => (others => '0'));
 
                        ram_buffer_full <= (others => '0');
 
                else
 
 
                        config.window_length      <= (others => '0');
                        for i in 0 to 1 loop
                        config.acquisition_length <= (others => '0');
                                if m_axis_output_tvalid_int(i) = '1' and m_axis_output_tready(i) = '0' and ram_buffer_full(i) = '0' then
 
                                        ram_buffer(i) <=  q_reg(to_integer(read_ram_ptr_d(i)));
 
                                        ram_buffer_full(i) <= '1';
 
                                end if;
 
 
                        en_ram                    <= (others => '1');
                                if m_axis_output_tvalid_int(i) = '1' and m_axis_output_tready(i) = '1' and ram_buffer_full(i) = '1' then
                        wen_ram                   <= (others => '0');
                                        ram_buffer_full(i) <= '0';
                        addr                      <= (others => (others => '0'));
                                end if;
 
                        end loop;
 
 
                        write_ram_ptr             <= to_unsigned(0, 2);
                end if;
                        write_addr_ptr            <= (others => '0');
        end if;
                        last_addr_ptr             <= (others => '0');
        end process pr_buf_ram_output;
 
 
                        read_ram_ptr              <= (to_unsigned(2, 2), to_unsigned(3, 2));
        -----------------------------
                        read_ram_data_ptr         <= (to_unsigned(2, 2), to_unsigned(3, 2));
        -- Manage writing from ACS --
                        read_ram_data_ptr_d1      <= (to_unsigned(2, 2), to_unsigned(3, 2));
        -----------------------------
                        read_addr_ptr             <= (others => '0');
        s_axis_input_tready_int <= '0' when (write_ram_fsm = CONFIGURE) or
                        next_traceback            <= 0;
                                   (write_ram_ptr = read_ram_ptr(0) and read_ram_fsm(0) /= WAIT_FOR_WINDOW) or
                        not_next_traceback        <= 1;
                                   (write_ram_ptr = read_ram_ptr(1) and read_ram_fsm(1) /= WAIT_FOR_WINDOW) or
 
                                    write_ram_fsm = WAIT_FOR_TRACEBACK or write_ram_fsm = WAIT_FOR_LAST_TRACEBACK else
                        switch_ram                <= false;
                                   '1';
                        switch_state              <= false;
        s_axis_input_tready <= s_axis_input_tready_int;
                        ram_writing               <= true;
 
 
 
                        m_axis_output_last_tuser_int     <= (others => '0');
 
                        m_axis_output_window_tuser       <= (others => '0');
 
                        m_axis_output_tvalid_int  <= (others => '0');
 
                        m_axis_output_tvalid_d1   <= (others => '0');
 
                        m_axis_output_tvalid_d2   <= (others => '0');
 
                        m_axis_output_tlast       <= (others => '0');
 
                        s_axis_ctrl_tready        <= '1';
 
                else
 
                        addr(v_write_ram_ptr)   <= write_addr_ptr;
 
                        addr(v_read_ram_ptr(0)) <= read_addr_ptr;
 
                        addr(v_read_ram_ptr(1)) <= read_addr_ptr;
 
 
 
                        d <= s_axis_input_tdata;
        s_axis_ctrl_tready_int <= '1' when (read_ram_fsm(0) = WAIT_FOR_WINDOW and read_ram_fsm(1) = WAIT_FOR_WINDOW and write_ram_fsm = CONFIGURE) else
 
                                  '0';
 
        s_axis_ctrl_tready <= s_axis_ctrl_tready_int;
 
 
                        q(0)   <= q_reg(to_integer(read_ram_data_ptr(0)));
        -- Process for writing to the RAM
                        q(1)   <= q_reg(to_integer(read_ram_data_ptr(1)));
        pr_write_ram: process(clk) is
 
                variable v_window_length      : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
                variable v_acquisition_length : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
 
        begin
 
        if rising_edge(clk) then
 
                if rst = '1' then
 
                        write_ram_fsm         <= CONFIGURE;
 
                        write_addr_ptr        <= (others => '0');
 
                        write_ram_ptr         <= (others => '0');
 
                        wen_ram               <= (others => '0');
 
                        write_window_complete <= '0';
 
                        write_last_window_complete <= '0';
 
                        read_last_addr_ptr    <= (others => '0');
 
                else
 
 
                        case ram_ctrl_fsm is
                        case write_ram_fsm is
 
 
                        --
                        --
                        -- It is necessary to configure the decoder before each block
                        -- It is necessary to configure the decoder before each block
                        -- The decoder is always ready to receive on the ctrl channel, when it is in this state
 
                        --
                        --
                        when CONFIGURE =>
                        when CONFIGURE =>
                                if s_axis_ctrl_tvalid = '1' then
                                write_window_complete <= '0';
                                        config.window_length      <= unsigned(s_axis_ctrl_tdata(BW_MAX_WINDOW_LENGTH - 1 + 16 downto 16));
                                write_last_window_complete <= '0';
                                        config.acquisition_length <= unsigned(s_axis_ctrl_tdata(BW_MAX_WINDOW_LENGTH - 1      downto  0));
                                if s_axis_ctrl_tvalid = '1' and s_axis_ctrl_tready_int = '1' then
                                        ram_ctrl_fsm <= START;
                                        v_window_length           := unsigned(s_axis_ctrl_tdata(BW_MAX_WINDOW_LENGTH - 1 + 16 downto 16));
                                        wen_ram(v_write_ram_ptr) <= '1';
                                        v_acquisition_length      := unsigned(s_axis_ctrl_tdata(BW_MAX_WINDOW_LENGTH - 1      downto  0));
                                        s_axis_ctrl_tready <= '0';
                                        write_addr_ptr            <= v_window_length - v_acquisition_length;
 
                                        config.window_length      <= v_window_length;
 
                                        config.acquisition_length <= v_acquisition_length;
 
                                        write_ram_fsm             <= START;
 
 
 
                                        wen_ram(to_integer(write_ram_ptr)) <= '1';
                                end if;
                                end if;
 
 
 
 
                        --
                        --
                        -- After the decoder is configured, the decoder is waiting for a new block
                        -- After the decoder is configured, the decoder is waiting for a new block.
                        -- When the AXIS handshake is there the packettransmission begins
                        -- When the AXIS handshake is there the packet transmission begins.
 
                        -- The first write is a special case, since writing data starts at the acquisition length.
 
                        -- There is no complete window available afterwards.
                        --
                        --
                        when START =>
                        when START =>
                                if s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' then
                                if s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' then
                                        ram_ctrl_fsm             <= BEGINNING;
 
                                        write_addr_ptr           <= write_addr_ptr + 1;
 
                                        read_ram_ptr(next_traceback)                     <= write_ram_ptr - 1;
 
                                        read_ram_ptr(not_next_traceback)                 <= write_ram_ptr - 2;
 
                                else
 
                                        write_addr_ptr                 <= config.window_length - config.acquisition_length;
 
 
 
                                        config.window_p_acquisition    <= config.window_length + config.acquisition_length;
                                        if write_addr_ptr = config.window_length - 1 then
                                        config.window_p_acquisition_m1 <= config.window_length + config.acquisition_length - 1;
 
                                        config.window_p_acquisition_m2 <= config.window_length + config.acquisition_length - 2;
 
                                        config.window_p_acquisition_m3 <= config.window_length + config.acquisition_length - 3;
 
                                        config.window_m1               <= config.window_length - 1;
 
                                end if;
 
 
 
                        --
                                                -- When we switch to the next RAM, we reset the write addr.
                        -- The first arriving data have to be stored on special locations to guarantee
                                                write_addr_ptr <= (others => '0');
                        -- a non malicious behavior of the traceback units.
 
                        --
                                                -- Switch to the next RAM.
                        when BEGINNING =>
 
                                if s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' then
 
                                        if switch_ram then
 
                                                ram_ctrl_fsm <= RUNNING;
 
                                                wen_ram(to_integer(unsigned(write_ram_ptr - 1))) <= '0';
 
                                                wen_ram(v_write_ram_ptr)                         <= '1';
 
                                                write_addr_ptr                                   <= write_addr_ptr + 1;
 
                                                read_addr_ptr                                    <= read_addr_ptr  - 1;
 
                                                switch_ram                                       <= false;
 
                                        else
 
                                                if write_addr_ptr = config.window_m1 then
 
                                                        write_addr_ptr <= to_unsigned(0, BW_MAX_WINDOW_LENGTH);
 
                                                        read_addr_ptr  <= config.window_m1;
 
                                                        write_ram_ptr  <= write_ram_ptr + 1;
                                                        write_ram_ptr  <= write_ram_ptr + 1;
                                                        switch_ram     <= true;
                                                wen_ram(to_integer(write_ram_ptr))     <= '0';
 
                                                wen_ram(to_integer(write_ram_ptr + 1)) <= '1';
 
 
 
                                                write_ram_fsm  <= RUN;
                                                else
                                                else
                                                        write_addr_ptr <= write_addr_ptr + 1;
                                                        write_addr_ptr <= write_addr_ptr + 1;
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                end if;
 
 
 
                        --
                        --
                        -- The running state handles the most decoding
                        -- The decoder is receiving data from the ACS.
                        -- It handels the writing of forward to ram and reading the decision vecotors
                        --
                        -- the decision vecotrs are forwarded to the traceback units.
                        when RUN =>
                        --
                                write_window_complete <= '0';
                        when RUNNING =>
                                write_last_window_complete <= '0';
                                if (s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' and ram_writing) or
 
                                   ((m_axis_output_tready(0) = '1' and m_axis_output_tready(1) = '1') and not(ram_writing)) then
                                if s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' then
 
                                        write_addr_ptr <= write_addr_ptr + 1;
                                        read_ram_data_ptr_d1 <= read_ram_ptr;
 
                                        read_ram_data_ptr    <= read_ram_data_ptr_d1;
                                        if write_addr_ptr = config.window_length - 1 then
                                        m_axis_output_tvalid_int <= m_axis_output_tvalid_d1;
 
                                        m_axis_output_tvalid_d1  <= m_axis_output_tvalid_d2;
                                                -- When we switch to the next RAM, we reset the write addr.
 
                                                write_addr_ptr <= (others => '0');
                                        if switch_ram then
 
                                                if ram_writing then
                                                -- Switch to the next RAM.
                                                        wen_ram(to_integer(unsigned(write_ram_ptr - 1))) <= '0';
 
                                                        wen_ram(v_write_ram_ptr)                         <= '1';
 
                                                        next_traceback                                   <= not_next_traceback;
 
                                                        not_next_traceback                               <= next_traceback;
 
                                                else
 
                                                        ram_ctrl_fsm <= ENDING;
 
                                                        ram_writing <= true;
 
                                                        wen_ram(to_integer(unsigned(write_ram_ptr - 1))) <= '0';
 
                                                end if;
 
                                                switch_ram      <= false;
 
                                        else
 
                                                if write_addr_ptr = config.window_m1 then
 
                                                        write_ram_ptr                    <= write_ram_ptr + 1;
                                                        write_ram_ptr                    <= write_ram_ptr + 1;
                                                        read_ram_ptr(next_traceback)     <= write_ram_ptr;
                                                wen_ram(to_integer(write_ram_ptr))     <= '0';
                                                        read_ram_ptr(not_next_traceback) <= write_ram_ptr - 2;
                                                wen_ram(to_integer(write_ram_ptr + 1)) <= '1';
                                                        switch_ram                       <= true;
 
                                                        data_cnt(next_traceback)         <= 0;
 
                                                end if;
 
                                        end if;
 
 
 
                                        -- Store last RAM address and stop writing after last bit of a block arrives
                                                -- Indicate, that a complete window is within the RAM and traceback may start.
                                        if s_axis_input_tlast = '1' then
                                                write_window_complete <= '1';
                                                ram_writing              <= false;
 
                                                last_addr_ptr            <= write_addr_ptr;
                                                if read_ram_fsm(0) /= WAIT_FOR_WINDOW and read_ram_fsm(1) /= WAIT_FOR_WINDOW then
--                                              wen_ram(v_write_ram_ptr) <= '0';
                                                        write_ram_fsm <= WAIT_FOR_TRACEBACK;
                                        end if;
                                        end if;
 
 
                                        -- Handle RAM addess point increase and reset
 
                                        if write_addr_ptr = config.window_m1 then
 
                                                write_addr_ptr <= to_unsigned(0, BW_MAX_WINDOW_LENGTH);
 
                                                read_addr_ptr  <= config.window_m1;
 
                                        else
                                        else
                                                write_addr_ptr <= write_addr_ptr + 1;
                                                write_addr_ptr <= write_addr_ptr + 1;
                                                read_addr_ptr  <= read_addr_ptr  - 1;
 
                                        end if;
                                        end if;
 
 
                                        -- Handle side channel information for traceback units.
                                        if s_axis_input_tlast = '1' then
                                        for i in 1 downto 0 loop
                                                write_ram_fsm <= CONFIGURE;
                                                if m_axis_output_tvalid_d1(i) = '1' then
                                                wen_ram       <= (others => '0');
                                                        data_cnt(i) <= data_cnt(i) + 1;
 
 
                                                write_last_window_complete <= '1';
 
                                                if (read_ram_fsm(0) /= WAIT_FOR_WINDOW and read_ram_fsm(1) /= WAIT_FOR_WINDOW) or write_window_complete = '1' then
 
                                                        write_ram_fsm <= WAIT_FOR_LAST_TRACEBACK;
                                                end if;
                                                end if;
 
                                                read_last_addr_ptr <= write_addr_ptr;
 
 
                                                -- Signals the valid signal
                                                write_addr_ptr <= (others => '0');
                                                if data_cnt(i) = config.window_p_acquisition_m2 then
                                                write_ram_ptr                          <= write_ram_ptr + 1;
                                                        m_axis_output_tvalid_d2(i)              <= '0';
 
                                                end if;
                                                end if;
                                                if switch_ram and ram_writing then
 
                                                        m_axis_output_tvalid_d2(next_traceback) <= '1';
 
                                                end if;
                                                end if;
 
 
                                                -- Signals the end of the current window
                        when WAIT_FOR_TRACEBACK =>
                                                if m_axis_output_last_tuser_int(i) = '1' then
                                if read_ram_fsm(0) = WAIT_FOR_WINDOW or read_ram_fsm(1) = WAIT_FOR_WINDOW then
                                                        m_axis_output_last_tuser_int(i) <= '0';
                                        write_ram_fsm <= RUN;
                                                end if;
                                        write_window_complete <= '0';
                                                if data_cnt(i) = config.window_p_acquisition_m1 then
 
                                                        m_axis_output_last_tuser_int(i) <= '1';
 
                                                end if;
                                                end if;
 
 
                                                -- Signals, whether there is acquisition or window
                        when WAIT_FOR_LAST_TRACEBACK =>
                                                if data_cnt(i) = config.window_p_acquisition then
                                if read_ram_fsm(0) = WAIT_FOR_WINDOW or read_ram_fsm(1) = WAIT_FOR_WINDOW then
                                                        m_axis_output_window_tuser(i) <= '0';
                                        write_ram_fsm <= CONFIGURE;
 
                                        write_last_window_complete <= '0';
                                                end if;
                                                end if;
                                                if data_cnt(i) = config.acquisition_length then
 
                                                        m_axis_output_window_tuser(i) <= '1';
                        end case;
                                                end if;
                                                end if;
                                        end loop;
 
                                end if;
                                end if;
 
        end process pr_write_ram;
 
 
                        --
 
                        -- Handle last traceback with no acquisition
 
                        -- Maybe the resulting window is longer than others
 
                        --
 
                        when ENDING =>
 
                                if m_axis_output_tready(0) = '1' and m_axis_output_tready(1) = '1' then
 
 
 
                                        read_ram_data_ptr_d1     <= read_ram_ptr;
        -------------------------------------------
                                        read_ram_data_ptr        <= read_ram_data_ptr_d1;
        -- Manage reading from RAM for traceback --
                                        m_axis_output_tvalid_int <= m_axis_output_tvalid_d1;
        -------------------------------------------
 
 
                                        for i in 1 downto 0 loop
 
                                                if m_axis_output_tvalid_int(i) = '1' then
 
                                                        data_cnt(i) <= data_cnt(i) + 1;
 
                                                end if;
 
                                        end loop;
 
 
 
                                        if data_cnt(not_next_traceback) = config.window_p_acquisition_m3 then
        gen_read_ram: for i in 0 to 1 generate
                                                read_addr_ptr <= last_addr_ptr;
                pr_read_ram: process(clk) is
                                        elsif read_addr_ptr = 0 then
                begin
                                                read_ram_ptr(0) <= read_ram_ptr(0) - 1;
                if rising_edge(clk) then
                                                read_ram_ptr(1) <= read_ram_ptr(1) - 1;
                        if rst = '1' then
                                                read_addr_ptr   <= config.window_m1;
                                read_addr_ptr(i) <= (others => '0');
 
                                read_ram_fsm(i)  <= WAIT_FOR_WINDOW;
 
                                m_axis_output_tvalid_int(i)       <= '0';
 
                                m_axis_output_tlast_int(i)        <= '0';
 
                                m_axis_output_window_tuser_int(i) <= '0';
 
                                m_axis_output_last_tuser_int(i)   <= '0';
 
                                read_ram_ptr(i)                   <= (others => '0');
 
                                read_ram_ptr_d(i)                 <= (others => '0');
                                        else
                                        else
                                                read_addr_ptr <= read_addr_ptr  - 1;
 
                                        end if;
 
 
 
                                        if data_cnt(not_next_traceback) =  config.window_p_acquisition_m1 then
                                read_ram_ptr_d(i) <= read_ram_ptr(i);
                                                m_axis_output_last_tuser_int(not_next_traceback) <= '1';
                                case read_ram_fsm(i) is
                                                m_axis_output_tvalid_d1(next_traceback)          <= '1';
 
                                                m_axis_output_tvalid_d1(not_next_traceback)     <= '0';
                                -- Wait for the next window to be ready within the RAM.
 
                                when WAIT_FOR_WINDOW =>
 
                                        read_addr_ptr(i) <= config.window_length - 1;
 
                                        m_axis_output_tlast_int(i) <= '0';
 
                                        m_axis_output_tvalid_int(i) <= '0';
 
                                        m_axis_output_last_tuser_int(i) <= '0';
 
                                        m_axis_output_window_tuser_int(i) <= '0';
 
                                        read_ram_ptr(i)   <= write_ram_ptr;
 
 
 
                                        -- We always start from the RAM, which was written last.
 
                                        if write_window_complete = '1' and next_traceback(i) = '1' then
 
                                                read_ram_ptr(i)   <= write_ram_ptr - 1;
 
                                                read_addr_ptr(i)            <= read_addr_ptr(i) - 1;
 
                                                read_ram_fsm(i)             <= TRACEBACK;
 
                                                m_axis_output_tvalid_int(i) <= '1';
 
                                        end if;
 
                                        if write_last_window_complete = '1' and next_traceback(i) = '1' then
 
                                                read_ram_ptr(i)   <= write_ram_ptr - 1;
 
                                                read_addr_ptr(i)            <= read_last_addr_ptr;
 
                                                read_ram_fsm(i)             <= TRACEBACK;
 
                                                m_axis_output_window_tuser_int(i) <= '1';
 
                                        end if;
 
 
 
                                -- Perform the Traceback on the RAM data of the first RAM we need for acquisition and traceback.
 
                                when TRACEBACK =>
 
                                        m_axis_output_tlast_int(i) <= '0';
 
                                        m_axis_output_last_tuser_int(i) <= '0';
 
                                        m_axis_output_tvalid_int(i) <= '1';
 
 
 
                                        if m_axis_output_tready(i) = '1' then
 
                                                if read_addr_ptr(i) = 0 then
 
                                                        if read_ram_fsm(1 - i) = TRACEBACK and read_ram_ptr(1 - i) = read_ram_ptr(i) - 1 then
 
                                                                read_ram_fsm(i) <= WAIT_FOR_RAM;
 
                                                        else
 
                                                                read_addr_ptr(i) <= config.window_length - 1;
 
                                                                read_ram_ptr(i)  <= read_ram_ptr(i) - 1;
 
                                                                read_ram_fsm(i)  <= FINISH;
 
                                                        end if;
 
                                                else
 
                                                        read_addr_ptr(i) <= read_addr_ptr(i) - 1;
                                        end if;
                                        end if;
 
 
                                        if data_cnt(not_next_traceback) = config.window_p_acquisition then
                                                -- Signal the traceback unit, acquisition is over.
                                                m_axis_output_window_tuser(not_next_traceback)  <= '0';
                                                if read_addr_ptr(i) = config.window_length - config.acquisition_length - 1 then
                                                m_axis_output_window_tuser(next_traceback) <= '1';
                                                        m_axis_output_window_tuser_int(i) <= '1';
 
                                                end if;
                                        end if;
                                        end if;
 
 
                                        if data_cnt(not_next_traceback) = config.acquisition_length then
                                when WAIT_FOR_RAM =>
                                                m_axis_output_window_tuser(not_next_traceback) <= '1';
                                        m_axis_output_tvalid_int(i) <= '0';
 
                                        if read_ram_fsm(1 - i) /= TRACEBACK or read_ram_ptr(1 - i) /= read_ram_ptr(i) - 1 then
 
                                                read_addr_ptr(i) <= config.window_length - 1;
 
                                                read_ram_ptr(i)  <= read_ram_ptr(i) - 1;
 
                                                read_ram_fsm(i)  <= FINISH;
                                        end if;
                                        end if;
 
 
                                        if m_axis_output_last_tuser_int(not_next_traceback) = '1' then
                                -- Get the remaining values from the second RAM we need for traceback (no acquisition values in this RAM)
                                                m_axis_output_last_tuser_int(not_next_traceback) <= '0';
                                when FINISH =>
 
                                        if m_axis_output_tvalid_int(i) <= '0' then
 
                                                m_axis_output_tvalid_int(i) <= '1';
 
                                                read_addr_ptr(i) <= read_addr_ptr(i) - 1;
                                        end if;
                                        end if;
 
                                        if m_axis_output_tready(i) = '1' then
 
 
 
                                                if read_addr_ptr(i) = config.window_length - config.acquisition_length then
 
                                                        m_axis_output_last_tuser_int(i) <= '1';
 
                                                        read_addr_ptr(i)        <= config.window_length - 1;
 
                                                        read_ram_fsm(i)         <= WAIT_FOR_WINDOW;
 
 
                                        if data_cnt(next_traceback) = last_addr_ptr + config.acquisition_length - 1 then
                                                        -- Check if the other read process finished processing.
                                                m_axis_output_tvalid_d1(next_traceback)      <= '0';
                                                        if read_ram_fsm((i+1) mod 2) = WAIT_FOR_WINDOW and last_of_block = '1' then
                                                m_axis_output_last_tuser_int(next_traceback) <= '1';
                                                                m_axis_output_tlast_int(i) <= '1';
                                                m_axis_output_tlast(next_traceback)          <= '1';
 
                                                switch_state                                 <= true;
 
                                        end if;
                                        end if;
 
 
                                        -- block is finished and the decoder is ready for a new configuration and block
                                                else
                                        if switch_state then
                                                        read_addr_ptr(i) <= read_addr_ptr(i) - 1;
                                                switch_state                 <= false;
 
                                                m_axis_output_last_tuser_int <= "00";
 
                                                m_axis_output_window_tuser   <= "00";
 
                                                m_axis_output_tlast          <= "00";
 
                                                ram_ctrl_fsm                 <= CONFIGURE;
 
                                                s_axis_ctrl_tready           <= '1';
 
                                                data_cnt(0)                  <= 0;
 
                                                data_cnt(1)                  <= 0;
 
                                                m_axis_output_tvalid_int  <= (others => '0');
 
                                                m_axis_output_tvalid_d1   <= (others => '0');
 
                                                m_axis_output_tvalid_d2   <= (others => '0');
 
                                        end if;
                                        end if;
                                end if;
                                end if;
                        end case;
                        end case;
                end if;
                end if;
        end if;
        end if;
        end process pr_ctrl_ram;
                end process pr_read_ram;
 
        end generate gen_read_ram;
 
 
 
        -- This process decides which traceback unit is the next one to use.
 
        pr_next_traceback: process(clk) is
 
        begin
 
        if rising_edge(clk) then
 
                if rst = '1' then
 
                        next_traceback <= "01";
 
                        last_of_block  <= '0';
 
                else
 
                        if write_window_complete = '1' then
 
                                if next_traceback(0) = '1' then
 
                                        next_traceback(0) <= '0';
 
                                        next_traceback(1) <= '1';
 
                                else
 
                                        next_traceback(0) <= '1';
 
                                        next_traceback(1) <= '0';
 
                                end if;
 
                        end if;
 
 
 
                        if s_axis_input_tlast = '1' then
 
                                last_of_block <= '1';
 
                        end if;
 
 
 
                end if;
 
        end if;
 
        end process pr_next_traceback;
 
 
        ------------------------------
        ------------------------------
        --- Portmapping components ---
        --- Portmapping components ---
        ------------------------------
        ------------------------------
 
 
        gen_generic_sp_ram : for i in 0 to 3 generate
        gen_generic_sp_ram : for i in 0 to 3 generate
        begin
        begin
 
 
 
        addr(i) <= write_addr_ptr   when (write_ram_fsm = RUN or write_ram_fsm = START) and to_integer(write_ram_ptr) = i else
 
                   read_addr_ptr(0) when (to_integer(read_ram_ptr(0)) = i and (read_ram_fsm(0) = TRACEBACK or read_ram_fsm(0) = WAIT_FOR_RAM or read_ram_fsm(0) = FINISH)) or
 
                                         (next_traceback(0) = '1' and write_window_complete = '1' and to_integer(read_ram_ptr(0)) = i) else
 
                   read_addr_ptr(1);
 
 
                inst_generic_sp_ram : generic_sp_ram
                inst_generic_sp_ram : generic_sp_ram
        generic map(
        generic map(
                DISTR_RAM => DISTRIBUTED_RAM,
                DISTR_RAM => DISTRIBUTED_RAM,
                WORDS     => MAX_WINDOW_LENGTH,
                WORDS     => MAX_WINDOW_LENGTH,
                BITWIDTH  => NUMBER_TRELLIS_STATES
                BITWIDTH  => NUMBER_TRELLIS_STATES
        )
        )
        port map(
        port map(
                clk => clk,
                clk => clk,
                rst => rst,
                rst => rst,
                wen => wen_ram(i),
                wen => wen_ram(i),
                en  => en_ram(i),
                en  => '1',
                a   => std_logic_vector(addr(i)),
                a   => std_logic_vector(addr(i)),
                d   => d,
                d   => s_axis_input_tdata,
                q   => q_reg(i)
                q   => q_reg(i)
        );
        );
        end generate gen_generic_sp_ram;
        end generate gen_generic_sp_ram;
 
 
end architecture rtl;
end architecture rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.