forth-cpu

Форк
0
/
tb.vhd 
406 строк · 12.3 Кб
1
-------------------------------------------------------------------------------
2
--| @file tb.vhd
3
--| @brief Main test bench.
4
--|
5
--| @author         Richard James Howe.
6
--| @copyright      Copyright 2013-2019 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 reads in from a
12
--| file, which it does in an awkward but usable fashion. It also has a
13
--| partially working way of connecting a simulated UART to STDIN/STDOUT, which
14
--| is a work in progress.
15
--|
16
--| It also tests multiple modules.
17
--|
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

29
entity tb is
30
end tb;
31

32
architecture testing of tb is
33
	constant g: common_generics := (
34
		clock_frequency    => 100_000_000,
35
		asynchronous_reset => true,
36
		delay              => 0 ns);
37

38
	constant number_of_interrupts:    positive := 8;
39
	constant uart_baud:               positive := 115200;
40
	constant configuration_file_name: string   := "tb.cfg";
41
	constant uart_tx_time:            time     := (10*1000 ms) / 115200;
42
	constant uart_default_input:      std_ulogic_vector(7 downto 0) := x"AA";
43
	constant reset_period_us:         natural  := 1;
44
	constant jitter_on:               boolean  := false;
45
	constant clock_period:            time     := 1000 ms / g.clock_frequency;
46
	constant tb_vga_on:               boolean  := false;
47
	constant tb_uart_on:              boolean  := false;
48
	constant tb_util_on:              boolean  := false;
49

50
	-- Test bench configurable options --
51

52
	type configurable_items is record
53
		number_of_iterations: natural; -- 0 == loop forever
54
		verbose:              boolean;
55
		report_number:        natural;
56
		interactive:          boolean;
57
		input_wait_for:       time;
58
	end record;
59

60
	function set_configuration_items(ci: configuration_items) return configurable_items is
61
		variable r: configurable_items;
62
	begin
63
		r.number_of_iterations := ci(0).value;
64
		r.verbose              := ci(1).value > 0;
65
		r.interactive          := ci(2).value > 0;
66
		r.input_wait_for       := ci(3).value * 1 ms;
67
		r.report_number        := ci(4).value;
68
		return r;
69
	end function;
70

71
	constant configuration_default: configuration_items(0 to 4) := (
72
		(name => "Cycles  ", value => 1000),
73
		(name => "Verbose ", value => 1),
74
		(name => "Interact", value => 0),
75
		(name => "InWaitMs", value => 8),
76
		(name => "LogFor  ", value => 256));
77

78
	-- Test bench configurable options --
79

80
	signal stop:  boolean := false;
81
	signal dbgi:  cpu_debug_interface;
82

83
	signal clk:          std_ulogic := '0';
84
	signal rst:          std_ulogic := '0';
85

86
	-- Basic I/O
87
	signal btnu:  std_ulogic := '0';  -- button up
88
	signal btnd:  std_ulogic := '0';  -- button down
89
	signal btnc:  std_ulogic := '0';  -- button centre
90
	signal btnl:  std_ulogic := '0';  -- button left
91
	signal btnr:  std_ulogic := '0';  -- button right
92
	signal sw:    std_ulogic_vector(7 downto 0) := (others => '0'); -- switches
93
	signal an:    std_ulogic_vector(3 downto 0) := (others => '0'); -- anodes   8 segment display
94
	signal ka:    std_ulogic_vector(7 downto 0) := (others => '0'); -- kathodes 8 segment display
95
	signal ld:    std_ulogic_vector(7 downto 0) := (others => '0'); -- leds
96

97
	-- VGA
98
	signal o_vga: vga_physical_interface;
99
	signal hsync_gone_high: boolean := false;
100
	signal vsync_gone_high: boolean := false;
101

102
	-- HID
103
	signal ps2_keyboard_data: std_ulogic := '0';
104
	signal ps2_keyboard_clk:  std_ulogic := '0';
105

106
	-- UART
107
	signal rx:                 std_ulogic := '0';
108
	signal tx:                 std_ulogic := '0';
109
	signal dout_ack, dout_stb: std_ulogic := '0';
110
	signal din_ack, din_stb:   std_ulogic := '0';
111
	signal dout:               std_ulogic_vector(7 downto 0) := (others => '0');
112
	signal din:                std_ulogic_vector(7 downto 0) := (others => '0');
113

114
	-- Wave form generator
115
	signal gen_dout:     std_ulogic_vector(15 downto 0) := (others => '0');
116

117
	shared variable cfg: configurable_items := set_configuration_items(configuration_default);
118

119
	signal configured: boolean := false;
120

121
	signal ram_cs:     std_ulogic := 'X';
122
	signal mem_oe:     std_ulogic := 'X'; -- negative logic
123
	signal mem_wr:     std_ulogic := 'X'; -- negative logic
124
	signal mem_adv:    std_ulogic := 'X'; -- negative logic
125
	signal mem_wait:   std_ulogic := 'X'; -- positive!
126
	signal flash_cs:   std_ulogic := 'X';
