Browse Source

Update VHDL code to ne equivalent to final tlv version

master
T. Meissner 4 years ago
parent
commit
49574bbbf0
3 changed files with 178 additions and 24 deletions
  1. +62
    -16
      vhdl/risc_v.vhd
  2. +80
    -1
      vhdl/risc_v_pkg.vhd
  3. +36
    -7
      vhdl/tb_risc_v.vhd

+ 62
- 16
vhdl/risc_v.vhd View File

@ -2,13 +2,18 @@ library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
use std.env.all;
use work.risc_v_pkg.all; use work.risc_v_pkg.all;
entity risc_v is entity risc_v is
port ( port (
reset_n_i : in std_logic;
clk_i : in std_logic
reset_n_i : in std_logic;
clk_i : in std_logic;
-- test out
reg_file_o : out t_reg_file;
dmem_o : out t_dmem
); );
end entity; end entity;
@ -18,7 +23,7 @@ architecture rtl of risc_v is
signal s_reg_file : t_reg_file; signal s_reg_file : t_reg_file;
signal s_dmem : t_dmem;
signal s_dmem : t_dmem;
signal s_instr : std_logic_vector(31 downto 0); signal s_instr : std_logic_vector(31 downto 0);
signal s_imm : std_logic_vector(31 downto 0); signal s_imm : std_logic_vector(31 downto 0);
@ -26,14 +31,15 @@ architecture rtl of risc_v is
signal s_src1_value : std_logic_vector(31 downto 0); signal s_src1_value : std_logic_vector(31 downto 0);
signal s_src2_value : std_logic_vector(31 downto 0); signal s_src2_value : std_logic_vector(31 downto 0);
signal s_ld_data : std_logic_vector(31 downto 0); signal s_ld_data : std_logic_vector(31 downto 0);
signal s_result : std_logic_vector(31 downto 0);
signal s_sltu_rslt : std_logic_vector(31 downto 0);
signal s_sltiu_rslt : std_logic_vector(31 downto 0);
signal s_pc : unsigned(31 downto 0); signal s_pc : unsigned(31 downto 0);
signal s_next_pc : unsigned(31 downto 0); signal s_next_pc : unsigned(31 downto 0);
signal s_br_tgt_br : unsigned(31 downto 0); signal s_br_tgt_br : unsigned(31 downto 0);
signal s_jalr_tgt_pc : unsigned(31 downto 0); signal s_jalr_tgt_pc : unsigned(31 downto 0);
signal s_result : signed(31 downto 0);
signal s_taken_br : boolean; signal s_taken_br : boolean;
signal s_is_r_instr : boolean; signal s_is_r_instr : boolean;
signal s_is_i_instr : boolean; signal s_is_i_instr : boolean;
@ -78,6 +84,8 @@ architecture rtl of risc_v is
signal s_is_and : boolean; signal s_is_and : boolean;
signal s_is_load : boolean; signal s_is_load : boolean;
signal s_is_store : boolean; signal s_is_store : boolean;
signal s_src_sgn_eq : boolean;
signal s_imm_sgn_eq : boolean;
alias a_opcode : std_logic_vector(6 downto 0) is s_instr(6 downto 0); alias a_opcode : std_logic_vector(6 downto 0) is s_instr(6 downto 0);
alias a_rd : std_logic_vector(4 downto 0) is s_instr(11 downto 7); alias a_rd : std_logic_vector(4 downto 0) is s_instr(11 downto 7);
@ -88,6 +96,11 @@ architecture rtl of risc_v is
begin begin
-- Test outs
reg_file_o <= s_reg_file;
dmem_o <= s_dmem;
-- prog counter next state logic -- prog counter next state logic
s_next_pc <= 32x"0" when not reset_n_i else s_next_pc <= 32x"0" when not reset_n_i else
s_br_tgt_br when s_taken_br or s_is_jal else s_br_tgt_br when s_taken_br or s_is_jal else
@ -184,10 +197,44 @@ begin
-- SB, SH, SW -- SB, SH, SW
s_is_store <= s_is_s_instr; s_is_store <= s_is_s_instr;
-- Some subexpressions
s_src_sgn_eq <= s_src1_value(31) = s_src2_value(31);
s_imm_sgn_eq <= s_src1_value(31) = s_imm(31);
-- SLTU & SLTI (set if less than, unsigned)
s_sltu_rslt <= 31x"0" & to_std_logic(unsigned(s_src1_value) < unsigned(s_src2_value));
s_sltiu_rslt <= 31x"0" & to_std_logic(unsigned(s_src1_value) < unsigned(s_imm));
-- ALU -- ALU
s_result <= signed(s_src1_value) + signed(s_imm) when s_is_addi or s_is_load or s_is_store else
signed(s_src1_value) + signed(s_src2_value) when s_is_add else
32x"0";
s_result <=
s_src1_value and s_imm when s_is_andi else
s_src1_value or s_imm when s_is_ori else
s_src1_value xor s_imm when s_is_xori else
std_logic_vector(signed(s_src1_value) + signed(s_imm)) when s_is_addi or
s_is_load or
s_is_store else
shift_left(s_src1_value, s_imm(5 downto 0)) when s_is_slli else
shift_right(s_src1_value, s_imm(5 downto 0)) when s_is_srli else
s_src1_value and s_src2_value when s_is_and else
s_src1_value or s_src2_value when s_is_or else
s_src1_value xor s_src2_value when s_is_xor else
std_logic_vector(signed(s_src1_value) + signed(s_src2_value)) when s_is_add else
std_logic_vector(signed(s_src1_value) - signed(s_src2_value)) when s_is_sub else
shift_left(s_src1_value, s_src2_value(4 downto 0)) when s_is_sll else
shift_right(s_src1_value, s_src2_value(4 downto 0)) when s_is_srl else
s_sltu_rslt when s_is_sltu else
s_sltiu_rslt when s_is_sltiu else
s_imm(31 downto 12) & 12x"0" when s_is_lui else
std_logic_vector(s_pc + unsigned(s_imm)) when s_is_auipc else
std_logic_vector(s_pc + 4) when s_is_jal or
s_is_jalr else
s_sltu_rslt when s_is_slt and
s_src_sgn_eq else
31x"0" & s_src1_value(31) when s_is_slt else
s_sltiu_rslt when s_is_slti and
s_imm_sgn_eq else
31x"0" & s_src1_value(31) when s_is_slti else
shift_arith_right(s_src1_value, s_src2_value(4 downto 0)) when s_is_sra else
shift_arith_right(s_src1_value, s_imm(4 downto 0)) when s_is_srai else
32x"0";
-- Branch logic -- Branch logic
s_taken_br <= s_src1_value = s_src2_value when s_is_beq else s_taken_br <= s_src1_value = s_src2_value when s_is_beq else
@ -202,16 +249,14 @@ begin
-- Register file -- Register file
process (clk_i) is process (clk_i) is
variable v_value : std_logic_vector(31 downto 0);
begin begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if reset_n_i = '0' then if reset_n_i = '0' then
s_reg_file <= (others => 32x"0");
s_reg_file <= init_reg_file;
elsif s_rd_valid and a_rd /= 5x"0" then elsif s_rd_valid and a_rd /= 5x"0" then
if s_is_load then
s_reg_file(to_integer(unsigned(a_rd))) <= std_logic_vector(s_ld_data);
else
s_reg_file(to_integer(unsigned(a_rd))) <= std_logic_vector(s_result);
end if;
v_value := std_logic_vector(s_ld_data) when s_is_load else s_result;
s_reg_file(to_integer(unsigned(a_rd))) <= v_value;
end if; end if;
end if; end if;
end process; end process;
@ -226,14 +271,15 @@ begin
begin begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if reset_n_i = '0' then if reset_n_i = '0' then
s_dmem <= (others => 32x"0");
s_dmem <= init_dmem;
elsif s_is_store then elsif s_is_store then
s_dmem(to_integer(unsigned(s_result(6 downto 2)))) <= std_logic_vector(s_src2_value); s_dmem(to_integer(unsigned(s_result(6 downto 2)))) <= std_logic_vector(s_src2_value);
end if;
end if;
end if; end if;
end process; end process;
s_ld_data <= s_dmem(to_integer(unsigned(s_result(6 downto 2)))) when s_is_load else s_ld_data <= s_dmem(to_integer(unsigned(s_result(6 downto 2)))) when s_is_load else
(others => '0'); (others => '0');
end architecture rtl; end architecture rtl;

