OpenCores
URL https://opencores.org/ocsvn/light8080/light8080/trunk

Subversion Repositories light8080

[/] [light8080/] [trunk/] [vhdl/] [test/] [tb_template.vhdl] - Blame information for rev 36

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 20 ja_rd
--------------------------------------------------------------------------------
2
-- Light8080 simulation test bench.
3
--------------------------------------------------------------------------------
4
-- Source for the 8080 program is in asm\@PROGNAME@.asm
5
-------------------------------------------------------------------------------- 
6
-- 
7
-- This test bench provides a simulated CPU system to test programs. This test 
8
-- bench does not do any assertions or checks, all assertions are left to the 
9
-- software.
10
--
11
-- The simulated environment has 2KB of RAM, mirror-mapped to all the memory 
12
-- map of the 8080, initialized with the test program object code. See the perl
13
-- script 'util\hexconv.pl' and BAT files in the asm directory.
14
--
15
-- Besides, it provides some means to trigger hardware irq from software, 
16
-- including the specification of the instructions fed to the CPU as interrupt
17
-- vectors during inta cycles.
18
--
19
-- We will simulate 8 possible irq sources. The software can trigger any one of 
20
-- them by writing at registers 0x010 and 0x011. Register 0x010 holds the irq
21
-- source to be triggered (0 to 7) and register 0x011 holds the number of clock
22
-- cycles that will elapse from the end of the instruction that writes to the
23
-- register to the assertion of intr. 
24
--
25
-- When the interrupt is acknowledged and inta is asserted, the test bench reads
26
-- the value at register 0x010 as the irq source, and feeds an instruction to 
27
-- the CPU starting from the RAM address 0040h+source*4.
28
-- That is, address range 0040h-005fh is reserved for the simulated 'interrupt
29
-- vectors', a total of 4 bytes for each of the 8 sources. This allows the 
30
-- software to easily test different interrupt vectors without any hand 
31
-- assembly. All of this is strictly simulation-only stuff.
32
--
33
--
34
-- Upon completion, the software must write a value to register 0x020. Writing 
35
-- a 0x055 means 'success', writing a 0x0aa means 'failure'. Success and 
36
-- failure conditions are defined by the software.
37
--------------------------------------------------------------------------------
38
 
39
library ieee;
40
use ieee.std_logic_1164.ALL;
41
use ieee.std_logic_unsigned.all;
42
use ieee.numeric_std.ALL;
43
 
44
entity light8080_@PROGNAME@ is
45
end entity light8080_@PROGNAME@;
46
 
47
architecture behavior of light8080_@PROGNAME@ is
48
 
49
--------------------------------------------------------------------------------
50
-- Simulation parameters
51
 
52
-- T: simulated clock period
53
constant T : time := 100 ns;
54
 
55
-- MAX_SIM_LENGTH: maximum simulation time
56
constant MAX_SIM_LENGTH : time := T*7000; -- enough for the tb0
57
 
58
 
59
--------------------------------------------------------------------------------
60
 
61
        -- Component Declaration for the Unit Under Test (UUT)
62
component light8080
63
  port (
64
    addr_out :  out std_logic_vector(15 downto 0);
65
 
66
    inta :      out std_logic;
67
    inte :      out std_logic;
68
    halt :      out std_logic;
69
    intr :      in std_logic;
70
 
71
    vma :       out std_logic;
72
    io :        out std_logic;
73
    rd :        out std_logic;
74
    wr :        out std_logic;
75
    fetch :     out std_logic;
76
    data_in :   in std_logic_vector(7 downto 0);
77
    data_out :  out std_logic_vector(7 downto 0);
78
 
79
    clk :       in std_logic;
80
    reset :     in std_logic );
81
end component;
82
 
83
 
84
signal data_i :           std_logic_vector(7 downto 0) := (others=>'0');
85
signal vma_o  :           std_logic;
86
signal rd_o :             std_logic;
87
signal wr_o :             std_logic;
88
signal io_o :             std_logic;
89
signal data_o :           std_logic_vector(7 downto 0);
90
signal data_mem :         std_logic_vector(7 downto 0);
91
signal addr_o :           std_logic_vector(15 downto 0);
92
signal fetch_o :          std_logic;
93
signal inta_o :           std_logic;
94
signal inte_o :           std_logic;
95
signal intr_i :           std_logic := '0';
96
signal halt_o :           std_logic;
97
 
98
signal reset :            std_logic := '0';
99
signal clk :              std_logic := '1';
100
signal done :             std_logic := '0';
101
 
102
type t_rom is array(0 to 2047) of std_logic_vector(7 downto 0);
103
 
104
signal rom : t_rom := (
105
 
106
--@rom_data
107
 
108
);
109
 
