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(REG_WIDTH-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 addr_w : out std_logic_vector(REG_WIDTH-1 downto 0);
signal data_w : out std_logic_vector(XLEN-1 downto 0);
signal we : out std_logic;
constant test_addr_w : in std_logic_vector(REG_WIDTH-1 downto 0);
constant test_data_w : in std_logic_vector(XLEN-1 downto 0);
constant period : in time) is
begin
addr_w <= test_addr_w;
data_w <= test_data_w;
we <= '1';
wait for period;
report "Wrote " & to_string(data_w) & " to reg " & to_string(addr_w);
end procedure write_reg;
-- Procédure pour un vecteur de test
-- TODO: Adapter
procedure test_vector (
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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(REG_WIDTH-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);
signal test_instruction : in std_logic_vector(XLEN-1 downto 0);
signal test_pc_i : in std_logic_vector(XLEN-1 downto 0);
signal test_wr_addr : in std_logic_vector(REG_WIDTH-1 downto 0);
signal test_wr_data : in std_logic_vector(REG_WIDTH-1 downto 0);
signal test_we : in std_logic;
signal 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;
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;
-- Main TB process
p_main : process is
constant DUMMY_DATA : std_logic_vector(XLEN-1 downto 0) := (3 downto 0 => "1010", others => '1');
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
-- TODO: Adapter mais le laisser faire la même chose
report "Write all registers except 0x00";
for i in 1 to 2**(REG_WIDTH)-1 loop
write_reg(
addr_w => addr_w,
data_w => data_w,
we => we,
test_addr_w => std_logic_vector(to_unsigned(i, addr_w)),
test_data_w => std_logic_vector(to_unsigned(i + 3, data_w)),
period => PERIOD
);
end loop;
-- Read back all registers
-- TODO: Adapter mais le laisser faire la même chose
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 & 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 => (others => '-'),
expected_sign => (others => '-'),
expected_jump => (others => '-'),
expected_branch => (others => '-'),
expected_pc_o => EXAMPLE_PC,
expected_imm => (others => '0'),
PERIOD
);
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 & 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 => (others => '-'),
expected_sign => (others => '-'),
expected_jump => (others => '-'),
expected_branch => (others => '-'),
expected_pc_o => EXAMPLE_PC,
expected_imm => (others => '0'),
PERIOD
);
end loop;
report "Test every instruction in supported ISA";
-- 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" & "00011" & 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 => (others => '-'),
expected_sign => (others => '-'),
expected_jump => (others => '-'),
expected_branch => (others => '-'),
expected_pc_o => EXAMPLE_PC,
expected_imm => (XLEN-1 downto 12 => "11110000111100001111", others => '0'),
PERIOD
);
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
-- JAL
-- JALR
-- BEQ
-- 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;