-- Risc16x16 test bench
-- Reads input file for each instruction
-- Writes results file
-- MP Tull
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;
ENTITY RISC16x16_TB4 IS
END RISC16x16_TB4;
ARCHITECTURE behavior OF RISC16x16_TB4 IS
FILE TESTFILE: TEXT OPEN READ_MODE IS "test1.txt"; -- input test file
FILE RESULTS: TEXT OPEN WRITE_MODE IS "results2.txt"; -- output file declaration
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT RISC16CPU
PORT(
CLK : IN std_logic;
XLD : IN std_logic;
TEN : IN std_logic;
MEMIO : IN std_logic;
C : IN std_logic_vector(4 downto 0);
S : IN std_logic_vector(3 downto 0);
T : IN std_logic_vector(3 downto 0);
D : IN std_logic_vector(3 downto 0);
MEMBUS : IN std_logic_vector(15 downto 0);
IOBUS : IN std_logic_vector(15 downto 0);
ALUOUT : INOUT std_logic_vector(15 downto 0);
OV : OUT std_logic;
SGN : OUT std_logic;
Z : OUT std_logic;
COUT : INOUT std_logic
);
END COMPONENT;
--Inputs
signal CLK : std_logic := '0';
signal XLD : std_logic := '0';
signal TEN : std_logic := '0';
signal MEMIO : std_logic := '0';
signal C : std_logic_vector(4 downto 0) := (others => '0');
signal S : std_logic_vector(3 downto 0) := (others => '0');
signal T : std_logic_vector(3 downto 0) := (others => '0');
signal D : std_logic_vector(3 downto 0) := (others => '0');
signal MEMBUS : std_logic_vector(15 downto 0) := (others => '0');
signal IOBUS : std_logic_vector(15 downto 0) := (others => '0');
--BiDirs
signal ALUOUT : std_logic_vector(15 downto 0);
signal COUT : std_logic;
--Outputs
signal OV : std_logic;
signal SGN : std_logic;
signal Z : std_logic;
-- Clock period definitions
constant CLK_period : time := 100 ns;
type Instr_Type is array (0 to 31) of string (1 to 5);
constant Instr: Instr_Type := ("PASS ", "ADD ", "SUB ", "INCR ", "ADDC ",
"SUBB ", "NEGR ", "DECR ", "COMR ", "ANDR ", "ORR ", "XORR ", "XNORR",
"LSLR ", "LSRR ", "ASRR ", "NOP ", "NOP ", "NOP ", "NOP ", "NOP ",
"ROLR ", "RORR ", "SWBR ", "NOP ", "NOP ", "NOP ", "NOP ", "NOP ",
"NOP ", "NOP ", "NOP ");
type Reg_Type is array (0 to 15) of integer;
signal Reg_TB: Reg_Type;
procedure WriteResults (OpCode: in string; Sreg, Treg, Dreg: in integer;
SRegVal, TRegVal,DRegVal: in integer; Flags_Var: in bit_vector) is
variable TX_OUT : LINE;
begin
write(TX_OUT, OpCode);
write(TX_OUT, string'(" "));
write(TX_OUT, Sreg, right, 2);
write(TX_OUT, string'(" "));
write(TX_OUT, Treg, right, 2);
write(TX_OUT, string'(" "));
write(TX_OUT, Dreg, right, 2);
write(TX_OUT, string'(" "));
write(TX_OUT, SRegVal, right, 5);
write(TX_OUT, string'(" "));
write(TX_OUT, TRegVal, right, 5);
write(TX_OUT, string'(" "));
write(TX_OUT, DRegVal, right, 5);
write(TX_OUT, string'(" "));
write(TX_OUT, Flags_Var);
writeline(results, TX_OUT);
end WriteResults;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: RISC16CPU PORT MAP (
CLK => CLK,
XLD => XLD,
TEN => TEN,
MEMIO => MEMIO,
C => C,
S => S,
T => T,
D => D,
MEMBUS => MEMBUS,
IOBUS => IOBUS,
ALUOUT => ALUOUT,
OV => OV,
SGN => SGN,
Z => Z,
COUT => COUT
);
-- Clock process definitions
CLK_process :process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
-- Stimulus process
stim_proc: process
variable NibbleVal: std_logic_vector(3 downto 0);
variable RegVal: std_logic_vector(15 downto 0);
variable L_In: LINE;
variable TX_OUT : LINE;
variable LoadVal: natural; -- used to accumulate reg load values
-- Internal test bench tracking registers (same as circuit)
type Reg_Type is array (0 to 15) of integer;
variable Reg_TB: Reg_Type;
variable SRegVal: integer;
variable TRegVal: integer;
variable DRegVal: integer;
variable Flags: std_logic_vector(3 downto 0);
variable Flags_Var: bit_vector(3 downto 0);
variable Instr_Var: string(1 to 5);
variable good_number: integer;
variable OpCode: string(1 to 5);
variable Sreg: integer;
variable Treg: integer;
variable Dreg: integer;
variable Opcodefound: boolean;
begin
WAIT FOR 30 ns;
---- load registers 0-7 from MEMBUS
XLD <= '1'; -- enable external loading
MEMIO <= '1'; -- assert MEMBUS loading
for i in 0 to 7 loop -- loop thru loading regs 0-7 from MEMBUS
NibbleVal := conv_std_logic_vector(i, 4);
RegVal := NibbleVal & NibbleVal & NibbleVal & NibbleVal;
-- assign values
MEMBUS <= RegVal;
S <= NibbleVal;
D <= NibbleVal;
Reg_TB(i) := conv_integer(RegVal); -- save test bench reg values
Wait For 100 ns;
end loop;
---- Load registers 8-15 from IOBUS
MEMIO <= '0'; -- assert IOBUS loading
for i in 8 to 15 loop -- loop thru loading regs 8-15 from IOBUS
NibbleVal := conv_std_logic_vector(i, 4);
RegVal := NibbleVal & NibbleVal & NibbleVal & NibbleVal;
-- assign values
IOBUS <= RegVal;
S <= NibbleVal;
D <= NibbleVal;
Reg_TB(i) := conv_integer(RegVal); -- save test bench reg values
Wait For 100 ns;
end loop;
------
-- Write initial register values
write(TX_OUT, string'("Initial Reg Values 0-7: "));
Reg_Loop1: for i in 0 to 7 loop
write(TX_OUT, Reg_TB(i), right, 5);
write(TX_OUT, string'(" "));
end loop;
writeline(results, TX_OUT);
write(TX_OUT, string'("Initial Reg Values 8-15: "));
Reg_Loop2: for i in 8 to 15 loop
write(TX_OUT, Reg_TB(i), right, 5);
write(TX_OUT, string'(" "));
end loop;
writeline(results, TX_OUT);
write(TX_OUT, string'(" ")); -- write blank line
writeline(results, TX_OUT);
-- write column headings
write(TX_OUT, string'("Instr S T D S-Reg_Val T-Reg_Val D-Reg_Val SZVC"));
writeline(results, TX_OUT);
Mainloop: while not endfile(TESTFILE) loop -- main loop to read vectors and write results
readline(TESTFILE, L_In); -- read test file record
read(L_In, OpCode);
read(L_In, Sreg); -- read souce register S bits
-- if not good-number then
-- assert (FALSE) REPORT "Bad source register number in test file"
-- severity failure;
-- end if;
read(L_In, Treg); -- read source register T bits
-- if not good-number then
-- assert (FALSE) REPORT "Bad source register number in test file"
-- severity failure;
-- end if;
read(L_In, Dreg); -- read desination register
-- if not good-number then
-- assert (FALSE) REPORT "Bad destination register number in test file"
-- severity failure;
-- end if;
S <= conv_std_logic_vector(Sreg, 4); -- assign S bits
T <= conv_std_logic_vector(Treg, 4); -- assign T bits
D <= conv_std_logic_vector(Dreg, 4); -- assign D bits
SRegVal := Reg_TB(Sreg); -- copy Sreg register value
TRegVal := Reg_TB(Treg); -- copy Treg register value
Opcodefound := false; -- set opcode found false
for i in 0 to 31 loop -- look up OpCode string to get C bit value
if OpCode = Instr(i) then
C <= conv_std_logic_vector(i, 5);
Opcodefound := true;
-- exit;
end if;
end loop Opcodesearch;
if not Opcodefound then
assert (FALSE) REPORT "Bad opcode string in test file"
severity failure;
end if;
wait for 15 ns; -- catch Regs and ALUOUT 5 ns before rising clock edge
Reg_TB(Dreg) := conv_integer(ALUOUT); -- update the destination reg
DRegVal := Reg_TB(Dreg); -- copy the Dreg value
wait for 15 ns; -- catch flag bits 10 ns after rising edge clk
Flags := SGN & Z & OV & COUT;
Flags_Var := to_bitvector(Flags);
WriteResults (OpCode, Sreg, Treg, Dreg, SRegVal, TRegVal, DRegVal, Flags_Var); -- call write results procedure
wait for 70 ns;
end loop Mainloop;
file_close(TESTFILE);
file_close(RESULTS);
ASSERT (FALSE) REPORT
"Simulation successful - not a failure."
SEVERITY FAILURE;
end process;
END;