-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- 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;


-- - - - - - - - - - - - -
--  round robin one hot arbiter
-- - - - - - - - - - - - -
entity axi4_arb_onehot4 is
  port ( clk_i      : in  std_logic;
         xrst_i     : in  std_logic;
         --  inputs
         hold_i     : in  std_logic;
         request_i  : in  slv_03_00;
         --  outputs
         grant_o    : out slv_03_00
         );
end entity axi4_arb_onehot4;


architecture rtl of axi4_arb_onehot4 is

  -- - - - - - - - - - - - -
  --  ffs: find first set
  -- - - - - - - - - - - - -
  function ffs (request : slv_03_00 ) return slv_t is
    variable ffs_v : slv_03_00;
  begin
    ffs_v(0) := request(0);
    ffs_v(1) := ffs_v(0) or request(1);
    ffs_v(2) := ffs_v(1) or request(2);
    ffs_v(3) := ffs_v(2) or request(3);
    return ffs_v;
  end function;

  -- - - - - - - - - - - - -
  --  registers / wires
  -- - - - - - - - - - - - -
  signal req_ffs_masked_w    :  slv_03_00;
  signal req_ffs_unmasked_w  :  slv_03_00;
  signal req_ffs_w           :  slv_03_00;

  signal mask_next_q         :  slv_03_00;
  signal grant_last_q        :  slv_03_00;
  signal grant_new_w         :  slv_03_00;

  signal grant_o_w           :  slv_03_00;

begin

  req_ffs_masked_w   <= ffs(request_i and mask_next_q);
  req_ffs_unmasked_w <= ffs(request_i);

  req_ffs_w <= req_ffs_masked_w when (not_zero(req_ffs_masked_w))
               else req_ffs_unmasked_w;

  p_grant : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') then
      if (xrst_i = '0') then
        mask_next_q  <= "1111";
        grant_last_q <= "0000";
      else
        if (hold_i = '0') then
          mask_next_q <= (req_ffs_w(2 downto 0) & '0');
        end if;
        grant_last_q <= grant_o_w;
      end if;
    end if;
  end process p_grant;

  grant_new_w <= req_ffs_w xor slv_t((shift_left(unsigned(req_ffs_w), 1)));
  grant_o_w   <= grant_last_q when (hold_i = '1') else grant_new_w;
  grant_o     <= grant_o_w;

end rtl;



-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--                               RISCV core
--                                 V1.1
--
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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


