OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [tb.vhd] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 howe.r.j.8
-------------------------------------------------------------------------------
2
--| @file tb.vhd
3
--| @brief Main test bench.
4
--|
5
--| @author         Richard James Howe.
6
--| @copyright      Copyright 2013,2017 Richard James Howe.
7
--| @license        MIT
8
--| @email          howe.r.j.89@gmail.com
9
--|
10
--| This test bench does quite a lot. It is not like normal VHDL test benches
11
--| in the fact that it uses configurable variables that it read in from a
12
--| file, which it does in an awkward but usable fashion.
13
--|
14
--| It also tests multiple modules.
15
--|
16
--| @todo Optionally, read in from standard input and send the character
17
--| over the UART, then print out any received characters to standard out.
18
-------------------------------------------------------------------------------
19
 
20
library ieee,work;
21
use ieee.std_logic_1164.all;
22
use ieee.numeric_std.all;
23
use ieee.math_real.all;
24
use std.textio.all;
25
use work.util.all;
26
use work.core_pkg.all;
27
use work.vga_pkg.all;
28
use work.uart_pkg.uart_core;
29
 
30
entity tb is
31
end tb;
32
 
33
architecture testing of tb is
34
        constant clock_frequency:         positive := 100_000_000;
35
        constant number_of_interrupts:    positive := 8;
36
        constant uart_baud_rate:          positive := 115200;
37
        constant configuration_file_name: string   := "tb.cfg";
38
        constant clk_period:              time     := 1000 ms / clock_frequency;
39
        constant uart_tx_time:            time     := (10*1000 ms) / 115200;
40
 
41
        -- Test bench configurable options --
42
 
43
        type configurable_items is record
44
                number_of_iterations: positive;
45
                verbose:              boolean;
46
                report_number:        natural;
47
                interactive:          boolean;
48
        end record;
49
 
50
        function set_configuration_items(ci: configuration_items) return configurable_items is
51
                variable r: configurable_items;
52
        begin
53
                r.number_of_iterations := ci(0).value;
54
                r.verbose              := ci(1).value > 0;
55
                r.interactive          := ci(2).value > 0;
56
                r.report_number        := ci(3).value;
57
                return r;
58
        end function;
59
 
60
        constant configuration_default: configuration_items(0 to 3) := (
61
                (name => "Cycles  ", value => 1000),
62
                (name => "Verbose ", value => 1),
63
                (name => "Interact", value => 0),
64
                (name => "LogFor  ", value => 256));
65
 
66
        -- Test bench configurable options --
67
 
68
        signal stop:  std_ulogic :=  '0';
69
        signal debug: cpu_debug_interface;
70
 
71
        signal clk:   std_ulogic := '0';
72
        signal rst:   std_ulogic := '0';
73
 
74
--      signal  cpu_wait: std_ulogic := '0'; -- CPU wait flag
75
 
76
        -- Basic I/O
77
        signal btnu:  std_ulogic := '0';  -- button up
78
        signal btnd:  std_ulogic := '0';  -- button down
79
        signal btnc:  std_ulogic := '0';  -- button centre
80
        signal btnl:  std_ulogic := '0';  -- button left
81
        signal btnr:  std_ulogic := '0';  -- button right
82
        signal sw:    std_ulogic_vector(7 downto 0) := (others => '0'); -- switches
83
        signal an:    std_ulogic_vector(3 downto 0) := (others => '0'); -- anodes   8 segment display
84
        signal ka:    std_ulogic_vector(7 downto 0) := (others => '0'); -- kathodes 8 segment display
85
        signal ld:    std_ulogic_vector(7 downto 0) := (others => '0'); -- leds
86
 
87
        -- VGA
88
        signal o_vga: vga_physical_interface;
89
        signal hsync_gone_high: boolean := false;
90
        signal vsync_gone_high: boolean := false;
91
 
92
        -- HID
93
        signal ps2_keyboard_data: std_ulogic := '0';
94
        signal ps2_keyboard_clk:  std_ulogic := '0';
95
 
96
        -- UART
97
        signal rx:                 std_ulogic := '0';
98
        signal tx:                 std_ulogic := '0';
99
        signal dout_ack, dout_stb: std_ulogic := '0';
100
        signal din_ack, din_stb:   std_ulogic := '0';
101
        signal dout:               std_ulogic_vector(7 downto 0) := (others => '0');
102
        signal din:                std_ulogic_vector(7 downto 0) := (others => '0');
103
 
104
        -- Wave form generator
105
        signal gen_dout:     std_ulogic_vector(15 downto 0) := (others => '0');
