-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- 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_regfile is
  generic ( RISCV_E : std_logic := '0' );   -- RV rf embedded extension
  port ( clk_i      : in  std_logic;
         xrst_i     : in  std_logic;        -- syncr reset
         --  write port
         rd_addr_i  : in  slv_04_00;
         rd_data_i  : in  slv_31_00;
         -- read port a
         ra_addr_i  : in  slv_04_00;
         ra_data_o  : out slv_31_00;
         -- read port b
         rb_addr_i  : in  slv_04_00;
         rb_data_o  : out slv_31_00
         );
end entity rv_regfile;


architecture rtl of rv_regfile is

  -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  -- flop based register file
  -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  -- Register   ABI Name    Description                       Saver
  -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  -- x0         zero        Hard-wired zero                   -
  -- x1         ra          Return address                    Caller
  -- x2         sp          Stack pointer                     Callee
  -- x3         gp          Global pointer                    -
  -- x4         tp          Thread pointer                    -
  -- x5-7       t0-2        Temporaries                       Caller
  -- x8         s0/fp       Saved register/Frame pointer      Callee
  -- x9         s1          Saved register                    Callee
  -- x10-11     a0-1        Function Arguments/return values  Caller
  -- x12-17     a2-7        Function arguments                Caller
  -- x18-27     s2-11       Saved registers                   Callee
  -- x28-31     t3-6        Temporaries                       Caller
  -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  -- pragma translate_off
  -- simulation friendly names
  type rv_regs_t is
  record
    x31_t6_w   : slv_31_00;
    x30_t5_w   : slv_31_00;
    x29_t4_w   : slv_31_00;
    x28_t3_w   : slv_31_00;
    x27_s11_w  : slv_31_00;
    x26_s10_w  : slv_31_00;
    x25_s9_w   : slv_31_00;
    x24_s8_w   : slv_31_00;
    x23_s7_w   : slv_31_00;
    x22_s6_w   : slv_31_00;
    x21_s5_w   : slv_31_00;
    x20_s4_w   : slv_31_00;
    x19_s3_w   : slv_31_00;
    x18_s2_w   : slv_31_00;
    x17_a7_w   : slv_31_00;
    x16_a6_w   : slv_31_00;
    x15_a5_w   : slv_31_00;
    x14_a4_w   : slv_31_00;
    x13_a3_w   : slv_31_00;
    x12_a2_w   : slv_31_00;
    x11_a1_w   : slv_31_00;
    x10_a0_w   : slv_31_00;
    x9_s1_w    : slv_31_00;
    x8_s0_w    : slv_31_00;
    x7_t2_w    : slv_31_00;
    x6_t1_w    : slv_31_00;
    x5_t0_w    : slv_31_00;
    x4_tp_w    : slv_31_00;
    x3_gp_w    : slv_31_00;
    x2_sp_w    : slv_31_00;
    x1_ra_w    : slv_31_00;
    x0_zero_w  : slv_31_00;
  end record;
  --
  signal rv_regs : rv_regs_t ;
  --
  -- pragma translate_on

  -- one hot write enebles
  signal wr_ohot_w  : slv_31_00;
  signal rfile_q    : rfile_t;

begin

  -- pragma translate_off
  -- simulation friendly names
  rv_regs.x31_t6_w  <= rfile_q(31);
  rv_regs.x30_t5_w  <= rfile_q(30);
  rv_regs.x29_t4_w  <= rfile_q(29);
  rv_regs.x28_t3_w  <= rfile_q(28);   -- t3-6   Temporaries
  rv_regs.x27_s11_w <= rfile_q(27);
  rv_regs.x26_s10_w <= rfile_q(26);
  rv_regs.x25_s9_w  <= rfile_q(25);
  rv_regs.x24_s8_w  <= rfile_q(24);
  rv_regs.x23_s7_w  <= rfile_q(23);
  rv_regs.x22_s6_w  <= rfile_q(22);
  rv_regs.x21_s5_w  <= rfile_q(21);
  rv_regs.x20_s4_w  <= rfile_q(20);
  rv_regs.x19_s3_w  <= rfile_q(19);
  rv_regs.x18_s2_w  <= rfile_q(18);   -- s2-11  Saved registers
  rv_regs.x17_a7_w  <= rfile_q(17);
  rv_regs.x16_a6_w  <= rfile_q(16);
  rv_regs.x15_a5_w  <= rfile_q(15);
  rv_regs.x14_a4_w  <= rfile_q(14);
  rv_regs.x13_a3_w  <= rfile_q(13);
  rv_regs.x12_a2_w  <= rfile_q(12);   -- a2-7   Function arguments
  rv_regs.x11_a1_w  <= rfile_q(11);
  rv_regs.x10_a0_w  <= rfile_q(10);   -- a0-1   Function Arguments/return values
  rv_regs.x9_s1_w   <= rfile_q(9);    -- s1     Saved register
  rv_regs.x8_s0_w   <= rfile_q(8);    -- s0/fp  Saved register/Frame pointer
  rv_regs.x7_t2_w   <= rfile_q(7);
  rv_regs.x6_t1_w   <= rfile_q(6);
  rv_regs.x5_t0_w   <= rfile_q(5);    -- t0-2   Temporaries
  rv_regs.x4_tp_w   <= rfile_q(4);    -- tp     Thread pointer
  rv_regs.x3_gp_w   <= rfile_q(3);    -- gp     Global pointer
  rv_regs.x2_sp_w   <= rfile_q(2);    -- sp     Stack pointer
  rv_regs.x1_ra_w   <= rfile_q(1);    -- ra     Return address
  rv_regs.x0_zero_w <= X"00000000";   -- zero   Hard-wired zero   (32'b0)
  -- pragma translate_on



  -- - - - - - - - - - - - - - - - - -
  --  flop based register file
  -- - - - - - - - - - - - - - - - - -

  -- probably infer clock gating
  p_one_hot_rf32(rd_addr_i, RISCV_E, wr_ohot_w);

  p_dff32x32(clk_i, xrst_i, wr_ohot_w, rd_data_i, rfile_q);

  p_rf32x2mux(ra_addr_i, rb_addr_i, rfile_q, ra_data_o, rb_data_o);

end rtl;
