-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- 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 rv_if is
  port ( clk_i       : in  std_logic;
         xrst_i      : in  std_logic;
         --  vsbus
         pp_rd_i     : in  std_logic;
         pp_wr_i     : in  slv_03_00;   -- ! 3:1 NC
         pp_addr_i   : in  slv_07_00;
         pp_data_i   : in  slv_31_00;
         pp_data_o   : out slv_31_00;
         --
         pll_cfg_i   : in  slv_08_00;   -- pll_ctrl[6:0], xtal_div2, xtal_div256
         uart_cfg_o  : out slv_03_00
         );
end entity rv_if;


architecture rtl of rv_if is

  constant ST_PLL    : slv_07_00 := X"00";
  constant CFG_UART  : slv_07_00 := X"04";

  signal pll_cfg_meta_q  : slv_08_00;
  signal pll_cfg_q       : slv_08_00;
  signal data_w          : slv_31_00;
  signal uart_cfg_q      : slv_03_00;

begin

  p_meta : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') Then
      if (xrst_i = '0') then
        pll_cfg_meta_q  <= (others => '0');
        pll_cfg_q       <= (others => '0');
      else
        pll_cfg_meta_q  <= pll_cfg_i;
        pll_cfg_q       <= pll_cfg_meta_q;
      end if;
    end if;
  end process p_meta;


  -- - - - - - - - - - - - -
  --  read mux
  -- - - - - - - - - - - - -
  p_c_omux : process (pp_rd_i, pp_addr_i, pll_cfg_q, uart_cfg_q)
  begin
    --
    data_w                          <= X"00000000";
    --
    if (pp_rd_i = '1') then
      case pp_addr_i(7 downto 0) is
        when ST_PLL =>
          data_w(pll_cfg_q'range)   <= pll_cfg_q;
        when CFG_UART =>
          data_w(uart_cfg_q'range)  <= uart_cfg_q;
        when others =>
          data_w <= X"00000000";
      end case;
    end if;
  end process p_c_omux;

  pp_data_o   <= data_w;


  -- - - - - - - - - - - - -
  -- write
  -- - - - - - - - - - - - -
  p_wr : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') then
      if (xrst_i = '0') then
        uart_cfg_q  <= (others => '0');
      else
        --
        if ( not_zero(pp_wr_i) ) then
          case pp_addr_i(7 downto 0) is
            when ST_PLL =>               -- 0x00
              null;                      -- read only register
            when CFG_UART =>             -- 0x04
              uart_cfg_q  <= pp_data_i(uart_cfg_q'range);
            when others =>
              null;
          end case;
        end if;
      end if;
    end if;
  end process p_wr;

  uart_cfg_o <= uart_cfg_q;

end rtl;
