-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- 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_soc_tcm is
  generic ( CLK_FREQ    : natural := 50000000;            -- default 50M
            UART_SPEED  : natural :=  1000000;            -- default 1M
            NR_GPIOS    : integer range 1 to 32 := 8 );
  port ( clk_i        : in  std_logic;
         xrst_i       : in  std_logic;
         --
         uart_txd_i   : in  std_logic;
         uart_rxd_o   : out std_logic;
         uart2_txd_i  : in  std_logic;
         uart2_rxd_o  : out std_logic;
         --
         spi_miso_i   : in  std_logic;
         spi_clk_o    : out std_logic;
         spi_cs_o     : out std_logic;
         spi_mosi_o   : out std_logic;
         --
         gpio_i       : in  slv_t(NR_GPIOS-1 downto 0);
         gpio_oena_o  : out slv_t(NR_GPIOS-1 downto 0);
         gpio_o       : out slv_t(NR_GPIOS-1 downto 0)
         );
end entity rv_soc_tcm;


architecture rtl of rv_soc_tcm is

  component rv_tcm
    port ( clk_i          : in  std_logic;
           xrst_i         : in  std_logic;                  -- syncr reset
           xrst_cpu_i     : in  std_logic;                  -- riscv core only
           --  AXI slave
           axi_arready_o  : out std_logic;
           axi_rvalid_o   : out std_logic;
           axi_rdata_o    : out slv_31_00;
           axi_rresp_o    : out slv_01_00;
           axi_rid_o      : out slv_03_00;
           axi_rlast_o    : out std_logic;
           axi_arvalid_i  : in  std_logic;
           axi_araddr_i   : in  slv_31_00;
           axi_arid_i     : in  slv_03_00;
           axi_arlen_i    : in  slv_07_00;
           axi_arburst_i  : in  slv_01_00;
           axi_rready_i   : in  std_logic;
           --
           axi_awready_o  : out std_logic;
           axi_wready_o   : out std_logic;
           axi_bvalid_o   : out std_logic;
           axi_bresp_o    : out slv_01_00;
           axi_bid_o      : out slv_03_00;
           axi_awvalid_i  : in  std_logic;
           axi_awaddr_i   : in  slv_31_00;
           axi_awid_i     : in  slv_03_00;
           axi_awlen_i    : in  slv_07_00;
           axi_awburst_i  : in  slv_01_00;
           axi_wvalid_i   : in  std_logic;
           axi_wdata_i    : in  slv_31_00;
           axi_wstrb_i    : in  slv_03_00;
           axi_wlast_i    : in  std_logic;
           axi_bready_i   : in  std_logic;
           --  vsbus for peripherals
           pp_irq_i       : in  std_logic;                  -- perip interrupt
           pp_addr_o      : out slv_31_00;
           pp_rd_o        : out std_logic;
           pp_rd_data_i   : in  slv_31_00;
           pp_wr_o        : out slv_03_00;
           pp_wr_data_o   : out slv_31_00 );
  end component;


  component vsperips
    generic ( CLK_FREQ    : natural := 50000000;            -- default 50M
              UART_SPEED  : natural :=  1000000;            -- default 1M
              NR_GPIOS    : integer range 1 to 32 := 8 );
    port ( clk_i          : in  std_logic;
           xrst_i         : in  std_logic;                  -- syncr reset
           --  vsbus for peripherals
           pp_addr_i      : in  slv_31_00;
           pp_rd_i        : in  std_logic;
           pp_wr_i        : in  slv_03_00;
           pp_wr_data_i   : in  slv_31_00;
           pp_rd_data_o   : out slv_31_00;
           pp_irq_o       : out std_logic;                  -- pp interrupt
           --
           pll_cfg_i      : in slv_08_00;
           --  peripheral ios to pads
           rx_i           : in  std_logic;
           tx_o           : out std_logic;
           rx2_i          : in  std_logic;
           tx2_o          : out std_logic;
           --
           spi_miso_i     : in  std_logic;
           spi_clk_o      : out std_logic;
           spi_cs_o       : out std_logic;
           spi_mosi_o     : out std_logic;
           --
           gpio_i         : in  slv_t(NR_GPIOS-1 downto 0);
           gpio_pdena_o   : out slv_t(NR_GPIOS-1 downto 0);
           gpio_puena_o   : out slv_t(NR_GPIOS-1 downto 0);
           gpio_oena_o    : out slv_t(NR_GPIOS-1 downto 0);
           gpio_o         : out slv_t(NR_GPIOS-1 downto 0);
           --  DMA bus
           dma_rd_o       : out std_logic;
           dma_wr_o       : out slv_03_00;
           dma_addr_o     : out slv_31_02;
           dma_wr_data_o  : out slv_31_00;
           dma_rd_data_i  : in  slv_31_00;
           dma_intr_i     : in  std_logic );                -- dma interrupt
  end component;


  component dbg_bridge
    generic ( CLK_FREQ    : natural := 50000000;            -- default 50M
              UART_SPEED  : natural :=  1000000;            -- default 1M
              AXIDATA_W   : natural range 32 to 64 := 32 ); -- select 32 / 64
    port ( clk_i          : in  std_logic;
           xrst_i         : in  std_logic;
           --
           vs_rst_cpu_i   : in  std_logic;      --  cpu/cache enable, '1' if NC
           --
           mbist_ena_o    : out std_logic;
           imbist_rd_o    : out slv_03_00;
           imbist_wr_o    : out slv_03_00;
           dmbist_rd_o    : out slv_03_00;
           dmbist_wr_o    : out slv_03_00;
           mbist_addr_o   : out slv_12_00;
           mbist_data_o   : out slv_t(AXIDATA_W-1 downto 0);
           mbist_data_i   : in  slv_t(AXIDATA_W-1 downto 0);
           --  AXI bus to DDR / TCM ram if
           mem_awready_i  : in  std_logic;
           mem_wready_i   : in  std_logic;
           mem_bvalid_i   : in  std_logic;
           mem_arready_i  : in  std_logic;
           mem_rvalid_i   : in  std_logic;
           mem_rdata_i    : in  slv_31_00;
           mem_awvalid_o  : out std_logic;
           mem_awaddr_o   : out slv_31_00;
           mem_wvalid_o   : out std_logic;
           mem_wdata_o    : out slv_31_00;
           mem_wstrb_o    : out slv_03_00;
           mem_bready_o   : out std_logic;
           mem_arvalid_o  : out std_logic;
           mem_araddr_o   : out slv_31_00;
           mem_rready_o   : out std_logic;
           --  pp io
           uart_rxd_i     : in  std_logic;
           uart_txd_o     : out std_logic;
           rv_cpu_xrst_o  : out std_logic;      -- cpu xreset  (cpu only, halt)
           rv_core_ena_o  : out std_logic );    -- core enable (cpu/caches)
  end component;


  signal axi_arready_w  :  std_logic;
  signal axi_rvalid_w   :  std_logic;
  signal axi_rdata_w    :  slv_31_00;
  signal axi_rresp_w    :  slv_01_00;
  signal axi_rid_w      :  slv_03_00;
  signal axi_rlast_w    :  std_logic;
  signal axi_arvalid_w  :  std_logic;
  signal axi_araddr_w   :  slv_31_00;
  signal axi_arid_w     :  slv_03_00;
  signal axi_arlen_w    :  slv_07_00;
  signal axi_arburst_w  :  slv_01_00;
  signal axi_rready_w   :  std_logic;

  signal axi_awready_w  :  std_logic;
  signal axi_wready_w   :  std_logic;
  signal axi_bvalid_w   :  std_logic;
  signal axi_bresp_w    :  slv_01_00;
  signal axi_bid_w      :  slv_03_00;
  signal axi_awvalid_w  :  std_logic;
  signal axi_awaddr_w   :  slv_31_00;
  signal axi_awid_w     :  slv_03_00;
  signal axi_awlen_w    :  slv_07_00;
  signal axi_awburst_w  :  slv_01_00;
  signal axi_wvalid_w   :  std_logic;
  signal axi_wdata_w    :  slv_31_00;
  signal axi_wstrb_w    :  slv_03_00;
  signal axi_wlast_w    :  std_logic;
  signal axi_bready_w   :  std_logic;

  signal pp_irq_w       : std_logic;                      -- perip interrupt
  signal pp_addr_w      : slv_31_00;
  signal pp_rd_w        : std_logic;
  signal pp_rd_data_w   : slv_31_00;
  signal pp_wr_w        : slv_03_00;
  signal pp_wr_data_w   : slv_31_00;

  signal xrst_cpu_w     : std_logic;
  signal rv_core_ena_w  : std_logic;
  signal rv_cpu_xrst_w  : std_logic;

  signal uart_txd_w     : std_logic;
  signal dbg_txd_w      : std_logic;
  signal txd_q          : std_logic;

