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


-- pragma translate_off

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

use std.textio.all;
library std_developerskit;
use std_developerskit.std_iopak.all;

-- - - - - - - - - - - - - - - - - - - - - - - - - 
--  PLL model of the FPGA PLL IP
-- - - - - - - - - - - - - - - - - - - - - - - - - 
entity pll24M576_50M_50M is
  port ( locked    : out std_logic;        --   locked.export
         outclk_0  : out std_logic;        --   outclk0.clk    -- 50M
         outclk_1  : out std_logic;        --   outclk1.clk    -- 50M
         refclk    : in  std_logic;        --   refclk.clk  ACTUALLY 24.576M
         rst       : in  std_logic         --   reset.reset ACTIVE HIGH
         );
end entity pll24M576_50M_50M;

architecture rtl of pll24M576_50M_50M is

  signal clk_50m_w : std_logic := '0';

begin

  clk_50m_w <= not clk_50m_w after 10 ns;

  outclk_0 <= clk_50m_w;
  outclk_1 <= clk_50m_w;

  p_locked : process (rst)
  begin
    if (rst = '1') then
      locked <= '0';
    elsif (rst'event and rst = '0') then
      locked <= '1' after 444 ns;
    end if;
  end process p_locked;

end rtl;

-- pragma translate_on



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

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

entity iopad is
  port ( pad_io   : inout std_logic;
         xenable  : in    std_logic;
         ina      : in    std_logic;
         outy     : out   std_logic
         );
end entity iopad;


architecture rtl of iopad is
begin
  process (pad_io, ina, xenable)
  begin
    if (To_X01(xenable) = '0') then
      pad_io <= To_X01(ina);
    else
      pad_io <= 'Z';
    end if;
  end process;
  outy       <= To_X01(pad_io);
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 rv_tcm_fpga is
  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         : inout slv_t(7 downto 0)
         );
end entity rv_tcm_fpga;


architecture rtl of rv_tcm_fpga is

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

  component pll24M576_50M_50M
    port ( locked    : out std_logic;         --   locked.export
           outclk_0  : out std_logic;         --   outclk0.clk
           outclk_1  : out std_logic;         --   outclk1.clk
           refclk    : in  std_logic;         --   refclk.clk  ACTUALLY 24.576M
           rst       : in  std_logic );       --   reset.reset ACTIVE HIGH
  end component;


  component iopad
    port ( pad_io   : inout std_logic;
           xenable  : in    std_logic;
           ina      : in    std_logic;
           outy     : out   std_logic );
  end component;


  signal rst_w          : std_logic;
  signal ckpll_50m_w    : std_logic;
  signal pll_locked_w   : std_logic;

  signal xrst_w         : std_logic;

  signal gpio_i_w       : slv_t(7 downto 0);
  signal gpio_oena_o_w  : slv_t(7 downto 0);
  signal gpio_o_w       : slv_t(7 downto 0);
  signal gpio_xoena_w   : slv_t(7 downto 0);

begin


  rst_w   <= not xrst_i;
  xrst_w  <= xrst_i and pll_locked_w;         -- wait for PLL locking


  u_pll : pll24M576_50M_50M
    port map ( locked   => pll_locked_w,      --           locked.export
               outclk_0 => ckpll_50m_w,       -- 50M       outclk0.clk
               outclk_1 => OPEN,              -- 50M       outclk1.clk
               refclk   => clk_i,             -- 24.576M   refclk.clk
               rst      => rst_w );           --           reset.reset ACT HIGH


  u_rv_soc_tcm : rv_soc_tcm
    generic map ( CLK_FREQ    => 50000000,    -- default 50M
                  UART_SPEED  =>  1000000,    -- default 1M
                  NR_GPIOS    => 8)
    port map ( clk_i        => ckpll_50m_w,
               xrst_i       => xrst_w,
               --
               uart_txd_i   => uart_txd_i,
               uart_rxd_o   => uart_rxd_o,
               uart2_txd_i  => uart2_txd_i,
               uart2_rxd_o  => uart2_rxd_o,
               --
               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_w,
               gpio_oena_o  => gpio_oena_o_w,
               gpio_o       => gpio_o_w);


  gpio_xoena_w  <= not gpio_oena_o_w;


  g_iopads : for ii in 0 to 7 generate
    u_iopad : iopad
      port map ( pad_io   => gpio(ii),
                 xenable  => gpio_xoena_w(ii),
                 ina      => gpio_o_w(ii),
                 outy     => gpio_i_w(ii) );
  end generate g_iopads;


end rtl;