entity axi4_arb is
  generic ( AXIDATA_W  : natural range 32 to 64 := 32 );         -- select 32/64
  port ( clk_i              : in  std_logic;
         xrst_i             : in  std_logic;
         --
         axi_a_awvalid_i   : in  std_logic;                     -- dbg uart
         axi_a_awaddr_i    : in  slv_31_00;
         axi_a_awid_i      : in  slv_03_00;
         axi_a_awlen_i     : in  slv_07_00;
         axi_a_awburst_i   : in  slv_01_00;
         axi_a_wvalid_i    : in  std_logic;
         axi_a_wdata_i     : in  slv_t(AXIDATA_W-1 downto 0);
         axi_a_wstrb_i     : in  slv_t(AXIDATA_W/8-1 downto 0); -- 64b / 32b
         axi_a_wlast_i     : in  std_logic;
         axi_a_bready_i    : in  std_logic;
         axi_a_arvalid_i   : in  std_logic;
         axi_a_araddr_i    : in  slv_31_00;
         axi_a_arid_i      : in  slv_03_00;
         axi_a_arlen_i     : in  slv_07_00;
         axi_a_arburst_i   : in  slv_01_00;
         axi_a_rready_i    : in  std_logic;
         axi_a_awready_o   : out std_logic;
         axi_a_wready_o    : out std_logic;
         axi_a_bvalid_o    : out std_logic;
         axi_a_bresp_o     : out slv_01_00;
         axi_a_bid_o       : out slv_03_00;
         axi_a_arready_o   : out std_logic;
         axi_a_rvalid_o    : out std_logic;
         axi_a_rdata_o     : out slv_t(AXIDATA_W-1 downto 0);
         axi_a_rresp_o     : out slv_01_00;
         axi_a_rid_o       : out slv_03_00;
         axi_a_rlast_o     : out std_logic;
         --
         axi_b_awvalid_i    : in  std_logic;                      -- NC
         axi_b_awaddr_i     : in  slv_31_00;
         axi_b_awid_i       : in  slv_03_00;
         axi_b_awlen_i      : in  slv_07_00;
         axi_b_awburst_i    : in  slv_01_00;
         axi_b_wvalid_i     : in  std_logic;
         axi_b_wdata_i      : in  slv_t(AXIDATA_W-1 downto 0);
         axi_b_wstrb_i      : in  slv_t(AXIDATA_W/8-1 downto 0);  -- 64b / 32b
         axi_b_wlast_i      : in  std_logic;
         axi_b_bready_i     : in  std_logic;
         axi_b_arvalid_i    : in  std_logic;
         axi_b_araddr_i     : in  slv_31_00;
         axi_b_arid_i       : in  slv_03_00;
         axi_b_arlen_i      : in  slv_07_00;
         axi_b_arburst_i    : in  slv_01_00;
         axi_b_rready_i     : in  std_logic;
         axi_b_awready_o    : out std_logic;
         axi_b_wready_o     : out std_logic;
         axi_b_bvalid_o     : out std_logic;
         axi_b_bresp_o      : out slv_01_00;
         axi_b_bid_o        : out slv_03_00;
         axi_b_arready_o    : out std_logic;
         axi_b_rvalid_o     : out std_logic;
         axi_b_rdata_o      : out slv_t(AXIDATA_W-1 downto 0);
         axi_b_rresp_o      : out slv_01_00;
         axi_b_rid_o        : out slv_03_00;
         axi_b_rlast_o      : out std_logic;
         --
         axi_c_awvalid_i    : in  std_logic;                     -- cpu
         axi_c_awaddr_i     : in  slv_31_00;
         axi_c_awid_i       : in  slv_03_00;
         axi_c_awlen_i      : in  slv_07_00;
         axi_c_awburst_i    : in  slv_01_00;
         axi_c_wvalid_i     : in  std_logic;
         axi_c_wdata_i      : in  slv_t(AXIDATA_W-1 downto 0);
         axi_c_wstrb_i      : in  slv_t(AXIDATA_W/8-1 downto 0); -- 64b / 32b
         axi_c_wlast_i      : in  std_logic;
         axi_c_bready_i     : in  std_logic;
         axi_c_arvalid_i    : in  std_logic;
         axi_c_araddr_i     : in  slv_31_00;
         axi_c_arid_i       : in  slv_03_00;
         axi_c_arlen_i      : in  slv_07_00;
         axi_c_arburst_i    : in  slv_01_00;
         axi_c_rready_i     : in  std_logic;
         axi_c_awready_o    : out std_logic;
         axi_c_wready_o     : out std_logic;
         axi_c_bvalid_o     : out std_logic;
         axi_c_bresp_o      : out slv_01_00;
         axi_c_bid_o        : out slv_03_00;
         axi_c_arready_o    : out std_logic;
         axi_c_rvalid_o     : out std_logic;
         axi_c_rdata_o      : out slv_t(AXIDATA_W-1 downto 0);
         axi_c_rresp_o      : out slv_01_00;
         axi_c_rid_o        : out slv_03_00;
         axi_c_rlast_o      : out std_logic;
          --
         outport_awready_i  : in  std_logic;                      -- xmem
         outport_wready_i   : in  std_logic;
         outport_bvalid_i   : in  std_logic;
         outport_bresp_i    : in  slv_01_00;
         outport_bid_i      : in  slv_03_00;
         outport_arready_i  : in  std_logic;
         outport_rvalid_i   : in  std_logic;
         outport_rdata_i    : in  slv_t(AXIDATA_W-1 downto 0);
         outport_rresp_i    : in  slv_01_00;
         outport_rid_i      : in  slv_03_00;
         outport_rlast_i    : in  std_logic;
         outport_awvalid_o  : out std_logic;
         outport_awaddr_o   : out slv_31_00;
         outport_awid_o     : out slv_03_00;
         outport_awlen_o    : out slv_07_00;
         outport_awburst_o  : out slv_01_00;
         outport_wvalid_o   : out std_logic;
         outport_wdata_o    : out slv_t(AXIDATA_W-1 downto 0);
         outport_wstrb_o    : out slv_t(AXIDATA_W/8-1 downto 0);  -- 64b / 32b
         outport_wlast_o    : out std_logic;
         outport_bready_o   : out std_logic;
         outport_arvalid_o  : out std_logic;
         outport_araddr_o   : out slv_31_00;
         outport_arid_o     : out slv_03_00;
         outport_arlen_o    : out slv_07_00;
         outport_arburst_o  : out slv_01_00;
         outport_rready_o   : out std_logic
         );