begin


  u_rv_tcm : rv_tcm
    port map ( clk_i          => clk_i,
               xrst_i         => xrst_i,
               xrst_cpu_i     => xrst_cpu_w,              -- NOTE: cpu reset
               --  AXI slave
               axi_arready_o  => axi_arready_w,
               axi_rvalid_o   => axi_rvalid_w,
               axi_rdata_o    => axi_rdata_w,
               axi_rresp_o    => axi_rresp_w,
               axi_rid_o      => axi_rid_w,
               axi_rlast_o    => axi_rlast_w,
               axi_arvalid_i  => axi_arvalid_w,
               axi_araddr_i   => axi_araddr_w,
               axi_arid_i     => axi_arid_w,
               axi_arlen_i    => axi_arlen_w,
               axi_arburst_i  => axi_arburst_w,
               axi_rready_i   => axi_rready_w,
               --
               axi_awready_o  => axi_awready_w,
               axi_wready_o   => axi_wready_w,
               axi_bvalid_o   => axi_bvalid_w,
               axi_bresp_o    => axi_bresp_w,
               axi_bid_o      => axi_bid_w,
               axi_awvalid_i  => axi_awvalid_w,
               axi_awaddr_i   => axi_awaddr_w,
               axi_awid_i     => axi_awid_w,
               axi_awlen_i    => axi_awlen_w,
               axi_awburst_i  => axi_awburst_w,
               axi_wvalid_i   => axi_wvalid_w,
               axi_wdata_i    => axi_wdata_w,
               axi_wstrb_i    => axi_wstrb_w,
               axi_wlast_i    => axi_wlast_w,
               axi_bready_i   => axi_bready_w,
               --  vsbus for peripherals
               pp_irq_i       => pp_irq_w,                -- perip interrupt
               pp_addr_o      => pp_addr_w,
               pp_rd_o        => pp_rd_w,
               pp_rd_data_i   => pp_rd_data_w,
               pp_wr_o        => pp_wr_w,
               pp_wr_data_o   => pp_wr_data_w );


  u_vsperips : vsperips
    generic map ( CLK_FREQ    => CLK_FREQ,                 -- default 50M
                  UART_SPEED  => UART_SPEED,               -- default 1M
                  NR_GPIOS    => NR_GPIOS )
    port map ( clk_i          => clk_i,
               xrst_i         => xrst_i,                   -- syncr reset
               --  vsbus for peripherals
               pp_addr_i      => pp_addr_w,
               pp_rd_i        => pp_rd_w,
               pp_wr_i        => pp_wr_w,
               pp_wr_data_i   => pp_wr_data_w,
               pp_rd_data_o   => pp_rd_data_w,
               pp_irq_o       => pp_irq_w,                 -- pp intr
               --
               pll_cfg_i      => (others => '0'),
               --  perip IO
               rx_i           => uart_txd_i,               -- in
               tx_o           => uart_txd_w,               -- out
               rx2_i          => uart2_txd_i,              -- in
               tx2_o          => uart2_rxd_o,              -- out
               --
               spi_miso_i     => spi_miso_i,
               spi_clk_o      => spi_clk_o,
               spi_cs_o       => spi_cs_o,
               spi_mosi_o     => spi_mosi_o,
               --
               gpio_i         => gpio_i,
               gpio_pdena_o   => OPEN,
               gpio_puena_o   => OPEN,
               gpio_oena_o    => gpio_oena_o,
               gpio_o         => gpio_o,
               --  DMA bus
               dma_rd_o       => OPEN,
               dma_wr_o       => OPEN,                     -- 03_00
               dma_addr_o     => OPEN,                     -- 31_02
               dma_wr_data_o  => OPEN,                     -- 31_00
               dma_rd_data_i  => (others => '0'),          -- 31_00
               dma_intr_i     => '0' );                    -- dma interrupt


  u_dbg_bridge : dbg_bridge
    generic map ( CLK_FREQ    => CLK_FREQ,                 -- default 50M
                  UART_SPEED  => UART_SPEED,               -- default 1M
                  AXIDATA_W   => 32 )                      -- select 32 / 64
    port map ( clk_i          => clk_i,
               xrst_i         => xrst_i,
               --
               vs_rst_cpu_i   => '1',             -- riscv core only, '1' if NC
               --
               mbist_ena_o    => OPEN,
               imbist_rd_o    => OPEN,
               imbist_wr_o    => OPEN,
               dmbist_rd_o    => OPEN,
               dmbist_wr_o    => OPEN,
               mbist_addr_o   => OPEN,
               mbist_data_o   => OPEN,
               mbist_data_i   => (others => '0'),
               --  AXI bus to DDR / TCM ram if
               mem_awready_i  => axi_awready_w,
               mem_wready_i   => axi_wready_w,
               mem_bvalid_i   => axi_bvalid_w,
               --
               mem_awvalid_o  => axi_awvalid_w,
               mem_awaddr_o   => axi_awaddr_w,
               mem_wvalid_o   => axi_wvalid_w,
               mem_wdata_o    => axi_wdata_w,
               mem_wstrb_o    => axi_wstrb_w,
               mem_bready_o   => axi_bready_w,
               --
               mem_arready_i  => axi_arready_w,
               mem_rvalid_i   => axi_rvalid_w,
               mem_rdata_i    => axi_rdata_w,
               --
               mem_arvalid_o  => axi_arvalid_w,
               mem_araddr_o   => axi_araddr_w,
               mem_rready_o   => axi_rready_w,
               --  pp io
               uart_rxd_i     => uart_txd_i,
               uart_txd_o     => dbg_txd_w,
               rv_cpu_xrst_o  => rv_cpu_xrst_w,    -- cpu xreset  (cpu only)
               rv_core_ena_o  => rv_core_ena_w );  -- core enable (cpu/caches)



  --  unused AXI signals
  --
  --  inputs to rv_tcm
  axi_arid_w     <= X"0";
  axi_arlen_w    <= X"00";
  axi_arburst_w  <= "01";
  axi_awid_w     <= X"0";
  axi_awlen_w    <= X"00";
  axi_awburst_w  <= "01";
  axi_wlast_w    <= '1';
  --
  -- outputs from rv_tcm
  -- axi_bresp_w   OPEN
  -- axi_bid_w     OPEN
  -- axi_rresp_w   OPEN
  -- axi_rid_w     OPEN
  -- axi_rlast_w   OPEN


  xrst_cpu_w   <= rv_cpu_xrst_w and rv_core_ena_w and xrst_i;


  p_txd : process (clk_i)
  begin
    if (clk_i'event and clk_i = '1') then
      if (xrst_i = '0') then
        txd_q <= '1';
      else
        txd_q <= dbg_txd_w and uart_txd_w;
      end if;
    end if;
  end process p_txd;

  uart_rxd_o     <= txd_q;

end rtl;