+ 80
- 1
vhdl/risc_v_pkg.vhd View File

@ -1,5 +1,8 @@
library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
package risc_v_pkg is package risc_v_pkg is
@ -10,7 +13,6 @@ package risc_v_pkg is
subtype t_imem is t_slv_array(natural range 0 to 57)(31 downto 0); subtype t_imem is t_slv_array(natural range 0 to 57)(31 downto 0);
subtype t_dmem is t_reg_file; subtype t_dmem is t_reg_file;
-- Test program -- Test program
constant c_imem : t_imem := ( constant c_imem : t_imem := (
-- (I) ADDI x1, x0, 10101 -- (I) ADDI x1, x0, 10101
@ -130,5 +132,82 @@ package risc_v_pkg is
-- (J) JAL x0, 0 -- (J) JAL x0, 0
b"00000000000000000000000001101111"); b"00000000000000000000000001101111");
function init_reg_file return t_reg_file;
function init_dmem return t_dmem;
function shift_right (data : in std_logic_vector(31 downto 0);
index : in std_logic_vector) return std_logic_vector;
function shift_left (data : in std_logic_vector(31 downto 0);
index : in std_logic_vector) return std_logic_vector;
function shift_arith_right (data : in std_logic_vector(31 downto 0);
index : in std_logic_vector) return std_logic_vector;
function to_std_logic (data : in boolean) return std_logic;
procedure check_equal (a, b : in std_logic_vector; prefix : in string := "");
end package risc_v_pkg; end package risc_v_pkg;
package body risc_v_pkg is
function init_reg_file return t_reg_file is
variable v_reg_file : t_reg_file;
begin
for i in t_reg_file'range loop
v_reg_file(i) := std_logic_vector(to_unsigned(i, 32));
end loop;
return v_reg_file;
end init_reg_file;
function init_dmem return t_dmem is
variable v_dmem : t_dmem;
begin
for i in t_dmem'range loop
v_dmem(t_dmem'high-i) := std_logic_vector(to_unsigned(i, 32));
end loop;
return v_dmem;
end init_dmem;
function shift_right (data : in std_logic_vector(31 downto 0);
index : in std_logic_vector) return std_logic_vector is
begin
return std_logic_vector(shift_right(unsigned(data),
to_integer(unsigned(index))));
end function shift_right;
function shift_left (data : in std_logic_vector(31 downto 0);
index : in std_logic_vector) return std_logic_vector is
begin
return std_logic_vector(shift_left(unsigned(data),
to_integer(unsigned(index))));
end function shift_left;
function shift_arith_right (data : in std_logic_vector(31 downto 0);
index : in std_logic_vector) return std_logic_vector is
begin
return std_logic_vector(shift_right(signed(data),
to_integer(unsigned(index))));
end function shift_arith_right;
function to_std_logic (data : in boolean) return std_logic is
begin
if data then
return '1';
else
return '0';
end if;
end function to_std_logic;
procedure check_equal (a, b : in std_logic_vector; prefix : in string := "") is
begin
assert a = b
report prefix & "expected 0x" & to_hstring(b) & ", got 0x" & to_hstring(a);
end procedure check_equal;
end package body risc_v_pkg;

+ 36
- 7
vhdl/tb_risc_v.vhd View File

@ -4,6 +4,8 @@ library ieee;
use std.env.all; use std.env.all;
use work.risc_v_pkg.all;
entity tb_risc_v is entity tb_risc_v is
end entity tb_risc_v; end entity tb_risc_v;
@ -12,8 +14,10 @@ end entity tb_risc_v;
architecture sim of tb_risc_v is architecture sim of tb_risc_v is
signal s_clk : std_logic := '1';
signal s_reset_n : std_logic := '0';
signal s_clk : std_logic := '1';
signal s_reset_n : std_logic := '0';
signal s_reg_file : t_reg_file;
signal s_dmem : t_dmem;
begin begin
@ -22,17 +26,42 @@ begin
s_clk <= not s_clk after 5 ns; s_clk <= not s_clk after 5 ns;
s_reset_n <= '1' after 20 ns; s_reset_n <= '1' after 20 ns;
DUT : entity work.risc_v DUT : entity work.risc_v
port map ( port map (
reset_n_i => s_reset_n,
clk_i => s_clk
reset_n_i => s_reset_n,
clk_i => s_clk,
reg_file_o => s_reg_file,
dmem_o => s_dmem
); );
-- Checker
process is process is
variable v_expected : std_logic_vector(31 downto 0);
begin begin
wait for 380 ns;
wait until s_reset_n = '1';
-- until program is finished
wait for c_imem'length * 10 ns;
-- Check register file entries
for i in t_reg_file'range loop
case i is
when 0 => v_expected := 32x"0";
when 1 => v_expected := 32x"15";
when 2 => v_expected := 32x"7";
when 3 => v_expected := x"FFFFFFFC";
when 4 => v_expected := 32x"B4";
when 31 => v_expected := 32x"1F";
when others => v_expected := 32x"1";
end case;
check_equal(s_reg_file(i), v_expected, "Reg. x" & to_string(i) & ": ");
end loop;
-- Check data memory entries
for i in t_dmem'range loop
case i is
when 2 => v_expected := 32x"15";
when others => v_expected := std_logic_vector(to_unsigned(t_dmem'high-i, 32));
end case;
check_equal(s_dmem(i), v_expected, "Dmem @" & to_string(i) & ": ");
end loop;
stop(0); stop(0);
end process; end process;


Loading…
Cancel
Save