106
 
107
        shared variable cfg: configurable_items := set_configuration_items(configuration_default);
108
 
109
        signal configured: boolean := false;
110
 
111
        signal RamCS:     std_ulogic := 'X';
112
        signal MemOE:     std_ulogic := 'X'; -- negative logic
113
        signal MemWR:     std_ulogic := 'X'; -- negative logic
114
        signal MemAdv:    std_ulogic := 'X'; -- negative logic
115
        signal MemWait:   std_ulogic := 'X'; -- positive!
116
        signal FlashCS:   std_ulogic := 'X';
117
        signal FlashRp:   std_ulogic := 'X';
118
        signal MemAdr:    std_ulogic_vector(26 downto 1) := (others => 'X');
119
        signal MemDB:     std_logic_vector(15 downto 0) := (others => 'X');
120
 
121
begin
122
---- Units under test ----------------------------------------------------------
123
 
124
        MemDB <= (others => '0') when MemOE = '1' else (others => 'Z');
125
 
126
        uut: entity work.top
127
        generic map(
128
                clock_frequency      => clock_frequency,
129
                uart_baud_rate       => uart_baud_rate)
130
        port map(
131
                debug       => debug,
132
                clk         => clk,
133
                -- rst      => rst,
134
                btnu        => btnu,
135
                btnd        => btnd,
136
                btnc        => btnc,
137
                btnl        => btnl,
138
                btnr        => btnr,
139
                sw          => sw,
140
                an          => an,
141
                ka          => ka,
142
                ld          => ld,
143
                rx          => rx,
144
                tx          => tx,
145
                o_vga       => o_vga,
146
 
147
                ps2_keyboard_data => ps2_keyboard_data,
148
                ps2_keyboard_clk  => ps2_keyboard_clk,
149
 
150
                RamCS    =>  RamCS,
151
                MemOE    =>  MemOE,
152
                MemWR    =>  MemWR,
153
                MemAdv   =>  MemAdv,
154
                MemWait  =>  MemWait,
155
                FlashCS  =>  FlashCS,
156
                FlashRp  =>  FlashRp,
157
                MemAdr   =>  MemAdr,
158
                MemDB    =>  MemDB);
159
 
160
        uut_util: work.util.util_tb generic map(clock_frequency => clock_frequency);
161
        uut_vga:  work.vga_pkg.vt100_tb generic map(clock_frequency => clock_frequency);
162
 
163
        -- The "io_pins_tb" works correctly, however GHDL 0.29, compiled under
164
        -- Windows, cannot fails to simulate this component correctly, and it
165
        -- crashes. This does not affect the Linux build of GHDL. It has
166
        -- something to do with 'Z' values for std_ulogic types.
167
        --
168
 
169
        uut_io_pins: work.util.io_pins_tb      generic map(clock_frequency => clock_frequency);
170
 
171
        uut_uart: work.uart_pkg.uart_core
172
                generic map(
173
                        baud_rate            =>  uart_baud_rate,
174
                        clock_frequency      =>  clock_frequency)
175
                port map(
176
                        clk       =>  clk,
177
                        rst       =>  rst,
178
                        din       =>  din,
179
                        din_stb   =>  din_stb,
180
                        din_ack   =>  din_ack,
181
                        tx        =>  rx,
182
                        rx        =>  tx,
183
                        dout_ack  =>  dout_ack,
184
                        dout_stb  =>  dout_stb,
185
                        dout      =>  dout);
186
 
187
------ Simulation only processes ----------------------------------------------
188
        clk_process: process
189
        begin
190
                while stop = '0' loop
191
                        clk <= '1';
192
                        wait for clk_period / 2;
193
                        clk <= '0';
194
                        wait for clk_period / 2;
195
                end loop;
196
                wait;
197
        end process;
198
 
199
        output_process: process
200
                variable oline: line;
201
                variable c: character;
202
                variable have_char: boolean := true;
203
        begin
204
                wait until configured;
205
 
206
                if not cfg.interactive then
207
                        wait;
208
                end if;
209
 
210
                report "WRITING TO STDOUT";
211
                while stop = '0' loop
212
                        wait until (dout_stb = '1' or stop = '1');
213
                        if stop = '0' then
214
                                c := character'val(to_integer(unsigned(dout)));
215
                                write(oline, c);
216
                                have_char := true;
217
                                if dout = x"0d" then
218
                                        writeline(output, oline);
219
                                        have_char := false;
220
                                end if;
221
                                wait for clk_period;
222
                                dout_ack <= '1';
