------------------------------------------------------------------------------- -- 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); -- 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'); 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 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 reg_file <= reg_file; end if; 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'); wrote_register <= '0'; 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 -- 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; --DEBUG --o_data_ra <= read_buffer_a; --o_data_rb <= read_buffer_b; end architecture beh;