110
signal irq_vector_byte:   std_logic_vector(7 downto 0);
111
signal irq_source :       integer range 0 to 7;
112
signal cycles_to_intr :   integer range -10 to 255;
113
signal int_vector_index : integer range 0 to 3;
114
signal addr_vector_table: integer range 0 to 65535;
115
 
116
begin
117
 
118
        -- Instantiate the Unit Under Test (UUT)
119
        uut: light8080 PORT MAP(
120
                clk => clk,
121
                reset => reset,
122
                vma => vma_o,
123
                rd => rd_o,
124
                wr => wr_o,
125
                io => io_o,
126
                fetch => fetch_o,
127
                addr_out => addr_o,
128
                data_in => data_i,
129
                data_out => data_o,
130
 
131
                intr => intr_i,
132
                inte => inte_o,
133
                inta => inta_o,
134
                halt => halt_o
135
        );
136
 
137
 
138
-- clock: run clock until test is done
139
clock:
140
process(done, clk)
141
begin
142
        if done = '0' then
143
                clk <= not clk after T/2;
144
        end if;
145
end process clock;
146
 
147
 
148
-- Drive reset and done 
149
main_test:
150
process
151
begin
152
        -- Assert reset for at least one full clk period
153
        reset <= '1';
154
        wait until clk = '1';
155
        wait for T/2;
156
        reset <= '0';
157
 
158
        -- Remember to 'cut away' the preceding 3 clk semiperiods from 
159
        -- the wait statement...
160
        wait for (MAX_SIM_LENGTH - T*1.5);
161
 
162
        -- Maximum sim time elapsed, assume the program ran away and
163
        -- stop the clk process asserting 'done' (which will stop the simulation)
164
        done <= '1';
165
 
166
  assert (done = '1')
167
        report "Test timed out."
168
        severity failure;
169
 
170
        wait;
171
end process main_test;
172
 
173
 
174
-- Synchronous RAM; 2KB mirrored everywhere
175
synchronous_ram:
176
process(clk)
177
begin
178
  if (clk'event and clk='1') then
179
    data_mem <= rom(conv_integer(addr_o(10 downto 0)));
180
    if wr_o = '1' and addr_o(15 downto 11)="00000" then
181
      rom(conv_integer(addr_o(10 downto 0))) <= data_o;
182
    end if;
183
  end if;
184
end process synchronous_ram;
185
 
186
 
187
irq_trigger_register:
188
process(clk)
189
begin
190
  if (clk'event and clk='1') then
191
    if reset='1' then
192
      cycles_to_intr <= -10; -- meaning no interrupt pending
193
      intr_i <= '0';
194
    else
195
      if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"11" then
196
        cycles_to_intr <= conv_integer(data_o) + 1;
197
      else
198
        if cycles_to_intr >= 0 then
199
          cycles_to_intr <= cycles_to_intr - 1;
200
        end if;
201
        if cycles_to_intr = 0 then
202
          intr_i <= '1';
203
        else
204
          intr_i <= '0';
205
        end if;
206
      end if;
207
    end if;
208
  end if;
209
end process irq_trigger_register;
210
 
211
 
212
irq_source_register:
213
process(clk)
214
begin
215
  if (clk'event and clk='1') then
216
    if reset='1' then
217
      irq_source <= 0;
218
    else
219
      if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"10" then
220
        irq_source <= conv_integer(data_o(2 downto 0));
221
      end if;
222
    end if;
223
  end if;
224
end process irq_source_register;
225
 
226
 
227
-- 'interrupt vector' logic.
228
irq_vector_table:
229
process(clk)
230
begin
231
  if (clk'event and clk='1') then
232
    if vma_o = '1' and rd_o='1' then
233
      if inta_o = '1' then
234
        int_vector_index <= int_vector_index + 1;
235
      else
236
        int_vector_index <= 0;
237
      end if;
238
    end if;
239
    -- this is the address of the byte we'll feed to the CPU
240
    addr_vector_table <= 64+irq_source*4+int_vector_index;
241
  end if;
242
end process irq_vector_table;
243
irq_vector_byte <= rom(addr_vector_table);
244
 
245
data_i <= data_mem when inta_o='0' else irq_vector_byte;
246
 
247
 
248
test_outcome_register:
249
process(clk)
250
variable outcome : std_logic_vector(7 downto 0);
251
begin
252
  if (clk'event and clk='1') then
253
    if io_o='1' and wr_o='1' and addr_o(7 downto 0)=X"20" then
254
    assert (data_o /= X"55") report "Software reports SUCCESS" severity failure;
255
    assert (data_o /= X"aa") report "Software reports FAILURE" severity failure;
256
    assert ((data_o = X"aa") or (data_o = X"55"))
257
    report "Software reports unexpected outcome value."
258
    severity failure;
259
    end if;
260
  end if;
261
end process test_outcome_register;
262
 
263
 
264
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.