end entity axi4_arb;


architecture rtl of axi4_arb is

  component axi4_arb_onehot4
    port ( clk_i      : in  std_logic;
           xrst_i     : in  std_logic;
           hold_i     : in  std_logic;
           request_i  : in  slv_03_00;
           grant_o    : out slv_03_00 );
  end component;

  --  read requestor select
  signal read_req_w           : slv_03_00;
  signal read_hold_q          : std_logic;
  signal read_grant_w         : slv_03_00;

  signal outport_arvalid_o_w  : std_logic;

  --  read request mux
  signal outport_arvalid_w    : std_logic;
  signal outport_araddr_w     : slv_31_00;
  signal outport_arid_w       : slv_03_00;
  signal outport_arlen_w      : slv_07_00;
  signal outport_arburst_w    : slv_01_00;

  --  read response routing
  signal rd_resp_target_w     : slv_03_00;

  signal axi_a_rready_w      : slv_03_00;

  --  write requestor select
  signal write_req_w          : slv_03_00;
  signal write_hold_q         : std_logic;
  signal write_dataphase_q    : std_logic;

  signal write_grant_w        : slv_03_00;

  --  write hold
  signal write_hold_w         : std_logic;
  signal write_dataphase_w    : std_logic;

  --  write request mux
  signal outport_awvalid_w    : std_logic;
  signal outport_awaddr_w     : slv_31_00;
  signal outport_awid_w       : slv_03_00;
  signal outport_awlen_w      : slv_07_00;
  signal outport_awburst_w    : slv_01_00;

  signal outport_wvalid_w     : std_logic;
  signal outport_wdata_w      : slv_t(AXIDATA_W-1 downto 0);
  signal outport_wstrb_w      : slv_t(AXIDATA_W/8-1 downto 0);    -- 64b / 32b
  signal outport_wlast_w      : std_logic;

  --  write response routing
  signal wr_resp_target_w     : slv_03_00;
  signal axi_a_bready_w      : slv_03_00;

  signal outport_awvalid_o_w  : std_logic;

  signal outport_wvalid_o_w   : std_logic;

  signal outport_wlast_o_w    : std_logic;

