Skip to content
Snippets Groups Projects
riscv_rf.vhd 4.98 KiB
Newer Older
Yann Roberge's avatar
Yann Roberge committed
-------------------------------------------------------------------------------
-- Project  ELE8304 : Circuits intégrés à très grande échelle
-------------------------------------------------------------------------------
-- File     riscv_rf.vhd
-- Authors  Titouan Luard <luardtitouan@gmail.com> 
--          Yann Roberge <yann.roberge@polymtl.ca> 
-- Lab      ELE8304-9
-- Date     2021-11-19
-------------------------------------------------------------------------------
-- Brief    RISC-V Register file
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Yann Roberge's avatar
Yann Roberge committed

library work;
use work.riscv_pkg.all;

entity riscv_rf is
  port (
      i_clk     : in  std_logic;
      i_rstn    : in  std_logic;
      i_we      : in  std_logic;
      
      i_addr_ra : in  std_logic_vector(REG_WIDTH-1 downto 0);
      o_data_ra : out std_logic_vector(XLEN-1 downto 0);
      
      i_addr_rb : in  std_logic_vector(REG_WIDTH-1 downto 0);
      o_data_rb : out std_logic_vector(XLEN-1 downto 0);
      
      i_addr_w  : in  std_logic_vector(REG_WIDTH-1 downto 0);
      i_data_w  : in  std_logic_vector(XLEN-1 downto 0));
Yann Roberge's avatar
Yann Roberge committed
end entity riscv_rf;


architecture beh of riscv_rf is
  -- Type des signaux du banc de registres
  type reg_file_t is array (0 to 2**(REG_WIDTH)-1) of std_logic_vector(XLEN-1 downto 0);
  signal reg_file : reg_file_t;
Yann Roberge's avatar
Yann Roberge committed

  -- Registres tampons
  signal write_buffer  : std_logic_vector(XLEN-1 downto 0);
  signal read_buffer_a : std_logic_vector(XLEN-1 downto 0);
  signal read_buffer_b : std_logic_vector(XLEN-1 downto 0);

  -- Signaux internes
  signal reg_file_wr_en: std_logic;
  signal read_value_a : std_logic_vector(XLEN-1 downto 0);  
  signal read_value_b : std_logic_vector(XLEN-1 downto 0);  

  -- Sauvegarde des adresses
  signal addr_ra : std_logic_vector(REG_WIDTH-1 downto 0);
  signal addr_rb : std_logic_vector(REG_WIDTH-1 downto 0);
  signal addr_w  : std_logic_vector(REG_WIDTH-1 downto 0);
  signal wrote_register : std_logic;
  constant ALL_ZEROES : std_logic_vector(REG_WIDTH-1 downto 0) := (others => '0');
Yann Roberge's avatar
Yann Roberge committed
begin
  -- Générer le signal write enable si l'adresse est pas 0 
  reg_file_wr_en <= '1' when ((i_we = '1') and (i_addr_w /= ALL_ZEROES)) else '0';

  -- Écrire le registre pointé
  write_reg_file:
  process (i_clk) is
--    if reg_file_wr_en = '1' then
--      if rising_edge(i_clk) then
--        if i_rstn = '1' then
--          reg_file(to_integer(unsigned(i_addr_w))) <= i_data_w;
--        else
--          reg_file <= (others => (others => '0'));
--        end if;
--      end if;
--    else
--      reg_file <= reg_file;
--    end if;

    if rising_edge(i_clk) then
      if i_rstn = '1' then
        if reg_file_wr_en = '1' then
          reg_file(to_integer(unsigned(i_addr_w))) <= i_data_w;
        else
          reg_file <= reg_file;
      else
        reg_file <= (others => (others => '0'));
      end if;
    end if;
  end process write_reg_file;

  -- Sélectionner les sorties des registres à lire
  read_value_a <= reg_file(to_integer(unsigned(i_addr_ra)));
  read_value_b <= reg_file(to_integer(unsigned(i_addr_rb)));

  -- Transférer la valeur écrite vers un tampon
  transfer_write_buffers:
  process (i_clk) is
  begin
    if rising_edge(i_clk) then
      if i_rstn = '1' then
        write_buffer <= i_data_w;
      else
        write_buffer <= (others => '0');
      end if;
    end if;
  end process transfer_write_buffers;

  -- Transférer le contenu des registres lus vers les registres tampons
  transfer_read_buffers:
  process (i_clk) is
  begin
    if rising_edge(i_clk) then
      if i_rstn = '1' then
        read_buffer_a <= read_value_a;
        read_buffer_b <= read_value_b;
      else
        read_buffer_a <= (others => '0');
        read_buffer_b <= (others => '0');
      end if;
    end if;
  end process transfer_read_buffers;

  -- Sauvegarder les adresses lues au dernier cycle, et l'information comme quoi
  -- on a écrit ou pas au dernier cycle
  transfer_addr_buffers:
  process (i_clk) is
  begin
    if rising_edge(i_clk) then
      if i_rstn = '1' then
        addr_ra <= i_addr_ra;
        addr_rb <= i_addr_rb;
        addr_w  <= i_addr_w;
        wrote_register <= reg_file_wr_en;
      else
        addr_ra <= (others => '0');
        addr_rb <= (others => '0');
        addr_w  <= (others => '0');
  -- Si on lit et écrit le même registre en même temps, retourner la valeur écrite
  select_data_out:
  process (all) is
  begin
    if wrote_register = '1' then
      o_data_ra <= write_buffer when (addr_w = addr_ra) else read_buffer_a;
      o_data_rb <= write_buffer when (addr_w = addr_rb) else read_buffer_b;
    else
      o_data_ra <= read_buffer_a;
      o_data_rb <= read_buffer_b;
    end if;
  end process select_data_out;
--DEBUG
  --o_data_ra <= read_buffer_a;
  --o_data_rb <= read_buffer_b;
Yann Roberge's avatar
Yann Roberge committed

end architecture beh;