127
	signal flash_rp:   std_ulogic := 'X';
128
	signal mem_addr:   std_ulogic_vector(26 downto 1) := (others => 'X');
129
	signal mem_data:   std_logic_vector(15 downto 0)  := (others => 'X');
130

131
begin
132
---- Units under test ----------------------------------------------------------
133

134
	mem_data <= (others => '0') when mem_oe = '1' else (others => 'Z');
135

136
	uut: entity work.top
137
	generic map(
138
		g               => g,
139
		reset_period_us => reset_period_us,
140
		uart_baud  => uart_baud)
141
	port map(
142
		debug       => dbgi,
143
		clk         => clk,
144
		-- rst      => rst,
145
		btnu        => btnu,
146
		btnd        => btnd,
147
		btnc        => btnc,
148
		btnl        => btnl,
149
		btnr        => btnr,
150
		sw          => sw,
151
		an          => an,
152
		ka          => ka,
153
		ld          => ld,
154
		rx          => rx,
155
		tx          => tx,
156
		o_vga       => o_vga,
157

158
		ps2_keyboard_data => ps2_keyboard_data,
159
		ps2_keyboard_clk  => ps2_keyboard_clk,
160

161
		ram_cs    =>  ram_cs,
162
		mem_oe    =>  mem_oe,
163
		mem_wr    =>  mem_wr,
164
		mem_adv   =>  mem_adv,
165
		mem_wait  =>  mem_wait,
166
		flash_cs  =>  flash_cs,
167
		flash_rp  =>  flash_rp,
168
		mem_addr  =>  mem_addr,
169
		mem_data  =>  mem_data);
170

171
	-- NB. It would be nice to configure these as off/on, as well as
172
	-- controlling how long they run for from here.
173
	util_g: if tb_util_on generate uut_util: work.util.util_tb     generic map(g => g); end generate;
174
	vga_g:  if tb_vga_on  generate uut_vga:  work.vga_pkg.vt100_tb generic map(g => g); end generate;
175
	uart_g: if tb_uart_on generate uut_uart: work.uart_pkg.uart_tb generic map(g => g); end generate;
176

177
	uart_0_blk: block
178
		signal uart_clock_rx_we, uart_clock_tx_we, uart_control_we: std_ulogic := '0';
179
		signal uart_reg: std_ulogic_vector(15 downto 0);
180
	begin
181
		uart_0: work.uart_pkg.uart_core
182
			generic map (g => g, baud => uart_baud)
183
			port map (
184
				clk   => clk,
185
				rst   => rst,
186
				tx_di => din,
187
				tx_we => din_stb,
188
				tx_ok => din_ack,
189
				tx    => rx,
190
		
191
				rx    => tx,
192
				rx_ok => open,
193
				rx_nd => dout_stb,
194
				rx_do => dout,
195
				rx_re => dout_ack,
196
		
197
				reg             => uart_reg,
198
				clock_reg_tx_we => uart_clock_tx_we,
199
				clock_reg_rx_we => uart_clock_rx_we,
200
				control_reg_we  => uart_control_we);
201
	end block;
202

203
------ Simulation only processes ----------------------------------------------
204
	clk_process: process
205
		variable seed1, seed2 : positive;
206
		variable r : real;
207
		variable jit_high, jit_low: time  := 0 ns;
208
	begin
209
		while not stop loop
210
			if jitter_on then
211
				uniform(seed1, seed2, r);
212
				jit_high := r * g.delay;
213
				uniform(seed1, seed2, r);
214
				jit_low := r * g.delay;
215
				uniform(seed1, seed2, r);
216
				if r < 0.5 then jit_high := -jit_high; end if;
217
				uniform(seed1, seed2, r);
218
				if r < 0.5 then jit_low := -jit_low; end if;
219
			else
220
				jit_high := 0 ns;
221
				jit_low  := 0 ns;
222
			end if;
223
			clk <= '1';
224
			wait for (clock_period / 2) + jit_high;
225
			clk <= '0';
226
			wait for (clock_period / 2) + jit_low;
227
		end loop;
228
		report "clk_process end";
229
		wait;
230
	end process;
231

232
	output_process: process
233
		variable oline: line;
234
		variable c: character;
235
		variable have_char: boolean := true;
236
	begin
237
		wait until configured;
238

239
		if not cfg.interactive then
240
			report "Output turned off";
241
			report "output_process end";
242
			wait;
243
		end if;
244

245
		report "Writing to STDOUT";
246
		while not stop loop
247
			wait until (dout_stb = '1' or stop);
248
			if not stop then
249
				c := character'val(to_integer(unsigned(dout)));
250
				write(oline, c);
251
				have_char := true;
252
				if dout = x"0d" then
253
					writeline(output, oline);
254
					have_char := false;
255
				end if;
256
				wait for clock_period;
257
				dout_ack <= '1';
258
				wait for clock_period;
259
				dout_ack <= '0';
260
			end if;
261
		end loop;
262
		if have_char then
263
			writeline(output, oline);
264
		end if;
265
		report "output_process end";
266
		wait;
