1 |
20 |
earlz |
LIBRARY ieee;
|
2 |
|
|
USE ieee.std_logic_1164.ALL;
|
3 |
|
|
USE ieee.numeric_std.ALL;
|
4 |
|
|
use work.tinycpu.all;
|
5 |
|
|
|
6 |
|
|
ENTITY core_tb IS
|
7 |
|
|
END core_tb;
|
8 |
|
|
|
9 |
|
|
ARCHITECTURE behavior OF core_tb IS
|
10 |
|
|
|
11 |
|
|
-- Component Declaration for the Unit Under Test (UUT)
|
12 |
|
|
|
13 |
|
|
component core is
|
14 |
|
|
port(
|
15 |
|
|
--memory interface
|
16 |
|
|
MemAddr: out std_logic_vector(15 downto 0); --memory address (in bytes)
|
17 |
|
|
MemWW: out std_logic; --memory writeword
|
18 |
|
|
MemWE: out std_logic; --memory writeenable
|
19 |
|
|
MemIn: in std_logic_vector(15 downto 0);
|
20 |
|
|
MemOut: out std_logic_vector(15 downto 0);
|
21 |
|
|
--general interface
|
22 |
|
|
Clock: in std_logic;
|
23 |
|
|
Reset: in std_logic; --When this is high, CPU will reset within 1 clock cycles.
|
24 |
|
|
--Enable: in std_logic; --When this is high, the CPU executes as normal, when low the CPU stops at the next clock cycle(maintaining all state)
|
25 |
|
|
Hold: in std_logic; --when high, CPU pauses execution and places Memory interfaces into high impendance state so the memory can be used by other components
|
26 |
|
|
HoldAck: out std_logic; --when high, CPU acknowledged hold and buses are in high Z
|
27 |
|
|
--todo: port interface
|
28 |
|
|
|
29 |
|
|
--debug ports:
|
30 |
|
|
DebugIR: out std_logic_vector(15 downto 0); --current instruction
|
31 |
|
|
DebugIP: out std_logic_vector(7 downto 0); --current IP
|
32 |
|
|
DebugCS: out std_logic_vector(7 downto 0); --current code segment
|
33 |
|
|
DebugTR: out std_logic; --current value of TR
|
34 |
|
|
DebugR0: out std_logic_vector(7 downto 0)
|
35 |
|
|
);
|
36 |
|
|
end component;
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
--memory interface
|
40 |
|
|
signal MemAddr: std_logic_vector(15 downto 0); --memory address (in bytes)
|
41 |
|
|
signal MemWW: std_logic; --memory writeword
|
42 |
|
|
signal MemWE: std_logic; --memory writeenable
|
43 |
|
|
signal MemOut: std_logic_vector(15 downto 0);
|
44 |
21 |
earlz |
signal MemIn: std_logic_vector(15 downto 0):=x"0000";
|
45 |
20 |
earlz |
--general interface
|
46 |
21 |
earlz |
signal Reset: std_logic:='0'; --When this is high, CPU will reset within 1 clock cycles.
|
47 |
20 |
earlz |
--Enable: in std_logic; --When this is high, the CPU executes as normal, when low the CPU stops at the next clock cycle(maintaining all state)
|
48 |
21 |
earlz |
signal Hold: std_logic:='0'; --when high, CPU pauses execution and places Memory interfaces into high impendance state so the memory can be used by other components
|
49 |
20 |
earlz |
signal HoldAck: std_logic; --when high, CPU acknowledged hold and buses are in high Z
|
50 |
|
|
--todo: port interface
|
51 |
|
|
|
52 |
|
|
--debug ports:
|
53 |
|
|
signal DebugIR: std_logic_vector(15 downto 0); --current instruction
|
54 |
|
|
signal DebugIP: std_logic_vector(7 downto 0); --current IP
|
55 |
|
|
signal DebugCS: std_logic_vector(7 downto 0); --current code segment
|
56 |
|
|
signal DebugTR: std_logic; --current value of TR
|
57 |
|
|
signal DebugR0: std_logic_vector(7 downto 0);
|
58 |
|
|
|
59 |
|
|
signal Clock: std_logic;
|
60 |
|
|
constant clock_period : time := 10 ns;
|
61 |
|
|
|
62 |
|
|
BEGIN
|
63 |
|
|
|
64 |
|
|
-- Instantiate the Unit Under Test (UUT)
|
65 |
|
|
uut: core PORT MAP (
|
66 |
|
|
MemAddr => MemAddr,
|
67 |
|
|
MemWW => MemWW,
|
68 |
|
|
MemWE => MemWE,
|
69 |
|
|
MemOut => MemOut,
|
70 |
|
|
MemIn => MemIn,
|
71 |
|
|
--general interface
|
72 |
|
|
Clock => Clock,
|
73 |
|
|
Reset => Reset,
|
74 |
|
|
--Enable: in std_logic; --When this is high, the CPU executes as normal, when low the CPU stops at the next clock cycle(maintaining all state)
|
75 |
|
|
Hold => Hold,
|
76 |
|
|
HoldAck => HoldAck,
|
77 |
|
|
DebugIR => DebugIR,
|
78 |
|
|
DebugIP => DebugIP,
|
79 |
|
|
DebugCS => DebugCS,
|
80 |
|
|
DebugTR => DebugTR,
|
81 |
|
|
DebugR0 => DebugR0
|
82 |
|
|
);
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
-- Clock process definitions
|
86 |
|
|
clock_process :process
|
87 |
|
|
begin
|
88 |
|
|
Clock <= '0';
|
89 |
|
|
wait for clock_period/2;
|
90 |
|
|
Clock <= '1';
|
91 |
|
|
wait for clock_period/2;
|
92 |
|
|
end process;
|
93 |
|
|
|
94 |
|
|
|
95 |
|
|
-- Stimulus process
|
96 |
|
|
stim_proc: process
|
97 |
|
|
variable err_cnt: integer :=0;
|
98 |
|
|
begin
|
99 |
|
|
Reset <= '1';
|
100 |
|
|
wait for 20 ns;
|
101 |
|
|
|
102 |
|
|
--state tests:
|
103 |
|
|
Hold <= '1';
|
104 |
|
|
wait for 10 ns;
|
105 |
|
|
assert(HoldAck = '1') report "hold state is not acknowledged" severity error;
|
106 |
|
|
--assert(MemAddr = "ZZZZZZZZZZZZZZZZ" and MemWW="Z" and MemWE="Z" and MemOut = "ZZZZZZZZZZZZZZZZZZZZ")
|
107 |
|
|
-- report "hold state does not set high-Z" severity error;
|
108 |
|
|
Hold <= '0';
|
109 |
|
|
wait for 10 ns;
|
110 |
|
|
assert(HoldAck = '0') report "hold state lasts longer than it should" severity error;
|
111 |
|
|
|
112 |
|
|
Reset <= '0';
|
113 |
|
|
MemIn <= x"0012"; --mov r0, 0xFF
|
114 |
21 |
earlz |
wait for 30 ns; --fetcher needs two clock cycles to catch up
|
115 |
20 |
earlz |
assert(MemAddr = x"0100") report "Not fetching from correct start address" severity error;
|
116 |
|
|
MemIn <= x"00F1"; --mov r0, 0xF1
|
117 |
|
|
wait for 10 ns;
|
118 |
|
|
assert(MemAddr = x"0102") report "fetcher is not incrementing address" severity error;
|
119 |
|
|
assert(DebugIR = x"00F1" and DebugR0 /= x"12") report "IR is not correct. Execution occurs during first fetch";
|
120 |
|
|
MemIn <= x"0056";
|
121 |
|
|
wait for 10 ns;
|
122 |
|
|
assert(DebugR0 = x"F1") report "loaded value of R0 is not correct" severity error;
|
123 |
|
|
wait for 10 ns;
|
124 |
|
|
|
125 |
|
|
-- summary of testbench
|
126 |
|
|
assert false
|
127 |
|
|
report "Testbench of core completed successfully!"
|
128 |
|
|
severity note;
|
129 |
|
|
|
130 |
|
|
wait;
|
131 |
|
|
|
132 |
|
|
-- insert stimulus here
|
133 |
|
|
|
134 |
|
|
wait;
|
135 |
|
|
end process;
|
136 |
|
|
|
137 |
|
|
|
138 |
|
|
END;
|