diff --git a/sources/riscv_rf.vhd b/sources/riscv_rf.vhd index 65bed8028c6abd283ece82dbccbe5645c74dd79e..05218aee25fd6d67cba4c4e90ac54a6c59a28898 100644 --- a/sources/riscv_rf.vhd +++ b/sources/riscv_rf.vhd @@ -20,12 +20,94 @@ 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); + + 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, reg_file_wr_en) 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; + 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; + + -- Si on lit et écrit le même registre en même temps, retourner la valeur écrite + -- Sinon retouner la valeur lue + o_data_ra <= write_buffer when (i_addr_w = i_addr_ra) else read_buffer_a; + o_data_rb <= write_buffer when (i_addr_w = i_addr_rb) else read_buffer_b; end architecture beh; diff --git a/sources/riscv_rf_tb.vhd b/sources/riscv_rf_tb.vhd index 5fe1d3f062e14d5c33d0a7f1ffacf7d3d43e952a..da233236a15e5927d6a1e6f5e029ca1b577e3e60 100644 --- a/sources/riscv_rf_tb.vhd +++ b/sources/riscv_rf_tb.vhd @@ -108,7 +108,6 @@ architecture tb of riscv_rf_tb is end procedure test_vector; - constant PERIOD : time := 10 ns; begin @@ -143,19 +142,19 @@ begin -- Tests des cas représentatif report "BEGIN SIMULATION"; rstn <= '0'; - addr_ra <= (others => '0'); - addr_rb <= (others => '0'); + addr_ra <= (others => '-'); + addr_rb <= (others => '-'); - addr_w <= (others => '0'); - data_w <= (others => '0'); - we <= '0'; + addr_w <= (others => '-'); + data_w <= (others => '-'); + we <= '-'; wait for PERIOD; rstn <= '1'; wait for 2*PERIOD; -- Write all registers report "Write all registers including 0x00"; - for i in 1 to 2**(REG_WIDTH-1)-1 loop + for i in 1 to 2**(REG_WIDTH)-1 loop write_reg( rstn => rstn, addr_ra => addr_ra, @@ -198,7 +197,7 @@ begin period => PERIOD ); - for i in 1 to 2**(REG_WIDTH-1)-2 loop + for i in 1 to 2**(REG_WIDTH)-2 loop test_vector( rstn => rstn, addr_ra => addr_ra, @@ -227,7 +226,7 @@ begin -- Read & Write all registers at the same time -- Note: Can't write into 0 report "Read & Write at the same time"; - for i in 1 to 2**(REG_WIDTH-1)-2 loop + for i in 1 to 2**(REG_WIDTH)-2 loop test_vector( rstn => rstn, addr_ra => addr_ra, @@ -262,7 +261,7 @@ begin -- Read all registers report "Verify reset worked"; - for i in 0 to 2**(REG_WIDTH-1)-2 loop + for i in 0 to 2**(REG_WIDTH)-2 loop test_vector( rstn => rstn, addr_ra => addr_ra,