223
                                wait for clk_period;
224
                                dout_ack <= '0';
225
                        end if;
226
                end loop;
227
                if have_char then
228
                        writeline(output, oline);
229
                end if;
230
                wait;
231
        end process;
232
 
233
 
234
        -- @note The Input and Output mechanism that allows the tester to
235
        -- interact with the running simulation needs more work, it is buggy
236
        -- and experimental, but demonstrates the principle - that a VHDL
237
        -- test bench can be interacted with at run time.
238
        input_process: process
239
                variable c: character := ' ';
240
                variable iline: line;
241
                -- variable oline: line;
242
                variable good: boolean := true;
243
        begin
244
                din_stb <= '0';
245
                din     <= x"00";
246
                wait until configured;
247
                if not cfg.interactive then
248
                        din_stb <= '1';
249
                        din     <= x"AA";
250
                        wait;
251
                end if;
252
 
253
                report "READING FROM STDIN";
254
                while (not endfile(input)) and stop = '0' loop
255
                        readline(input, iline);
256
                        good := true;
257
                        while good and stop = '0' loop
258
                                read(iline, c, good);
259
                                if good then
260
                                        report "" & c;
261
                                end if;
262
                                din <=
263
                                std_ulogic_vector(to_unsigned(character'pos(c), din'length));
264
                                din_stb <= '1';
265
                                wait for clk_period;
266
                                din_stb <= '0';
267
                                assert din_ack = '1' severity warning;
268
                                -- wait for 100 us;
269
                                wait for 10 ms;
270
                        end loop;
271
                end loop;
272
                -- stop <= '1';
273
                wait;
274
        end process;
275
 
276
        hsync_gone_high <= true when o_vga.hsync = '1' else hsync_gone_high;
277
        vsync_gone_high <= true when o_vga.vsync = '1' else vsync_gone_high;
278
 
279
        -- I/O settings go here.
280
        stimulus_process: process
281
                variable w: line;
282
                variable count: integer := 0;
283
 
284
                function stringify(slv: std_ulogic_vector) return string is
285
                begin
286
                        return integer'image(to_integer(unsigned(slv)));
287
                end stringify;
288
 
289
                procedure element(l: inout line; we: boolean; name: string; slv: std_ulogic_vector) is
290
                begin
291
                        if we then
292
                                write(l, name & "(" & stringify(slv) & ") ");
293
                        end if;
294
                end procedure;
295
 
296
                procedure element(l: inout line; name: string; slv: std_ulogic_vector) is
297
                begin
298
                        element(l, true, name, slv);
299
                end procedure;
300
 
301
                function reportln(debug: cpu_debug_interface; cycles: integer) return line is
302
                        variable l: line;
303
                begin
304
                        write(l, integer'image(cycles) & ": ");
305
                        element(l, "pc",    debug.pc);
306
                        element(l, "insn",  debug.insn);
307
                        element(l, "daddr", debug.daddr);
308
                        element(l, "dout",  debug.dout);
309
                        return l;
310
                end function;
311
 
312
                variable configuration_values: configuration_items(configuration_default'range) := configuration_default;
313
        begin
314
                -- write_configuration_tb(configuration_file_name, configuration_default);
315
                read_configuration_tb(configuration_file_name, configuration_values);
316
                cfg := set_configuration_items(configuration_values);
317
                configured <= true;
318
 
319
                rst  <= '1';
320
                wait for clk_period * 2;
321
                rst  <= '0';
322
                for i in 0 to cfg.number_of_iterations loop
323
                        if cfg.verbose then
324
                                if count < cfg.report_number then
325
                                        w := reportln(debug, count);
326
                                        writeline(OUTPUT, w);
327
                                        count := count + 1;
328
                                elsif count < cfg.report_number + 1 then
329
                                        report "Simulation continuing: Reporting turned off";
330
                                        count := count + 1;
331
                                end if;
332
                        end if;
333
                        wait for clk_period * 1;
334
                end loop;
335
 
336
                -- It would be nice to test the other peripherals as
337
                -- well, the CPU-ID should be written to the LED 7 Segment
338
                -- displays, however we only get the cathode and anode
339
                -- values out of the unit.
340
 
341
                assert hsync_gone_high report "HSYNC not active - H2 failed to initialize VGA module";
342
                assert vsync_gone_high report "VSYNC not active - H2 failed to initialize VGA module";
343
 
344
                stop   <=  '1';
345
                wait;
346
        end process;
347
 
348
end architecture;
349
------ END ---------------------------------------------------------------------
350
 

powered by: WebSVN 2.1.0

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