begin

  -- - - - - - - - - - - - -
  --  read requestor select
  -- - - - - - - - - - - - -
  read_req_w(0)  <= axi_a_arvalid_i;
  read_req_w(1)  <= axi_c_arvalid_i;
  read_req_w(2)  <= axi_b_arvalid_i;
  read_req_w(3)  <= '0';

  u_rd_arb : axi4_arb_onehot4
    port map ( clk_i      => clk_i,
               xrst_i     => xrst_i,
               --
               hold_i     => read_hold_q,
               request_i  => read_req_w,
               grant_o    => read_grant_w );


  -- - - - - - - - - - - - -
  --  read hold
  -- - - - - - - - - - - - -
  p_grant : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') then
      if (xrst_i = '0') then
        read_hold_q    <= '0';
      else
        if (outport_arvalid_o_w = '1' and outport_arready_i = '0') then
          read_hold_q  <= '1';
        elsif (outport_arready_i = '1') then
          read_hold_q  <= '0';
        end if;
      end if;
    end if;
  end process p_grant;


  -- - - - - - - - - - - - -
  --  read request mux
  -- - - - - - - - - - - - -
  p_c_omux : process ( read_grant_w,  axi_c_arvalid_i, axi_c_araddr_i,
                       axi_c_arid_i, axi_c_arlen_i, axi_c_arburst_i,
                       axi_b_arvalid_i, axi_b_araddr_i, axi_b_arid_i,
                       axi_b_arlen_i, axi_b_arburst_i,
                       axi_a_arvalid_i, axi_a_araddr_i, axi_a_arid_i,
                       axi_a_arlen_i, axi_a_arburst_i )
  begin
    outport_arvalid_w      <= '0';
    outport_araddr_w       <= X"00000000";
    outport_arid_w         <= X"0";
    outport_arlen_w        <= X"00";
    outport_arburst_w      <= "00";
    --
    case read_grant_w is
      when "0001" =>
        outport_arvalid_w  <= axi_a_arvalid_i;
        outport_araddr_w   <= axi_a_araddr_i;
        outport_arid_w     <= axi_a_arid_i;
        outport_arlen_w    <= axi_a_arlen_i;
        outport_arburst_w  <= axi_a_arburst_i;
       when "0010" =>
        outport_arvalid_w  <= axi_c_arvalid_i;
        outport_araddr_w   <= axi_c_araddr_i;
        outport_arid_w     <= axi_c_arid_i;
        outport_arlen_w    <= axi_c_arlen_i;
        outport_arburst_w  <= axi_c_arburst_i;
      when "0100" =>
        outport_arvalid_w  <= axi_b_arvalid_i;
        outport_araddr_w   <= axi_b_araddr_i;
        outport_arid_w     <= axi_b_arid_i;
        outport_arlen_w    <= axi_b_arlen_i;
        outport_arburst_w  <= axi_b_arburst_i;
      when others =>
        outport_arvalid_w  <= axi_a_arvalid_i;
        outport_araddr_w   <= axi_a_araddr_i;
        outport_arid_w     <= axi_a_arid_i;
        outport_arlen_w    <= axi_a_arlen_i;
        outport_arburst_w  <= axi_a_arburst_i;
    end case;
  end process p_c_omux;


  outport_arvalid_o_w <= outport_arvalid_w;
  outport_arvalid_o   <= outport_arvalid_o_w;

  outport_araddr_o    <= outport_araddr_w;
  outport_arid_o      <= outport_arid_w;
  outport_arlen_o     <= outport_arlen_w;
  outport_arburst_o   <= outport_arburst_w;

  -- - - - - - - - - - - - -
  --  read handshaking demux
  -- - - - - - - - - - - - -
  axi_a_arready_o   <= outport_arready_i when (read_grant_w(0) = '1') else '0';
  axi_c_arready_o   <= outport_arready_i when (read_grant_w(1) = '1') else '0';
  axi_b_arready_o   <= outport_arready_i when (read_grant_w(2) = '1') else '0';


  -- - - - - - - - - - - - -
  --  read response routing
  -- - - - - - - - - - - - -
  p_c_rresp : process (outport_rid_i)
  begin
    --
    rd_resp_target_w  <= X"0";
    --
    case outport_rid_i(3 downto 2) is
      when "00"   =>  rd_resp_target_w(0)  <= '1';
      when "01"   =>  rd_resp_target_w(1)  <= '1';
      when "10"   =>  rd_resp_target_w(2)  <= '1';
      when "11"   =>  rd_resp_target_w(3)  <= '1';
      when others =>  rd_resp_target_w(0)  <= '1';
    end case;
  end process p_c_rresp;

  axi_a_rready_w(0)  <= axi_a_rready_i;
  axi_a_rready_w(1)  <= axi_c_rready_i;
  axi_a_rready_w(2)  <= axi_b_rready_i;
  axi_a_rready_w(3)  <= '0';

  outport_rready_o    <= not_zero(axi_a_rready_w and rd_resp_target_w);

  axi_a_rvalid_o     <= outport_rvalid_i and rd_resp_target_w(0);
  axi_a_rdata_o      <= outport_rdata_i;
  axi_a_rid_o        <= outport_rid_i;
  axi_a_rresp_o      <= outport_rresp_i;
  axi_a_rlast_o      <= outport_rlast_i;
  axi_c_rvalid_o      <= outport_rvalid_i and rd_resp_target_w(1);
  axi_c_rdata_o       <= outport_rdata_i;
  axi_c_rid_o         <= outport_rid_i;
  axi_c_rresp_o       <= outport_rresp_i;
  axi_c_rlast_o       <= outport_rlast_i;
  axi_b_rvalid_o      <= outport_rvalid_i and rd_resp_target_w(2);
  axi_b_rdata_o       <= outport_rdata_i;
  axi_b_rid_o         <= outport_rid_i;
  axi_b_rresp_o       <= outport_rresp_i;
  axi_b_rlast_o       <= outport_rlast_i;


  -- - - - - - - - - - - - -
  --  write requestor select
  -- - - - - - - - - - - - -
  write_req_w(0)      <= axi_a_awvalid_i;
  write_req_w(1)      <= axi_c_awvalid_i;
  write_req_w(2)      <= axi_b_awvalid_i;
  write_req_w(3)      <= '0';


  u_wr_arb : axi4_arb_onehot4
    port map ( clk_i      => clk_i,
               xrst_i     => xrst_i,
               --
               hold_i     => write_hold_q,
               request_i  => write_req_w,
               grant_o    => write_grant_w );


  -- - - - - - - - - - - - -
  --  write hold
  -- - - - - - - - - - - - -
  p_c_whld : process ( write_hold_q, write_dataphase_q, outport_awvalid_o_w,
                       outport_awready_i, outport_wvalid_o_w, outport_wready_i,
                       outport_wlast_o_w )
    variable write_hold_v : std_logic;
  begin
    write_hold_v           := write_hold_q;
    write_dataphase_w      <= write_dataphase_q;

    --  command phase
    if (outport_awvalid_o_w = '1') then
      --  command not accepted yet
      if (outport_awready_i = '0') then
        write_hold_v       := '1';
        write_dataphase_w  <= '0';
        --  address + data, single, all accepted
      elsif (outport_wvalid_o_w = '1' and outport_wready_i = '1' and
             outport_wlast_o_w = '1') then
        write_hold_v       := '0';
        write_dataphase_w  <= '0';
        --  enter data phase, data outstanding
      else
        write_hold_v       := '1';
        write_dataphase_w  <= '1';
      end if;
      --  data phase
    elsif (write_hold_v = '1') then
      --  last data accepted
      if (outport_wvalid_o_w = '1' and outport_wready_i = '1' and
          outport_wlast_o_w = '1') then
        write_hold_v       := '0';
        write_dataphase_w  <= '0';
        --  stay in data phase, data outstanding
      else
        write_hold_v       := '1';
        write_dataphase_w  <= '1';
      end if;
    end if;
    write_hold_w  <= write_hold_v;
  end process p_c_whld;


  p_wr : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') then
      if (xrst_i = '0') then
        write_hold_q      <= '0';
        write_dataphase_q <= '0';
      else
        write_hold_q      <= write_hold_w;
        write_dataphase_q <= write_dataphase_w;
      end if;
    end if;
  end process p_wr;


  -- - - - - - - - - - - - -
  --  write request mux
  -- - - - - - - - - - - - -
  p_c_wreqo : process (write_grant_w, axi_c_awvalid_i, axi_c_awaddr_i,
                       axi_c_awid_i, axi_c_awlen_i, axi_c_awburst_i,
                       axi_c_wvalid_i, axi_c_wdata_i, axi_c_wstrb_i,
                       axi_c_wlast_i,
                       axi_b_awvalid_i,axi_b_awaddr_i, axi_b_awid_i,
                       axi_b_awlen_i, axi_b_awburst_i, axi_b_wvalid_i,
                       axi_b_wdata_i, axi_b_wstrb_i, axi_b_wlast_i,
                       axi_a_awvalid_i, axi_a_awaddr_i, axi_a_awid_i,
                       axi_a_awlen_i, axi_a_awburst_i, axi_a_wvalid_i,
                       axi_a_wdata_i, axi_a_wstrb_i, axi_a_wlast_i)
  begin
    outport_awvalid_w      <= '0';
    outport_awaddr_w       <= X"00000000";
    outport_awid_w         <= X"0";
    outport_awlen_w        <= X"00";
    outport_awburst_w      <= "00";
    outport_wvalid_w       <= '0';
    outport_wdata_w        <= (others => '0');
    outport_wstrb_w        <= (others => '0');
    outport_wlast_w        <= '0';
    case write_grant_w is
      when "0001" =>
        outport_awvalid_w  <= axi_a_awvalid_i;
        outport_awaddr_w   <= axi_a_awaddr_i;
        outport_awid_w     <= axi_a_awid_i;
        outport_awlen_w    <= axi_a_awlen_i;
        outport_awburst_w  <= axi_a_awburst_i;
        outport_wvalid_w   <= axi_a_wvalid_i;
        outport_wdata_w    <= axi_a_wdata_i;
        outport_wstrb_w    <= axi_a_wstrb_i;
        outport_wlast_w    <= axi_a_wlast_i;
       when "0010" =>
        outport_awvalid_w  <= axi_c_awvalid_i;
        outport_awaddr_w   <= axi_c_awaddr_i;
        outport_awid_w     <= axi_c_awid_i;
        outport_awlen_w    <= axi_c_awlen_i;
        outport_awburst_w  <= axi_c_awburst_i;
        outport_wvalid_w   <= axi_c_wvalid_i;
        outport_wdata_w    <= axi_c_wdata_i;
        outport_wstrb_w    <= axi_c_wstrb_i;
        outport_wlast_w    <= axi_c_wlast_i;
      when "0100" =>
        outport_awvalid_w  <= axi_b_awvalid_i;
        outport_awaddr_w   <= axi_b_awaddr_i;
        outport_awid_w     <= axi_b_awid_i;
        outport_awlen_w    <= axi_b_awlen_i;
        outport_awburst_w  <= axi_b_awburst_i;
        outport_wvalid_w   <= axi_b_wvalid_i;
        outport_wdata_w    <= axi_b_wdata_i;
        outport_wstrb_w    <= axi_b_wstrb_i;
        outport_wlast_w    <= axi_b_wlast_i;
      when others =>
        outport_awvalid_w  <= axi_a_awvalid_i;
        outport_awaddr_w   <= axi_a_awaddr_i;
        outport_awid_w     <= axi_a_awid_i;
        outport_awlen_w    <= axi_a_awlen_i;
        outport_awburst_w  <= axi_a_awburst_i;
        outport_wvalid_w   <= axi_a_wvalid_i;
        outport_wdata_w    <= axi_a_wdata_i;
        outport_wstrb_w    <= axi_a_wstrb_i;
        outport_wlast_w    <= axi_a_wlast_i;
    end case;
  end process p_c_wreqo;


  outport_awvalid_o_w  <= (outport_awvalid_w and (not write_dataphase_q));
  outport_awvalid_o    <= outport_awvalid_o_w;
  outport_awaddr_o     <= outport_awaddr_w;
  outport_awid_o       <= outport_awid_w;
  outport_awlen_o      <= outport_awlen_w;
  outport_awburst_o    <= outport_awburst_w;
  outport_wvalid_o_w   <= outport_wvalid_w;
  outport_wvalid_o     <= outport_wvalid_o_w;
  outport_wdata_o      <= outport_wdata_w;
  outport_wstrb_o      <= outport_wstrb_w;
  outport_wlast_o_w    <= outport_wlast_w;
  outport_wlast_o      <= outport_wlast_o_w;


  -- - - - - - - - - - - - - -
  --  write handshaking demux
  -- - - - - - - - - - - - - -
  axi_a_awready_o   <= (outport_awready_i and (not write_dataphase_q))
                       when (write_grant_w(0) = '1') else '0';
  axi_a_wready_o    <= outport_wready_i when (write_grant_w(0) = '1') else '0';
  axi_c_awready_o   <= (outport_awready_i and (not write_dataphase_q))
                       when (write_grant_w(1) = '1') else '0';
  axi_c_wready_o    <= outport_wready_i when (write_grant_w(1) = '1') else '0';
  axi_b_awready_o   <= (outport_awready_i and (not write_dataphase_q))
                       when (write_grant_w(2) = '1')  else '0';
  axi_b_wready_o    <= outport_wready_i when (write_grant_w(2) = '1') else '0';


  -- - - - - - - - - - - - - -
  --  write response routing
  -- - - - - - - - - - - - - -
  p_c_wresp : process (outport_bid_i)
  begin
    --
    wr_resp_target_w  <= X"0";
    --
    case outport_bid_i(3 downto 2) is
      when "00"   =>  wr_resp_target_w(0)  <= '1';
      when "01"   =>  wr_resp_target_w(1)  <= '1';
      when "10"   =>  wr_resp_target_w(2)  <= '1';
      when "11"   =>  wr_resp_target_w(3)  <= '1';
      when others =>  wr_resp_target_w(0)  <= '1';
    end case;
  end process p_c_wresp;


  axi_a_bready_w(0)   <= axi_a_bready_i;
  axi_a_bready_w(1)   <= axi_c_bready_i;
  axi_a_bready_w(2)   <= axi_b_bready_i;
  axi_a_bready_w(3)   <= '0';

  outport_bready_o    <= not_zero(axi_a_bready_w and wr_resp_target_w);

  axi_a_bvalid_o      <= outport_bvalid_i and wr_resp_target_w(0);
  axi_a_bid_o         <= outport_bid_i;
  axi_a_bresp_o       <= outport_bresp_i;
  axi_c_bvalid_o      <= outport_bvalid_i and wr_resp_target_w(1);
  axi_c_bid_o         <= outport_bid_i;
  axi_c_bresp_o       <= outport_bresp_i;
  axi_b_bvalid_o      <= outport_bvalid_i and wr_resp_target_w(2);
  axi_b_bid_o         <= outport_bid_i;
  axi_b_bresp_o       <= outport_bresp_i;

end rtl;
