Newer
Older
-------------------------------------------------------------------------------
-- 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;
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));
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;
-- 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);

Yann Roberge
committed
-- 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;

Yann Roberge
committed
constant ALL_ZEROES : std_logic_vector(REG_WIDTH-1 downto 0) := (others => '0');
-- 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:
begin
-- 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
end if;
else
reg_file <= (others => (others => '0'));
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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

Yann Roberge
committed
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;

Yann Roberge
committed
else
addr_ra <= (others => '0');
addr_rb <= (others => '0');
addr_w <= (others => '0');
wrote_register <= '0';

Yann Roberge
committed
end if;
end if;
end process transfer_addr_buffers;
-- Si on lit et écrit le même registre en même temps, retourner la valeur écrite

Yann Roberge
committed
-- Sinon retourner la valeur lue
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;

Yann Roberge
committed
--DEBUG
--o_data_ra <= read_buffer_a;
--o_data_rb <= read_buffer_b;