267
	end process;
268

269

270
	-- The Input and Output mechanism that allows the tester to
271
	-- interact with the running simulation needs more work, it is buggy
272
	-- and experimental, but demonstrates the principle - that a VHDL
273
	-- test bench can be interacted with at run time.
274
	input_process: process
275
		variable c: character := ' ';
276
		variable iline: line;
277
		-- variable oline: line;
278
		variable good: boolean := true;
279
		variable eoi:  boolean := false;
280
	begin
281
		din_stb <= '0';
282
		din     <= x"00";
283
		wait until configured;
284
		if not cfg.interactive then
285
			din_stb <= '1';
286
			din     <= uart_default_input;
287
			report "input process non-interactive";
288
			report "input_process end";
289
			wait;
290
		end if;
291

292
		report "Waiting for " & time'image(cfg.input_wait_for) & " (before reading from STDIN)";
293
		wait for cfg.input_wait_for;
294
		report "Reading from STDIN (Hit EOF/CTRL-D/CTRL-Z After entering a line)";
295
		while (not endfile(input)) and not stop and eoi = false loop
296
			report "readline...";
297
			readline(input, iline);
298
			good := true;
299
			while good and not stop loop
300
				read(iline, c, good);
301
				if good then
302
					report "" & c;
303
				else
304
					report "EOL/EOI";
305
					c   := LF;
306
					eoi := true;
307
				end if;
308
				din <= std_ulogic_vector(to_unsigned(character'pos(c), din'length));
309
				din_stb <= '1';
310
				wait for clock_period;
311
				din_stb <= '0';
312
				wait for 100 us;
313
			end loop;
314
		end loop;
315
		report "input_process end";
316
		wait;
317
	end process;
318

319
	hsync_gone_high <= true when o_vga.hsync = '1' else hsync_gone_high;
320
	vsync_gone_high <= true when o_vga.vsync = '1' else vsync_gone_high;
321

322
	-- I/O settings go here.
323
	stimulus_process: process
324
		variable w: line;
325
		variable count: integer := 0;
326

327
		function stringify(slv: std_ulogic_vector) return string is
328
		begin
329
			return integer'image(to_integer(unsigned(slv)));
330
		end stringify;
331

332
		procedure element(l: inout line; we: boolean; name: string; slv: std_ulogic_vector) is
333
		begin
334
			if we then
335
				write(l, name & "(" & stringify(slv) & ") ");
336
			end if;
337
		end procedure;
338

339
		procedure element(l: inout line; name: string; slv: std_ulogic_vector) is
340
		begin
341
			element(l, true, name, slv);
342
		end procedure;
343

344
		function reportln(debug: cpu_debug_interface; cycles: integer) return line is
345
			variable l: line;
346
		begin
347
			write(l, integer'image(cycles) & ": ");
348
			element(l, "pc",    debug.pc);
349
			element(l, "insn",  debug.insn);
350
			element(l, "daddr", debug.daddr);
351
			element(l, "dout",  debug.dout);
352
			return l;
353
		end function;
354

355
		variable configuration_values: configuration_items(configuration_default'range) := configuration_default;
356
	begin
357
		-- write_configuration_tb(configuration_file_name, configuration_default);
358
		read_configuration_tb(configuration_file_name, configuration_values);
359
		cfg := set_configuration_items(configuration_values);
360
		configured <= true;
361

362
		rst  <= '1';
363
		wait for clock_period * 2;
364
		rst  <= '0';
365

366
		if cfg.number_of_iterations = 0 then
367
			report "RUNNING FOREVER: number of iterations is zero" severity warning;
368
			report "stimulus_process end";
369
			wait;
370
		end if;
371

372
		for i in 0 to cfg.number_of_iterations loop
373
			if cfg.verbose then
374
				if count < cfg.report_number then
375
					w := reportln(dbgi, count);
376
					writeline(OUTPUT, w);
377
					count := count + 1;
378
				elsif count < cfg.report_number + 1 then
379
					report "Simulation continuing: Reporting turned off";
380
					count := count + 1;
381
				end if;
382
			end if;
383
			wait for clock_period * 1;
384
		end loop;
385

386
		-- These HSYNC and VSYNC asserts are included under the assumption
387
		-- that the image running on the H2 CPU will initiate the VGA, if
388
		-- it does not (perhaps because it is running it's own initialization
389
		-- routines), then the HSYNC or VSYNC will never go high - so this is
390
		-- not necessarily an error.
391
		--
392
		-- It would be nice to test the other peripherals as
393
		-- well, the CPU-ID should be written to the LED 7 Segment
394
		-- displays, however we only get the cathode and anode
395
		-- values out of the unit.
396

397
		assert hsync_gone_high report "HSYNC not active - H2 failed to initialize VGA module";
398
		assert vsync_gone_high report "VSYNC not active - H2 failed to initialize VGA module";
399

400
		stop   <=  true;
401
		report "stimulus_process end";
402
		wait;
403
	end process;
404

405
end architecture;
406
------ END ---------------------------------------------------------------------
407

408

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.