-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- Copyright 2025 VLSI Solution Oy
-- SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
--
-- Licensed under the Solderpad Hardware License v 2.1 (the "License");
-- you may not use this file except in compliance with the License, or,
-- at your option, the Apache License version 2.0.
-- You may obtain a copy of the License at
--
--    https://solderpad.org/licenses/SHL-2.1/
--
-- Unless required by applicable law or agreed to in writing, any work
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--                               RISCV core
--                                 V1.1
--
--
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-- - - - - - - -
--  libraries
-- - - - - - - -
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.rv_pkg.all;


entity dbg_bridge_fifo is
  generic ( WIDTH   : natural := 8;
            DEPTH   : natural := 4;
            ADDR_W  : natural := 2 );
  port ( clk_i       : in  std_logic;
         xrst_i      : in  std_logic;
         --  inputs
         data_in_i   : in  slv_t(WIDTH-1 downto 0);
         push_i      : in  std_logic;
         pop_i       : in  std_logic;
         --  outputs
         data_out_o  : out slv_t(WIDTH-1 downto 0);
         accept_o    : out std_logic;
         valid_o     : out std_logic
         );
end entity dbg_bridge_fifo;


architecture rtl of dbg_bridge_fifo is

  -- - - - - - - - - - - - -
  --  local params
  -- - - - - - - - - - - - -
  constant COUNT_W : natural := ADDR_W + 1;

  -- - - - - - - - - - - - -
  --  registers / wires
  -- - - - - - - - - - - - -
  type rfile_t is array (DEPTH-1 downto 0) of slv_t(WIDTH-1 downto 0);
  signal rfile_q     : rfile_t;
  signal rd_ptr_q    : slv_t(ADDR_W-1 downto 0);
  signal wr_ptr_q    : slv_t(ADDR_W-1 downto 0);
  signal count_q     : slv_t(COUNT_W-1 downto 0);

  signal accept_o_w  : std_logic;           
  signal valid_o_w   : std_logic;

begin

  p_fifo : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') then
      if (xrst_i = '0') then
        count_q   <= (COUNT_W-1 downto 0 => '0');
        rd_ptr_q  <= (ADDR_W-1  downto 0 => '0');
        wr_ptr_q  <= (ADDR_W-1  downto 0 => '0');
        rfile_q   <= (others =>  (others => '0'));
      else
        --  push
        if (push_i = '1' and accept_o_w = '1') then
          rfile_q(to_uint(wr_ptr_q)) <= data_in_i;
          wr_ptr_q                   <= inc1u(wr_ptr_q);
        end if;
        --  pop
        if (pop_i = '1' and valid_o_w = '1') then
          rd_ptr_q  <= inc1u(rd_ptr_q);
        end if;
        --  count up
        if ( (push_i = '1' and accept_o_w = '1') and
             (pop_i  = '0' or valid_o_w = '0')) then
          count_q   <= inc1u(count_q);
          --  count down
        elsif ( (push_i  = '0' or accept_o_w = '0') and
                (pop_i  = '1' and valid_o_w = '1') ) then
          count_q   <= dec1u(count_q);
        end if;
      end if;
    end if;
  end process p_fifo;


  valid_o_w  <= not_zero(count_q);
  valid_o    <= valid_o_w;
  
  accept_o_w <= ne(count_q, DEPTH);
  accept_o   <= accept_o_w;

  data_out_o <= rfile_q(to_uint(rd_ptr_q));

end rtl;
