Newer
Older
-------------------------------------------------------------------------------
-- Project ELE8304 : Circuits intégrés à très grande échelle
-------------------------------------------------------------------------------
-- File riscv_decode_tb.vhd
-- Authors Titouan Luard <luardtitouan@gmail.com>
-- Yann Roberge <yann.roberge@polymtl.ca>
-- Lab ELE8304-9
-- Date 2021-11-28
-------------------------------------------------------------------------------
-- Brief RISC-V Register file
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library work;
use work.riscv_pkg.all;
entity riscv_decode_tb is
end riscv_decode_tb;
architecture tb of riscv_decode_tb is
-- Entrées/Sorties du DUT
signal instruction : std_logic_vector(XLEN-1 downto 0);
signal pc_i : std_logic_vector(XLEN-1 downto 0);
signal wr_addr : std_logic_vector(REG_WIDTH-1 downto 0);
signal wr_data : std_logic_vector(XLEN-1 downto 0);
signal we : std_logic;
signal flush : std_logic;
signal rstn : std_logic;
signal clk : std_logic;
signal rs1_data : std_logic_vector(XLEN-1 downto 0);
signal rs2_data : std_logic_vector(XLEN-1 downto 0);
signal shamt : std_logic_vector(SHAMT_WIDTH-1 downto 0);
signal arith : std_logic;
signal sign : std_logic;
signal jump : std_logic;
signal branch : std_logic;
signal pc_o : std_logic_vector(XLEN-1 downto 0);
signal imm : std_logic_vector(XLEN-1 downto 0);
-- Write to a register, no checking of what's coming out
-- TODO: Adapter
procedure write_reg (
signal wr_addr : out std_logic_vector(REG_WIDTH-1 downto 0);
signal wr_data : out std_logic_vector(XLEN-1 downto 0);
signal we : out std_logic;
constant test_wr_addr : in std_logic_vector(REG_WIDTH-1 downto 0);
constant test_wr_data : in std_logic_vector(XLEN-1 downto 0);
constant period : in time) is
begin
wr_addr <= test_wr_addr;
wr_data <= test_wr_data;
we <= '1';
wait for period;
report "Wrote " & to_string(wr_data) & " to reg " & to_string(wr_addr);
end procedure write_reg;
-- Procédure pour un vecteur de test
-- TODO: Adapter
procedure test_vector (
signal instruction : out std_logic_vector(XLEN-1 downto 0);
signal pc_i : out std_logic_vector(XLEN-1 downto 0);
signal wr_addr : out std_logic_vector(REG_WIDTH-1 downto 0);
signal wr_data : out std_logic_vector(XLEN-1 downto 0);
signal we : out std_logic;
signal flush : out std_logic;
signal rs1_data : in std_logic_vector(XLEN-1 downto 0);
signal rs2_data : in std_logic_vector(XLEN-1 downto 0);
signal shamt : in std_logic_vector(SHAMT_WIDTH-1 downto 0);
signal arith : in std_logic;
signal sign : in std_logic;
signal jump : in std_logic;
signal branch : in std_logic;
signal pc_o : in std_logic_vector(XLEN-1 downto 0);
signal imm : in std_logic_vector(XLEN-1 downto 0);
constant test_instruction : in std_logic_vector(XLEN-1 downto 0);
constant test_pc_i : in std_logic_vector(XLEN-1 downto 0);
constant test_wr_addr : in std_logic_vector(REG_WIDTH-1 downto 0);
constant test_wr_data : in std_logic_vector(XLEN-1 downto 0);
constant test_we : in std_logic;
constant test_flush : in std_logic;
constant expected_rs1_data : in std_logic_vector(XLEN-1 downto 0);
constant expected_rs2_data : in std_logic_vector(XLEN-1 downto 0);
constant expected_shamt : in std_logic_vector(SHAMT_WIDTH-1 downto 0);
constant expected_arith : in std_logic;
constant expected_sign : in std_logic;
constant expected_jump : in std_logic;
constant expected_branch : in std_logic;
constant expected_pc_o : in std_logic_vector(XLEN-1 downto 0);
constant expected_imm : in std_logic_vector(XLEN-1 downto 0);
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
constant period : in time) is
begin
-- Set test signals
instruction <= test_instruction;
pc_i <= test_pc_i;
wr_addr <= test_wr_addr;
wr_data <= test_wr_data;
we <= test_we;
flush <= test_flush;
-- Wait a cycle
wait for period;
-- Assert all outputs are what we expect
assert rs1_data = expected_rs1_data
report "RS1_DATA DIFFERS FROM EXPECTED" severity error;
assert rs2_data = expected_rs2_data
report "RS2_DATA DIFFERS FROM EXPECTED" severity error;
assert shamt = expected_shamt
report "SHAMT DIFFERS FROM EXPECTED" severity error;
assert arith = expected_arith
report "ARITH DIFFERS FROM EXPECTED" severity error;
assert sign = expected_sign
report "SIGN DIFFERS FROM EXPECTED" severity error;
assert jump = expected_jump
report "JUMP DIFFERS FROM EXPECTED" severity error;
assert branch = expected_branch
report "BRANCH DIFFERS FROM EXPECTED" severity error;
assert pc_o = expected_pc_o
report "PC_O DIFFERS FROM EXPECTED" severity error;
assert imm = expected_imm
report "IMM DIFFERS FROM EXPECTED" severity error;
end procedure test_vector;
constant PERIOD : time := 10 ns;
-- Used to set the expected IMM as a function of intruction and its type
signal inst : std_logic_vector(XLEN-1 downto 0);
signal i_imm : std_logic_vector(XLEN-1 downto 0);
signal s_imm : std_logic_vector(XLEN-1 downto 0);
signal b_imm : std_logic_vector(XLEN-1 downto 0);
signal u_imm : std_logic_vector(XLEN-1 downto 0);
signal j_imm : std_logic_vector(XLEN-1 downto 0);
begin
-- Instanciation du DUT
dut: entity work.riscv_decode
port map (
i_instruction => instruction,
i_pc => pc_i,
i_wr_addr => wr_addr,
i_wr_data => wr_data,
i_we => we,
i_flush => flush,
i_rstn => rstn,
i_clk => clk,
o_rs1_data => rs1_data,
o_rs2_data => rs2_data,
o_shamt => shamt,
o_arith => arith,
o_sign => sign,
o_jump => jump,
o_branch => branch,
o_pc => pc_o,
o_imm => imm
);
-- Drive clock
drive_clk : process is
begin
clk <= '0';
wait for PERIOD/2;
clk <= '1';
wait for PERIOD/2;
end process drive_clk;
-- Set expected IMM as a function of the instruction type
set_imm : process (inst) is
begin
i_imm <= (others => '0');
s_imm <= (others => '0');
b_imm <= (others => '0');
u_imm <= (others => '0');
j_imm(31 downto 20) <= (others => inst(31));
j_imm(19 downto 0) <= inst(19 downto 12) & inst(20) & inst(30 downto 25) & inst(24 downto 21) & '0';
end process set_imm;
-- Main TB process
p_main : process is
constant DUMMY_DATA : std_logic_vector(XLEN-1 downto 0) := (3 downto 0 => "1010", others => '1');
constant DUMMY_REG_ADDR : std_logic_vector(REG_WIDTH-1 downto 0) := (others => '1');
constant DUMMY_DEST_REG : std_logic_vector(REG_WIDTH-1 downto 0) := (1 downto 0 => "11", others => '0');
constant EXAMPLE_PC : std_logic_vector(XLEN-1 downto 0) := (3 downto 0 => "1010", others => '1');
-- Tests des cas représentatif
report "BEGIN SIMULATION";
instruction <= (others => '-');
pc_i <= (others => '-');
wr_data <= (others => '-');
we <= '-';
flush <= '0';
rstn <= '0';
wait for PERIOD;
rstn <= '1';
wait for 2*PERIOD;
-- Write all registers
report "Write all registers except 0x00";
for i in 1 to 2**(REG_WIDTH)-1 loop
write_reg(
wr_addr => wr_addr,
wr_data => wr_data,
we => we,
test_wr_addr => std_logic_vector(to_unsigned(i, wr_addr'length)),
test_wr_data => std_logic_vector(to_unsigned(i + 3, wr_data'length)),
period => PERIOD
);
end loop;
-- Read back all registers
report "Read back all registers";
-- ADDI 0 to reg[0] specifically, check result
test_vector(
instruction, pc_i, wr_addr, wr_data, we, flush, rs1_data, rs2_data,
shamt, arith, sign, jump, branch, pc_o, imm,
test_instruction => "000000000000" & std_logic_vector(to_unsigned(0, REG_WIDTH)) & FUNCT3_ADD & DUMMY_REG_ADDR & OPCODE_ALU_I_TYPE,
test_pc_i => EXAMPLE_PC,
test_wr_addr => (others => '-'),
test_wr_data => (others => '-'),
test_we => '0',
test_flush => '0',
expected_rs1_data => (others => '0'),
expected_rs2_data => (others => '-'),
expected_shamt => (others => '-'),
expected_arith => '-',
expected_sign => '-',
expected_jump => '-',
expected_branch => '-',
expected_pc_o => EXAMPLE_PC,
expected_imm => (others => '0'),
for i in 1 to 2**(REG_WIDTH)-2 loop
-- ADDI 0 to reg[i], check result
instruction, pc_i, wr_addr, wr_data, we, flush, rs1_data, rs2_data,
shamt, arith, sign, jump, branch, pc_o, imm,
test_instruction => "000000000000" & std_logic_vector(to_unsigned(i, REG_WIDTH)) & FUNCT3_ADD & DUMMY_REG_ADDR & OPCODE_ALU_I_TYPE,
test_pc_i => EXAMPLE_PC,
test_wr_addr => (others => '-'),
test_wr_data => (others => '-'),
test_we => '0',
test_flush => '0',
expected_rs1_data => std_logic_vector(to_unsigned(i+3, rs1_data'length)),
expected_rs2_data => (others => '-'),
expected_shamt => (others => '-'),
expected_arith => '-',
expected_sign => '-',
expected_jump => '-',
expected_branch => '-',
expected_pc_o => EXAMPLE_PC,
expected_imm => (others => '0'),
);
end loop;
-- LUI: registre 0x03 <- pattern 0101 répété sur 20 bits
test_vector(
instruction, pc_i, wr_addr, wr_data, we, flush, rs1_data, rs2_data,
shamt, arith, sign, jump, branch, pc_o, imm,
test_instruction => "11110000111100001111" & DUMMY_REG_ADDR & OPCODE_LUI,
test_pc_i => EXAMPLE_PC,
test_wr_addr => (others => '-'),
test_wr_data => (others => '-'),
test_we => '0',
test_flush => '0',
expected_rs1_data => (others => '-'),
expected_rs2_data => (others => '-'),
expected_shamt => (others => '-'),
expected_arith => '0',
expected_sign => '0',
expected_jump => '0',
expected_branch => '0',
expected_pc_o => EXAMPLE_PC,
expected_imm => (XLEN-1 downto 12 => "11110000111100001111", others => '0'),
inst <= "11110000111100001111" & DUMMY_DEST_REG & OPCODE_JAL;
test_vector(
instruction, pc_i, wr_addr, wr_data, we, flush, rs1_data, rs2_data,
shamt, arith, sign, jump, branch, pc_o, imm,
test_instruction => "11110000111100001111" & DUMMY_DEST_REG & OPCODE_JAL,
test_pc_i => EXAMPLE_PC,
test_wr_addr => (others => '-'),
test_wr_data => (others => '-'),
test_we => '0',
test_flush => '0',
expected_rs1_data => (others => '-'),
expected_rs2_data => (others => '-'),
expected_shamt => (others => '-'),
expected_arith => '0',
expected_sign => '0',
expected_jump => '1',
expected_branch => '0',
expected_pc_o => EXAMPLE_PC,
test_vector(
instruction, pc_i, wr_addr, wr_data, we, flush, rs1_data, rs2_data,
shamt, arith, sign, jump, branch, pc_o, imm,
test_instruction => "111100001111" & DUMMY_REG_ADDR & FUNCT3_JALR & DUMMY_DEST_REG & OPCODE_JALR,
test_pc_i => EXAMPLE_PC,
test_wr_addr => (others => '-'),
test_wr_data => (others => '-'),
test_we => '0',
test_flush => '0',
expected_rs1_data => (others => '-'),
expected_rs2_data => (others => '-'),
expected_shamt => (others => '-'),
expected_arith => '0',
expected_sign => '0',
expected_jump => '1',
expected_branch => '0',
test_vector(
instruction, pc_i, wr_addr, wr_data, we, flush, rs1_data, rs2_data,
shamt, arith, sign, jump, branch, pc_o, imm,
test_instruction => "111100001111" & DUMMY_REG_ADDR & FUNCT3_JALR & DUMMY_DEST_REG & OPCODE_JALR,
test_pc_i => EXAMPLE_PC,
test_wr_addr => (others => '-'),
test_wr_data => (others => '-'),
test_we => '0',
test_flush => '0',
expected_rs1_data => (others => '-'),
expected_rs2_data => (others => '-'),
expected_shamt => (others => '-'),
expected_arith => '0',
expected_sign => '0',
expected_jump => '1',
expected_branch => '0',
expected_pc_o => EXAMPLE_PC,
expected_imm => (others => '0'),
period => PERIOD
);
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
-- LW
-- SW
-- ADDI
-- SLTI
-- SLTUI
-- XORI
-- ORI
-- ANDI
-- SLLI
-- SRLI
-- SRAI
-- ADD
-- SUB
-- SLL
-- SLT
-- SLTU
-- XOR
-- SRL
-- SRA
-- OR
-- AND
-- Flush pipeline
-- Reset entire stage
report "Reset";
rstn <= '0';
wait for PERIOD;
rstn <= '1';
wait for PERIOD;
report "SIMULATION DONE";
wait;
end process p_main;
end architecture tb;