-- 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;