forth-cpu

Форк
0
/
util.vhd 
4102 строки · 120.5 Кб
1
-------------------------------------------------------------------------------
2
--| @file util.vhd
3
--| @brief A collection of utilities and simple components. The components
4
--| should be synthesizable, and the functions can be used within synthesizable
5
--| components, unless marked with a "_tb" suffix (or if the function n_bits).
6
--|
7
--| Other modules to implement; CRC core (reuse LFSR), Count
8
--| Leading Zeros, Count Trailing Zeros, Manchester CODEC, Wishbone interface
9
--| types and Wishbone Bus Arbitrator. Also SPI, a H2 core with an eForth image
10
--| read to go, and UART.
11
--|
12
--| More exotic modules would include; encryption, compression, sorting networks,
13
--| switching networks, Reed-Solomon CODEC, Discrete Fourier Transform/Discrete
14
--| Cosine Transform, Pulse Width/Code/Position Modulation modules, so long as
15
--| they are fairly generic and synthesizable.
16
--|
17
--| Potential improvements to the library:
18
--| - Optional registers on either input or output, selectable by a generic
19
--| - Better timing models
20
--| - More assertions
21
--| - See 'A Structured VHDL design' by Jiri Gaisler,
22
--|   <http://gaisler.com/doc/vhdl2proc.pdf> and apply methodology.
23
--|
24
--| @author         Richard James Howe
25
--| @copyright      Copyright 2017, 2019 Richard James Howe
26
--| @license        MIT
27
--| @email          howe.r.j.89@gmail.com
28
-------------------------------------------------------------------------------
29
library ieee, work;
30
use ieee.std_logic_1164.all;
31
use ieee.numeric_std.all;
32
use std.textio.all;
33

34
package util is
35
	-- Not all modules will need every generic specified here, even so it
36
	-- is easier to group the common generics in one structure.
37
	type common_generics is record
38
		clock_frequency:    positive; -- clock frequency of module clock
39
		delay:              time;     -- gate delay for simulation purposes
40
		asynchronous_reset: boolean;  -- use asynchronous reset if true
41
	end record;
42

43
	constant default_settings: common_generics := (
44
		clock_frequency    => 100_000_000,
45
		delay              => 10 ns,
46
		asynchronous_reset => true
47
	);
48

49
	component util_tb is
50
		generic (g: common_generics);
51
	end component;
52

53
	component clock_source_tb is
54
		generic (g: common_generics; hold_rst: positive := 1);
55
		port (
56
			stop:            in     std_ulogic := '0';
57
			clk:             out    std_ulogic;
58
			clk_with_jitter: out    std_ulogic := '0';
59
			rst:             out    std_ulogic := '0');
60
	end component;
61

62
	component reg
63
		generic (g: common_generics; N: positive);
64
		port (
65
			clk: in  std_ulogic;
66
			rst: in  std_ulogic;
67
			we:  in  std_ulogic;
68
			di:  in  std_ulogic_vector(N - 1 downto 0);
69
			do:  out std_ulogic_vector(N - 1 downto 0));
70
	end component;
71

72
	component shift_register
73
		generic (g: common_generics; N: positive);
74
		port (
75
			clk:     in  std_ulogic;
76
			rst:     in  std_ulogic;
77
			we:      in  std_ulogic;
78
			di:      in  std_ulogic;
79
			do:      out std_ulogic;
80

81
			-- optional
82
			load_we: in  std_ulogic := '0';
83
			load_i:  in  std_ulogic_vector(N - 1 downto 0) := (others => '0');
84
			load_o:  out std_ulogic_vector(N - 1 downto 0));
85
	end component;
86

87
	component shift_register_tb
88
		generic (g: common_generics);
89
	end component;
90

91
	component timer_us
92
		generic (g: common_generics; timer_period_us: natural);
93
		port (
94
			clk: in  std_ulogic;
95
			rst: in  std_ulogic;
96
			co:  out std_ulogic);
97
	end component;
98

99
	component timer_us_tb
100
		generic (g: common_generics);
101
	end component;
102

103
	component rising_edge_detector is
104
		generic (g: common_generics);
105
		port (
106
			clk:    in  std_ulogic;
107
			rst:    in  std_ulogic;
108
			di:     in  std_ulogic;
109
			do:     out std_ulogic);
110
	end component;
111

112
	component rising_edge_detector_tb is
113
		generic (g: common_generics);
114
	end component;
115

116
	component rising_edge_detectors is
117
		generic (g: common_generics; N: positive);
118
		port (
119
			clk:    in  std_ulogic;
120
			rst:    in  std_ulogic;
121
			di:     in  std_ulogic_vector(N - 1 downto 0);
122
			do:     out std_ulogic_vector(N - 1 downto 0));
123
	end component;
124

125
	-- NB. 'half_adder' test bench is folded in to 'full_adder_tb'
126
	component half_adder is
127
		generic (g: common_generics); -- simulation only
128
		port (
129
			a:     in  std_ulogic;
130
			b:     in  std_ulogic;
131
			sum:   out std_ulogic;
132
			carry: out std_ulogic);
133
	end component;
134

135
	component full_adder is
136
		generic (g: common_generics); -- simulation only
137
		port (
138
			x:     in    std_ulogic;
139
			y:     in    std_ulogic;
140
			z:     in    std_ulogic;
141
			sum:   out   std_ulogic;
142
			carry: out   std_ulogic);
143
	end component;
144

145
	component full_adder_tb is
146
		generic (g: common_generics);
147
	end component;
148

149
	component fifo is
150
		generic (g: common_generics;
151
			data_width:  positive;
152
			fifo_depth:  positive;
153
			read_first:  boolean := true);
154
		port (
155
			clk:   in  std_ulogic;
156
			rst:   in  std_ulogic;
157
			di:    in  std_ulogic_vector(data_width - 1 downto 0);
158
			we:    in  std_ulogic;
159
			re:    in  std_ulogic;
160
			do:    out std_ulogic_vector(data_width - 1 downto 0);
161

162
			-- optional
163
			full:  out std_ulogic := '0';
164
			empty: out std_ulogic := '1');
165
	end component;
166

167
	component fifo_tb is
168
		generic (g: common_generics);
169
	end component;
170

171
	component counter is
172
		generic (g: common_generics; N: positive);
173
		port (
174
			clk:     in  std_ulogic;
175
			rst:     in  std_ulogic;
176
			ce:      in  std_ulogic;
177
			cr:      in  std_ulogic;
178
			dout:    out std_ulogic_vector(N - 1 downto 0);
179

180
			-- optional
181
			load_we: in  std_ulogic := '0';
182
			load_i:  in  std_ulogic_vector(N - 1 downto 0) := (others => '0'));
183
	end component;
184

185
	component counter_tb is
186
		generic (g: common_generics);
187
	end component;
188

189
	component lfsr is
190
		generic (g: common_generics; constant tap: std_ulogic_vector);
191
		port (
192
			clk: in  std_ulogic;
193
			rst: in  std_ulogic;
194
			ce:  in  std_ulogic := '1';
195
			we:  in  std_ulogic;
196
			di:  in  std_ulogic_vector(tap'high + 1 downto tap'low);
197
			do:  out std_ulogic_vector(tap'high + 1 downto tap'low));
198
	end component;
199

200
	component lfsr_tb is
201
		generic (g: common_generics);
202
	end component;
203

204
	component io_pins is
205
		generic (g: common_generics; N: positive);
206
		port (
207
			clk:         in    std_ulogic;
208
			rst:         in    std_ulogic;
209
			control:     in    std_ulogic_vector(N - 1 downto 0);
210
			control_we:  in    std_ulogic;
211
			din:         in    std_ulogic_vector(N - 1 downto 0);
212
			din_we:      in    std_ulogic;
213
			dout:        out   std_ulogic_vector(N - 1 downto 0);
214
			pins:        inout std_logic_vector(N - 1 downto 0)); -- NB!
215
	end component;
216

217
	component io_pins_tb is
218
		generic (g: common_generics);
219
	end component;
220

221
	type file_format is (FILE_HEX, FILE_BINARY, FILE_NONE);
222

223
	component dual_port_block_ram is
224
	generic (g: common_generics;
225
		addr_length: positive    := 12;
226
		data_length: positive    := 16;
227
		file_name:   string      := "memory.bin";
228
		file_type:   file_format := FILE_BINARY);
229
	port (
230
		-- port A of dual port RAM
231
		a_clk:  in  std_ulogic;
232
		a_dwe:  in  std_ulogic;
233
		a_dre:  in  std_ulogic;
234
		a_addr: in  std_ulogic_vector(addr_length - 1 downto 0);
235
		a_din:  in  std_ulogic_vector(data_length - 1 downto 0);
236
		a_dout: out std_ulogic_vector(data_length - 1 downto 0) := (others => '0');
237
		-- port B of dual port RAM
238
		b_clk:  in  std_ulogic;
239
		b_dwe:  in  std_ulogic;
240
		b_dre:  in  std_ulogic;
241
		b_addr: in  std_ulogic_vector(addr_length - 1 downto 0);
242
		b_din:  in  std_ulogic_vector(data_length - 1 downto 0);
243
		b_dout: out std_ulogic_vector(data_length - 1 downto 0) := (others => '0'));
244
	end component;
245

246
	component single_port_block_ram is
247
	generic (g: common_generics;
248
		addr_length: positive    := 12;
249
		data_length: positive    := 16;
250
		file_name:   string      := "memory.bin";
251
		file_type:   file_format := FILE_BINARY);
252
	port (
253
		clk:  in  std_ulogic;
254
		dwe:  in  std_ulogic;
255
		dre:  in  std_ulogic;
256
		addr: in  std_ulogic_vector(addr_length - 1 downto 0);
257
		din:  in  std_ulogic_vector(data_length - 1 downto 0);
258
		dout: out std_ulogic_vector(data_length - 1 downto 0) := (others => '0'));
259
	end component;
260

261
	component data_source is
262
		generic (g: common_generics;
263
			addr_length: positive    := 12;
264
			data_length: positive    := 16;
265
			file_name:   string      := "memory.bin";
266
			file_type:   file_format := FILE_BINARY);
267
		port (
268
			clk:     in  std_ulogic;
269
			rst:     in  std_ulogic;
270

271
			ce:      in  std_ulogic := '1';
272
			cr:      in  std_ulogic;
273

274
			load:    in  std_ulogic_vector(addr_length - 1 downto 0) := (others => '0');
275
			load_we: in  std_ulogic := '0';
276

277
			dout:    out std_ulogic_vector(data_length - 1 downto 0));
278
	end component;
279

280
	component ucpu is
281
		generic (
282
			asynchronous_reset:  boolean := true; -- use asynchronous reset if true, synchronous if false
283
			delay:               time    := 0 ns; -- simulation only
284

285
			width:               positive range 8 to 32 := 8);
286
		port (
287
			clk, rst: in  std_ulogic;
288

289
			pc:       out std_ulogic_vector(width - 3 downto 0);
290
			op:       in  std_ulogic_vector(width - 1 downto 0);
291

292
			adr:      out std_ulogic_vector(width - 3 downto 0);
293
			di:       in  std_ulogic_vector(width - 1 downto 0);
294
			re, we:   out std_ulogic;
295
			do:       out std_ulogic_vector(width - 1 downto 0));
296
	end component;
297

298
	component ucpu_tb is
299
		generic (g: common_generics; file_name: string := "ucpu.bin");
300
	end component;
301

302
	component restoring_divider is
303
		generic (g: common_generics; N: positive);
304
		port (
305
			clk:   in  std_ulogic;
306
			rst:   in  std_ulogic := '0';
307

308
			a:     in  std_ulogic_vector(N - 1 downto 0);
309
			b:     in  std_ulogic_vector(N - 1 downto 0);
310
			start: in  std_ulogic;
311
			done:  out std_ulogic;
312
			c:     out std_ulogic_vector(N - 1 downto 0));
313
	end component;
314

315
	component restoring_divider_tb is
316
		generic (g: common_generics);
317
	end component;
318

319
	component debounce_us is
320
		generic (g: common_generics; timer_period_us: natural);
321
		port (
322
			clk:   in  std_ulogic;
323
			di:    in  std_ulogic;
324
			do:    out std_ulogic);
325
	end component;
326

327
	component debounce_block_us is
328
		generic (g: common_generics; N: positive; timer_period_us: natural);
329
		port (
330
			clk:   in  std_ulogic;
331
			di:    in  std_ulogic_vector(N - 1 downto 0);
332
			do:    out std_ulogic_vector(N - 1 downto 0));
333
	end component;
334

335
	component debounce_us_tb is
336
		generic (g: common_generics);
337
	end component;
338

339
	component state_changed is
340
		generic (g: common_generics);
341
		port (
342
			clk: in  std_ulogic;
343
			rst: in  std_ulogic;
344
			di:  in  std_ulogic;
345
			do:  out std_ulogic);
346
	end component;
347

348
	component state_block_changed is
349
		generic (g: common_generics; N: positive);
350
		port (
351
			clk: in  std_ulogic;
352
			rst: in  std_ulogic;
353
			di:  in  std_ulogic_vector(N - 1 downto 0);
354
			do:  out std_ulogic_vector(N - 1 downto 0));
355
	end component;
356

357
	component reset_generator is
358
		generic (g: common_generics; reset_period_us: natural := 1);
359
		port (
360
			clk: in  std_logic := 'X';
361
			rst: out std_logic := '0'); -- reset out!
362
	end component;
363

364
	component reset_generator_tb is
365
		generic (g: common_generics);
366
	end component;
367

368
	function n_bits(x: natural) return natural;           -- Not synthesizable
369
	function n_bits(x: std_ulogic_vector) return natural; -- Not synthesizable
370

371
	component bit_count is
372
		generic (g: common_generics; N: positive);
373
		port (
374
			bits:   in std_ulogic_vector(N - 1 downto 0);
375
			count: out std_ulogic_vector(n_bits(N) downto 0));
376
	end component;
377

378
	component bit_count_tb is
379
		generic (g: common_generics);
380
	end component;
381

382
	component majority is
383
		generic (g: common_generics; N: positive; even_wins: boolean := false);
384
		port (
385
			bits: in std_ulogic_vector(N - 1 downto 0);
386
			vote: out std_ulogic;
387
			tie: out std_ulogic);
388
	end component;
389

390
	component majority_tb is
391
		generic (g: common_generics);
392
	end component;
393

394
	component delay_line is
395
		generic (g: common_generics; width: positive; depth: natural);
396
		port (
397
			clk: in std_ulogic;
398
			rst: in std_ulogic;
399
			ce:  in std_ulogic := '1';
400
			di:  in std_ulogic_vector(width - 1 downto 0);
401
			do: out std_ulogic_vector(width - 1 downto 0));
402
	end component;
403

404
	component delay_line_tb is
405
		generic (g: common_generics);
406
	end component;
407

408
	component gray_encoder is
409
		generic (g: common_generics; N: positive);
410
		port (di: in std_ulogic_vector(N - 1 downto 0);
411
		     do: out std_ulogic_vector(N - 1 downto 0));
412
	end component;
413

414
	component gray_decoder is
415
		generic (g: common_generics; N: positive);
416
		port (di: in std_ulogic_vector(N - 1 downto 0);
417
		     do: out std_ulogic_vector(N - 1 downto 0));
418
	end component;
419

420
	component gray_tb is
421
		generic (g: common_generics);
422
	end component;
423

424
	component parity_module is
425
		generic (g: common_generics; N: positive; even: boolean);
426
		port (di: in std_ulogic_vector(N - 1 downto 0);
427
			do: out std_ulogic);
428
	end component;
429

430
	component hamming_7_4_encoder is
431
		generic (g: common_generics);
432
		port (
433
			di:      in std_ulogic_vector(3 downto 0);
434
			do:     out std_ulogic_vector(6 downto 0);
435
			parity: out std_ulogic -- parity over 'di'
436
		);
437
	end component;
438

439
	component hamming_7_4_decoder is
440
		generic (g: common_generics; secdec: boolean := true);
441
		port (
442
			di:      in std_ulogic_vector(6 downto 0);
443
			parity:  in std_ulogic;
444
			do:     out std_ulogic_vector(3 downto 0);
445
			single, double: out std_ulogic);
446
	end component;
447

448
	component hamming_7_4_tb is
449
		generic (g: common_generics);
450
	end component;
451

452
	type vga_configuration is record
453
		clock_frequency: positive;   -- pixel clock frequency
454
		h_pulse:         integer;    -- horizontal sync pulse width in pixels
455
		h_back_porch:    integer;    -- horizontal back porch width in pixels
456
		h_pixels:        integer;    -- horizontal display width in pixels
457
		h_front_porch:   integer;    -- horizontal front porch width in pixels
458
		h_polarity:      std_ulogic; -- horizontal sync pulse polarity (1 = positive, 0 = negative)
459

460
		v_pulse:         integer;    -- vertical sync pulse width in rows
461
		v_back_porch:    integer;    -- vertical back porch width in rows
462
		v_pixels:        integer;    -- vertical display width in rows
463
		v_front_porch:   integer;    -- vertical front porch width in rows
464
		v_polarity:      std_ulogic; -- vertical sync pulse polarity (1 = positive, 0 = negative)
465
	end record;
466

467
	constant vga_640x480: vga_configuration := (
468
		clock_frequency => 25_175_000,
469
		h_pulse =>  96, h_back_porch =>  48, h_pixels =>  640, h_front_porch =>  16, h_polarity => '0',
470
		v_pulse =>   2, v_back_porch =>  33, v_pixels =>  480, v_front_porch =>  10, v_polarity => '0');
471

472
	constant vga_800x600: vga_configuration := (
473
		clock_frequency => 40_000_000,
474
		h_pulse => 128, h_back_porch =>  88, h_pixels =>  800, h_front_porch =>  40, h_polarity => '1',
475
		v_pulse =>   4, v_back_porch =>  23, v_pixels =>  600, v_front_porch =>   1, v_polarity => '1');
476

477
	constant vga_1024x768: vga_configuration := (
478
		clock_frequency => 44_900_000,
479
		h_pulse => 176, h_back_porch =>  56, h_pixels => 1024, h_front_porch =>   8, h_polarity => '1',
480
		v_pulse => 8,   v_back_porch =>  41, v_pixels =>  800, v_front_porch =>   0, v_polarity => '1');
481

482
	constant vga_1920x1200: vga_configuration := (
483
		clock_frequency => 193_160_000,
484
		h_pulse => 208, h_back_porch => 336, h_pixels => 1920, h_front_porch => 128, h_polarity => '0',
485
		v_pulse => 3,   v_back_porch => 38,  v_pixels => 1200, v_front_porch =>   1, v_polarity => '1');
486

487
	component vga_controller is
488
	generic (
489
		g: common_generics;
490
		pixel_clock_frequency:  positive := 25_000_000;
491
		constant cfg: vga_configuration  := vga_640x480);
492
	port (
493
		clk, rst:          in std_ulogic;  -- pixel clock, must run at configured frequency
494
		h_sync, v_sync:   out std_ulogic;  -- sync pulses
495
		h_blank, v_blank: out std_ulogic;
496
		column, row:      out integer);   -- pixel coordinates
497
	end component;
498

499
	component vga_tb is
500
		generic (g: common_generics; pixel_clock_frequency: positive := 25_000_000; simulation_us: time := 20000 us);
501
	end component;
502

503
	constant led_7_segment_character_length: positive := 4;
504
	subtype led_7_segment_character is std_ulogic_vector(led_7_segment_character_length - 1 downto 0);
505
	subtype led_7_segment is std_ulogic_vector(7 downto 0);
506

507
	component led_7_segment_display is
508
		generic (g: common_generics;
509
			use_bcd_not_hex:         boolean := true;
510
			refresh_rate_us:         natural := 1500;
511
			number_of_led_displays: positive := 4);
512
		port (
513
			clk:      in   std_ulogic;
514
			rst:      in   std_ulogic;
515

516
			leds_we:  in   std_ulogic;
517
			leds:     in   std_ulogic_vector((number_of_led_displays * led_7_segment_character_length) - 1 downto 0);
518

519
			-- Physical outputs
520
			an:       out  std_ulogic_vector(number_of_led_displays - 1 downto 0);  -- anodes, controls on/off
521
			ka:       out  std_ulogic_vector(7 downto 0)); -- cathodes, data on display
522
	end component;
523

524
	component led_7_segment_display_tb is
525
		generic (g: common_generics);
526
	end component;
527

528
	component sine is
529
		generic (g: common_generics; pipeline: boolean := true);
530
		port (
531
			clk, rst, xwe: in std_ulogic;
532
			x:  in  std_ulogic_vector(15 downto 0);
533
			s:  out std_ulogic_vector(15 downto 0));
534
	end component;
535

536
	component cosine is
537
		generic (g: common_generics; pipeline: boolean := true);
538
		port (
539
			clk, rst, xwe: in std_ulogic;
540
			x:  in  std_ulogic_vector(15 downto 0);
541
			s:  out std_ulogic_vector(15 downto 0));
542
	end component;
543

544
	component sine_tb is
545
		generic (g: common_generics);
546
	end component;
547

548
	function max(a: natural; b: natural) return natural;
549
	function min(a: natural; b: natural) return natural;
550
	function reverse (a: in std_ulogic_vector) return std_ulogic_vector;
551
	function invert(slv:std_ulogic_vector) return std_ulogic_vector;
552
	function parity(slv:std_ulogic_vector; even: boolean) return std_ulogic;
553
	function parity(slv:std_ulogic_vector; even: std_ulogic) return std_ulogic;
554
	function or_reduce(slv:std_ulogic_vector) return std_ulogic;
555
	function and_reduce(slv:std_ulogic_vector) return std_ulogic;
556
	function select_bit(indexed, selector: std_ulogic_vector) return std_ulogic;
557
	function priority(order: std_ulogic_vector; high: boolean) return natural;
558
	function priority(order: std_ulogic_vector; high: boolean) return std_ulogic_vector;
559
	function mux(a: std_ulogic_vector; b: std_ulogic_vector; sel: std_ulogic) return std_ulogic_vector;
560
	function mux(a: std_ulogic; b: std_ulogic; sel: std_ulogic) return std_ulogic;
561
	function mux(a, b : std_ulogic_vector) return std_ulogic;
562
	function decode(encoded: std_ulogic_vector) return std_ulogic_vector;
563
	function to_std_ulogic_vector(s: string) return std_ulogic_vector;
564
	function logical(b: boolean) return std_ulogic;
565
	function bit_count_f(s: std_ulogic_vector) return integer;
566
	function hex_char_to_std_ulogic_vector_tb(hc: character) return std_ulogic_vector;
567

568
	type ulogic_string is array(integer range <>) of std_ulogic_vector(7 downto 0);
569
  	function to_std_ulogic_vector(s: string) return ulogic_string;
570

571
	-- synthesis translate_off
572
	subtype configuration_name is string(1 to 8);
573

574
	type configuration_item is record
575
		name:  configuration_name;
576
		value: integer;
577
	end record;
578

579
	type configuration_items is array(integer range <>) of configuration_item;
580

581
	function search_configuration_tb(find_me: configuration_name; ci: configuration_items) return integer;
582
	procedure read_configuration_tb(file_name:  string; ci: inout configuration_items);
583
	procedure write_configuration_tb(file_name: string; ci: configuration_items);
584
	-- synthesis translate_on
585
end;
586

587
package body util is
588

589
	function max(a: natural; b: natural) return natural is
590
	begin
591
		if (a > b) then return a; else return b; end if;
592
	end function;
593

594
	function min(a: natural; b: natural) return natural is
595
	begin
596
		if (a < b) then return a; else return b; end if;
597
	end function;
598

599
	function n_bits(x: natural) return natural is -- Not synthesizable
600
		variable x1: natural := max(x, 1) - 1;
601
		variable n:  natural := 1;
602
	begin
603
		while x1 > 1 loop
604
			x1 := x1 / 2;
605
			n  := n + 1;
606
		end loop;
607
		return n;
608
	end function;
609

610
	function n_bits(x: std_ulogic_vector) return natural is -- Not synthesizable
611
	begin
612
		return n_bits(x'high);
613
	end function;
614

615
	-- <https://stackoverflow.com/questions/13584307>
616
	function reverse (a: in std_ulogic_vector) return std_ulogic_vector is
617
		variable result: std_ulogic_vector(a'range);
618
		alias aa: std_ulogic_vector(a'reverse_range) is a;
619
	begin
620
		for i in aa'range loop
621
			result(i) := aa(i);
622
		end loop;
623
		return result;
624
	end;
625

626
	function invert(slv: std_ulogic_vector) return std_ulogic_vector is
627
		variable z: std_ulogic_vector(slv'range);
628
	begin
629
		for i in slv'range loop
630
			z(i) := not(slv(i));
631
		end loop;
632
		return z;
633
	end;
634

635
	function parity(slv: std_ulogic_vector; even: boolean) return std_ulogic is
636
		variable z: std_ulogic := '0';
637
	begin
638
		if not even then
639
			z := '1';
640
		end if;
641
		for i in slv'range loop
642
			z := z xor slv(i);
643
		end loop;
644
		return z;
645
	end;
646

647
	function parity(slv:std_ulogic_vector; even: std_ulogic) return std_ulogic is
648
		variable z: boolean := false;
649
	begin
650
		if even = '1' then
651
			z := true;
652
		end if;
653
		return parity(slv, z);
654
	end;
655

656
	function or_reduce(slv:std_ulogic_vector) return std_ulogic is
657
		variable z: std_ulogic := '0';
658
	begin
659
		for i in slv'range loop
660
			z := z or slv(i);
661
		end loop;
662
		return z;
663
	end;
664

665
	function and_reduce(slv:std_ulogic_vector) return std_ulogic is
666
		variable z: std_ulogic := '1';
667
	begin
668
		for i in slv'range loop
669
			z := z and slv(i);
670
		end loop;
671
		return z;
672
	end;
673

674
	function select_bit(indexed, selector: std_ulogic_vector) return std_ulogic is
675
		variable z: std_ulogic := 'X';
676
	begin
677
		assert n_bits(indexed) = selector'high + 1 severity failure;
678
		for i in indexed'range loop
679
			if i = to_integer(unsigned(selector)) then
680
				z := indexed(i);
681
			end if;
682
		end loop;
683
		return z;
684
	end;
685

686
	function priority(order: std_ulogic_vector; high: boolean) return natural is
687
		variable p: natural := 0;
688
	begin
689
		if not high then
690
			for i in order'high + 1 downto 1 loop
691
				if order(i-1) = '1' then
692
					p := i - 1;
693
				end if;
694
			end loop;
695
		else
696
			for i in 1 to order'high + 1 loop
697
				if order(i-1) = '1' then
698
					p := i - 1;
699
				end if;
700
			end loop;
701
		end if;
702
		return p;
703
	end;
704

705
	function priority(order: std_ulogic_vector; high: boolean) return std_ulogic_vector is
706
		variable length: natural := n_bits(order'length);
707
	begin
708
		return std_ulogic_vector(to_unsigned(priority(order, high), length));
709
	end;
710

711
	function mux(a: std_ulogic_vector; b: std_ulogic_vector; sel: std_ulogic) return std_ulogic_vector is
712
		variable m: std_ulogic_vector(a'range) := (others => 'X');
713
	begin
714
		if sel = '0' then m := a; else m := b; end if;
715
		return m;
716
	end;
717

718
	function mux(a: std_ulogic; b: std_ulogic; sel: std_ulogic) return std_ulogic is
719
		variable m: std_ulogic := 'X';
720
	begin
721
		if sel = '0' then m := a; else m := b; end if;
722
		return m;
723
	end;
724

725
	function mux(a, b : std_ulogic_vector) return std_ulogic is
726
		variable r: std_ulogic_vector(b'length - 1 downto 0) := (others => 'X');
727
		variable i: integer;
728
	begin
729
		r := b;
730
		i := to_integer(unsigned(a));
731
		return r(i);
732
	end;
733

734
	function decode(encoded : std_ulogic_vector) return std_ulogic_vector is
735
		variable r: std_ulogic_vector((2 ** encoded'length) - 1 downto 0) := (others => '0');
736
		variable i: natural;
737
	begin
738
		i    := to_integer(unsigned(encoded));
739
		r(i) := '1';
740
		return r;
741
	end;
742

743
	function logical(b: boolean) return std_ulogic is
744
	begin
745
		if b then return '1'; else return '0'; end if;
746
	end;
747

748
	function hex_char_to_std_ulogic_vector_tb(hc: character) return std_ulogic_vector is
749
		variable slv: std_ulogic_vector(3 downto 0);
750
	begin
751
		case hc is
752
		when '0' => slv := "0000";
753
		when '1' => slv := "0001";
754
		when '2' => slv := "0010";
755
		when '3' => slv := "0011";
756
		when '4' => slv := "0100";
757
		when '5' => slv := "0101";
758
		when '6' => slv := "0110";
759
		when '7' => slv := "0111";
760
		when '8' => slv := "1000";
761
		when '9' => slv := "1001";
762
		when 'A' => slv := "1010";
763
		when 'a' => slv := "1010";
764
		when 'B' => slv := "1011";
765
		when 'b' => slv := "1011";
766
		when 'C' => slv := "1100";
767
		when 'c' => slv := "1100";
768
		when 'D' => slv := "1101";
769
		when 'd' => slv := "1101";
770
		when 'E' => slv := "1110";
771
		when 'e' => slv := "1110";
772
		when 'F' => slv := "1111";
773
		when 'f' => slv := "1111";
774
		when others => slv := "XXXX";
775
		end case;
776
		assert (slv /= "XXXX") report " not a valid hex character: " & hc  severity failure;
777
		return slv;
778
	end;
779

780
	function bit_count_f(s : std_ulogic_vector) return integer is
781
		variable count: natural := 0;
782
	begin
783
		for i in s'range loop
784
			if s(i) = '1' then
785
				count := count + 1;
786
			end if;
787
		end loop;
788
		return count;
789
	end;
790

791
	-- <https://stackoverflow.com/questions/30519849/vhdl-convert-string-to-std-logic-vector>
792
	function to_std_ulogic_vector(s: string) return std_ulogic_vector is
793
	    variable ret: std_ulogic_vector(s'length*8-1 downto 0);
794
	begin
795
	    for i in s'range loop
796
		ret(i*8+7 downto i*8) := std_ulogic_vector(to_unsigned(character'pos(s(i)), 8));
797
	    end loop;
798
	    return ret;
799
	end;
800

801
	function to_std_ulogic_vector(s: string) return ulogic_string is
802
	    variable ret: ulogic_string(s'range);
803
	begin
804
		for i in s'range loop
805
			ret(i) := std_ulogic_vector(to_unsigned(character'pos(s(i)), 8));
806
		end loop;
807
		return ret;
808
	end;
809

810
	-- synthesis translate_off
811

812
	-- Find a string in a configuration items array, or returns -1 on
813
	-- failure to find the string.
814
	function search_configuration_tb(find_me: configuration_name; ci: configuration_items) return integer is
815
	begin
816
		for i in ci'range loop
817
			if ci(i).name = find_me then
818
				return i;
819
			end if;
820
		end loop;
821
		return -1;
822
	end;
823

824
	-- VHDL provides quite a limited set of options for dealing with
825
	-- operations that are not synthesizeable but would be useful for
826
	-- in test benches. This method provides a crude way of reading
827
	-- in configurable options. It has a very strict format.
828
	--
829
	-- The format is line oriented, it expects a string on a line
830
	-- with a length equal to the "configuration_name" type, which
831
	-- is a subtype of "string". It finds the corresponding record
832
	-- in configuration_items if it exists. It then reads in an
833
	-- integer from the next line and sets the record for it.
834
	--
835
	-- Any deviation from this format causes an error and the simulation
836
	-- to halt, whilst not a good practice to do error checking with asserts
837
	-- there is no better way in VHDL in this case. The only sensible
838
	-- action on an error would for the configuration file to be fixed
839
	-- anyway.
840
	--
841
	-- Comment lines and variable length strings would be nice, but
842
	-- are too much of a hassle.
843
	--
844
	-- The configuration function only deal with part of the configuration
845
	-- process, it does not deal with deserialization into structures
846
	-- more useful to the user - like into individual signals.
847
	--
848
	procedure read_configuration_tb(file_name: string; ci: inout configuration_items) is
849
		file     in_file: text is in file_name;
850
		variable in_line: line;
851
		variable d:       integer;
852
		variable s:       configuration_name;
853
		variable index:   integer;
854
	begin
855
		while not endfile(in_file) loop
856

857
			readline(in_file, in_line);
858
			read(in_line, s);
859
			index := search_configuration_tb(s, ci);
860

861
			assert index >= 0 report "Unknown configuration item: " & s severity failure;
862

863
			readline(in_file, in_line);
864
			read(in_line, d);
865

866
			ci(index).value := d;
867

868
			report "Config Item: '" & ci(index).name & "' = " & integer'image(ci(index).value);
869
		end loop;
870
		file_close(in_file);
871
	end procedure;
872

873
	procedure write_configuration_tb(file_name: string; ci: configuration_items) is
874
		file     out_file: text is out file_name;
875
		variable out_line: line;
876
	begin
877
		for i in ci'range loop
878
			write(out_line, ci(i).name);
879
			writeline(out_file, out_line);
880
			write(out_line, ci(i).value);
881
			writeline(out_file, out_line);
882
		end loop;
883
	end procedure;
884

885
	-- synthesis translate_on
886
end;
887

888
------------------------- Utility Test Bench ----------------------------------------
889
library ieee, work;
890
use ieee.std_logic_1164.all;
891
use work.util.all;
892

893
entity util_tb is
894
	generic (g: common_generics);
895
end entity;
896

897
architecture behav of util_tb is
898
begin
899
	-- The "io_pins_tb" works correctly, however in GHDL 0.29, compiled under
900
	-- Windows, fails to simulate this component correctly, resulting
901
	-- in a crash. This does not affect the Linux build of GHDL. It has
902
	-- something to do with 'Z' values for std_logic types.
903
	uut_io_pins:  work.util.io_pins_tb              generic map (g => g);
904
	uut_timer_us: work.util.timer_us_tb             generic map (g => g);
905
	uut_full_add: work.util.full_adder_tb           generic map (g => g);
906
	uut_fifo:     work.util.fifo_tb                 generic map (g => g);
907
	uut_counter:  work.util.counter_tb              generic map (g => g);
908
	uut_ucpu:     work.util.ucpu_tb                 generic map (g => g);
909
	uut_rdivider: work.util.restoring_divider_tb    generic map (g => g);
910
	uut_debounce: work.util.debounce_us_tb          generic map (g => g);
911
	uut_rst_gen:  work.util.reset_generator_tb      generic map (g => g);
912
	uut_bit_cnt:  work.util.bit_count_tb            generic map (g => g);
913
	uut_majority: work.util.majority_tb             generic map (g => g);
914
	uut_delay_ln: work.util.delay_line_tb           generic map (g => g);
915
	uut_rising:   work.util.rising_edge_detector_tb generic map (g => g);
916
	uut_shiftReg: work.util.shift_register_tb       generic map (g => g);
917
	uut_lfsr:     work.util.lfsr_tb                 generic map (g => g);
918
	uut_gray:     work.util.gray_tb                 generic map (g => g);
919
	uut_ham:      work.util.hamming_7_4_tb          generic map (g => g); -- Oink!
920
	uut_vga:      work.util.vga_tb                  generic map (g => g, simulation_us => 1 us);
921
	uut_sine:     work.util.sine_tb                 generic map (g => g);
922
	uut_7_seg:   work.util.led_7_segment_display_tb generic map (g => g);
923

924
	stimulus_process: process
925
	begin
926
		assert max(5, 4)                 =  5      severity failure;
927
		assert work.util.min(5, 4)       =  4      severity failure;
928
		assert n_bits(1)                 =  1      severity failure;
929
		assert n_bits(2)                 =  1      severity failure;
930
		assert n_bits(7)                 =  3      severity failure;
931
		assert n_bits(8)                 =  3      severity failure;
932
		assert n_bits(9)                 =  4      severity failure;
933
		assert reverse("1")              =  "1"    severity failure;
934
		assert reverse("0")              =  "0"    severity failure;
935
		assert reverse("10")             =  "01"   severity failure;
936
		assert reverse("11")             =  "11"   severity failure;
937
		assert reverse("0101")           =  "1010" severity failure;
938
		assert invert("1")               =  "0"    severity failure;
939
		assert invert("0")               =  "1"    severity failure;
940
		assert invert("0101")            =  "1010" severity failure;
941
		assert select_bit("01000", "01") =  '1'    severity failure;
942
		assert parity("0", true)         =  '0'    severity failure;
943
		assert parity("1", true)         =  '1'    severity failure;
944
		assert parity("11", true)        =  '0'    severity failure;
945
		assert parity("1010001", true)   =  '1'    severity failure;
946
		assert parity("0", false)        =  '1'    severity failure;
947
		assert parity("1", false)        =  '0'    severity failure;
948
		assert parity("11", false)       =  '1'    severity failure;
949
		assert parity("1010001", false)  =  '0'    severity failure;
950
		assert or_reduce("0000")         =  '0'    severity failure;
951
		assert or_reduce("0")            =  '0'    severity failure;
952
		assert or_reduce("1")            =  '1'    severity failure;
953
		assert or_reduce("11")           =  '1'    severity failure;
954
		assert or_reduce("10")           =  '1'    severity failure;
955
		assert or_reduce("01")           =  '1'    severity failure;
956
		assert and_reduce("01")          =  '0'    severity failure;
957
		assert and_reduce("11")          =  '1'    severity failure;
958
		assert and_reduce("1")           =  '1'    severity failure;
959
		assert and_reduce("0")           =  '0'    severity failure;
960
		assert and_reduce("10")          =  '0'    severity failure;
961
		assert priority("01001", false)  =  1      severity failure;
962
		assert mux("1010", "0101", '0')  =  "1010" severity failure;
963
		assert mux("1010", "0101", '1')  =  "0101" severity failure;
964
		assert decode("00")              =  "0001" severity failure;
965
		assert decode("01")              =  "0010" severity failure;
966
		assert decode("10")              =  "0100" severity failure;
967
		assert decode("11")              =  "1000" severity failure;
968
		wait;
969
	end process;
970
end architecture;
971

972
------------------------- Function Test Bench ---------------------------------------
973

974
------------------------- Test bench clock source -----------------------------------
975

976
library ieee, work;
977
use ieee.std_logic_1164.all;
978
use ieee.numeric_std.all;
979
use ieee.math_real.all;
980
use work.util.common_generics;
981

982
entity clock_source_tb is
983
	generic (g: common_generics; hold_rst: positive);
984
	port (
985
		stop:            in     std_ulogic := '0';
986
		clk:             out    std_ulogic;
987
		clk_with_jitter: out    std_ulogic := '0';
988
		rst:             out    std_ulogic := '0');
989
end entity;
990

991
architecture rtl of clock_source_tb is
992
	constant clock_period: time      :=  1000 ms / g.clock_frequency;
993
	signal jitter_delay:   time      := 0 ns;
994
	signal jitter_clk:     std_ulogic := '0';
995
begin
996
	jitter_clk_process: process
997
		variable seed1, seed2: positive;
998
		variable r: real;
999
		variable jit_high, jit_low: time  := 0 ns;
1000
	begin
1001
		while stop = '0' loop
1002
			uniform(seed1, seed2, r);
1003
			jit_high := r * g.delay;
1004
			uniform(seed1, seed2, r);
1005
			jit_low := r * g.delay;
1006
			uniform(seed1, seed2, r);
1007
			if r < 0.5 then jit_high := -jit_high; end if;
1008
			uniform(seed1, seed2, r);
1009
			if r < 0.5 then jit_low := -jit_low; end if;
1010
			clk_with_jitter <= '1';
1011
			wait for (clock_period / 2) + jit_high;
1012
			clk_with_jitter <= '0';
1013
			wait for (clock_period / 2) + jit_low;
1014
		end loop;
1015
		wait;
1016
	end process;
1017

1018
	clk_process: process
1019
	begin
1020
		while stop = '0' loop
1021
			clk <= '1';
1022
			wait for clock_period / 2;
1023
			clk <= '0';
1024
			wait for clock_period / 2;
1025
		end loop;
1026
		wait;
1027
	end process;
1028

1029
	rst_process: process
1030
	begin
1031
		rst <= '1';
1032
		wait for clock_period * hold_rst;
1033
		rst <= '0';
1034
		wait;
1035
	end process;
1036

1037
end architecture;
1038

1039
------------------------- Generic Register of std_ulogic_vector ----------------------
1040

1041
library ieee, work;
1042
use ieee.std_logic_1164.all;
1043
use ieee.numeric_std.all;
1044
use work.util.common_generics;
1045

1046
entity reg is
1047
	generic (g: common_generics; N: positive);
1048
	port (
1049
		clk: in  std_ulogic;
1050
		rst: in  std_ulogic;
1051
		we:  in  std_ulogic;
1052
		di:  in  std_ulogic_vector(N - 1 downto 0);
1053
		do:  out std_ulogic_vector(N - 1 downto 0));
1054
end entity;
1055

1056
architecture rtl of reg is
1057
	signal r_c, r_n: std_ulogic_vector(N - 1 downto 0) := (others => '0');
1058
begin
1059
	do <= r_c after g.delay;
1060

1061
	process(rst, clk)
1062
	begin
1063
		if rst = '1' and g.asynchronous_reset then
1064
			r_c <= (others => '0') after g.delay;
1065
		elsif rising_edge(clk) then
1066
			if rst = '1' and not g.asynchronous_reset then
1067
				r_c <= (others => '0') after g.delay;
1068
			else
1069
				r_c <= r_n after g.delay;
1070
			end if;
1071
		end if;
1072
	end process;
1073

1074
	process(r_c, di, we)
1075
	begin
1076
		if we = '1' then
1077
			r_n <= di after g.delay;
1078
		else
1079
			r_n <= r_c after g.delay;
1080
		end if;
1081
	end process;
1082
end;
1083

1084
------------------------- Generic Register of std_ulogic_vector ----------------------
1085

1086
------------------------- Shift register --------------------------------------------
1087
library ieee, work;
1088
use ieee.std_logic_1164.all;
1089
use work.util.common_generics;
1090

1091
-- https://stackoverflow.com/questions/36342960/optional-ports-in-vhdl
1092
entity shift_register is
1093
	generic (g: common_generics; N: positive);
1094
	port (
1095
		clk:     in  std_ulogic;
1096
		rst:     in  std_ulogic;
1097
		we:      in  std_ulogic;
1098
		di:      in  std_ulogic;
1099
		do:      out std_ulogic;
1100

1101
		-- optional
1102
		load_we: in  std_ulogic := '0';
1103
		load_i:  in  std_ulogic_vector(N - 1 downto 0) := (others => '0');
1104
		load_o:  out std_ulogic_vector(N - 1 downto 0));
1105
end entity;
1106

1107
architecture rtl of shift_register is
1108
	signal r_c, r_n : std_ulogic_vector(N - 1 downto 0) := (others => '0');
1109
begin
1110
	do     <= r_c(0);
1111
	load_o <= r_c;
1112

1113
	process(rst, clk)
1114
	begin
1115
		if rst = '1' and g.asynchronous_reset then
1116
			r_c <= (others => '0') after g.delay;
1117
		elsif rising_edge(clk) then
1118
			if rst = '1' and not g.asynchronous_reset then
1119
				r_c <= (others => '0') after g.delay;
1120
			else
1121
				r_c <= r_n after g.delay;
1122
			end if;
1123
		end if;
1124
	end process;
1125

1126
	process(r_c, di, we, load_i, load_we)
1127
	begin
1128
		if load_we = '1' then
1129
			r_n <= load_i after g.delay;
1130
		else
1131
			r_n <= "0" & r_c(N - 1 downto 1) after g.delay;
1132
			if we = '1' then
1133
				r_n(N-1) <= di after g.delay;
1134
			end if;
1135
		end if;
1136
	end process;
1137
end;
1138

1139
library ieee, work;
1140
use ieee.std_logic_1164.all;
1141
use work.util.common_generics;
1142

1143
entity shift_register_tb is
1144
	generic (g: common_generics);
1145
end entity;
1146

1147
architecture behav of shift_register_tb is
1148
	constant N: positive := 8;
1149
	constant clock_period: time :=  1000 ms / g.clock_frequency;
1150
	signal we: std_ulogic := '0';
1151
	signal di: std_ulogic := '0';
1152
	signal do: std_ulogic := '0';
1153

1154
	signal clk, rst: std_ulogic := '0';
1155
	signal stop: std_ulogic := '0';
1156
begin
1157
	cs: entity work.clock_source_tb
1158
		generic map (g => g, hold_rst => 2)
1159
		port map (stop => stop, clk => clk, rst => rst);
1160

1161
	uut: entity work.shift_register
1162
	generic map (g => g, N => N) port map (clk => clk, rst => rst, we => we, di => di, do => do);
1163

1164
	stimulus_process: process
1165
	begin
1166
		-- Put a bit into the shift register and wait
1167
		-- for it to come out the other size.
1168
		wait until rst = '0';
1169
		di <= '1';
1170
		we <= '1';
1171
		wait for clock_period;
1172
		di <= '0';
1173
		we <= '0';
1174
		for I in 0 to 7 loop
1175
			assert do = '0' report "bit appeared to quickly";
1176
			wait for clock_period;
1177
		end loop;
1178
		assert do = '1' report "bit disappeared in shift register";
1179
		wait for clock_period * 1;
1180
		assert do = '0' report "extra bit set in shift register";
1181
		stop <= '1';
1182
		wait;
1183
	end process;
1184
end;
1185
------------------------- Shift register --------------------------------------------
1186

1187
------------------------- Microsecond Timer -----------------------------------------
1188
library ieee, work;
1189
use ieee.std_logic_1164.all;
1190
use ieee.numeric_std.all;
1191
use work.util.max;
1192
use work.util.n_bits;
1193
use work.util.common_generics;
1194

1195
entity timer_us is
1196
	generic (g: common_generics; timer_period_us: natural);
1197
	port (
1198
		clk: in  std_ulogic;
1199
		rst: in  std_ulogic;
1200
		co:  out std_ulogic);
1201
end timer_us;
1202

1203
architecture rtl of timer_us is
1204
	constant cycles:   natural := (g.clock_frequency / 1000000) * timer_period_us;
1205
	subtype  counter is unsigned(max(1, n_bits(cycles) - 1) downto 0);
1206
	signal   c_c, c_n: counter := (others => '0');
1207
begin
1208
	process (clk, rst)
1209
	begin
1210
		if rst = '1' and g.asynchronous_reset then
1211
			c_c <= (others => '0') after g.delay;
1212
		elsif rising_edge(clk) then
1213
			if rst = '1' and not g.asynchronous_reset then
1214
				c_c <= (others => '0') after g.delay;
1215
			else
1216
				c_c <= c_n after g.delay;
1217
			end if;
1218
		end if;
1219
	end process;
1220

1221
	process (c_c)
1222
	begin
1223
		if c_c = (cycles - 1) then
1224
			c_n <= (others => '0') after g.delay;
1225
			co  <= '1' after g.delay;
1226
		else
1227
			c_n <= c_c + 1 after g.delay;
1228
			co  <= '0' after g.delay;
1229
		end if;
1230
	end process;
1231
end;
1232

1233
library ieee, work;
1234
use ieee.std_logic_1164.all;
1235
use ieee.numeric_std.all;
1236
use work.util.common_generics;
1237

1238
entity timer_us_tb is
1239
	generic (g: common_generics);
1240
end;
1241

1242
architecture behav of timer_us_tb is
1243
	constant clock_period: time := 1000 ms / g.clock_frequency;
1244
	signal co: std_ulogic        := 'X';
1245
	signal clk, rst: std_ulogic  := '0';
1246
	signal stop: std_ulogic      := '0';
1247
begin
1248
	cs: entity work.clock_source_tb
1249
		generic map (g => g, hold_rst => 2)
1250
		port map (stop => stop, clk => clk, rst => rst);
1251

1252
	uut: entity work.timer_us
1253
		generic map (g => g, timer_period_us => 1)
1254
		port map (clk => clk, rst => rst, co => co);
1255

1256
	stimulus_process: process
1257
	begin
1258
		wait for 1 us;
1259
		assert co = '0' severity failure;
1260
		wait for clock_period;
1261
		assert co = '1' severity failure;
1262
		stop <= '1';
1263
		wait;
1264
	end process;
1265
end;
1266

1267
------------------------- Microsecond Timer -----------------------------------------
1268

1269
------------------------- Rising Edge Detector --------------------------------------
1270
library ieee, work;
1271
use ieee.std_logic_1164.all;
1272
use work.util.common_generics;
1273

1274
entity rising_edge_detector is
1275
	generic (g: common_generics);
1276
	port (
1277
		clk:    in  std_ulogic;
1278
		rst:    in  std_ulogic;
1279
		di:     in  std_ulogic;
1280
		do:     out std_ulogic);
1281
end;
1282

1283
architecture rtl of rising_edge_detector is
1284
	signal sin_0: std_ulogic := '0';
1285
	signal sin_1: std_ulogic := '0';
1286
begin
1287
	red: process(clk, rst)
1288
	begin
1289
		if rst = '1' and g.asynchronous_reset then
1290
			sin_0 <= '0' after g.delay;
1291
			sin_1 <= '0' after g.delay;
1292
		elsif rising_edge(clk) then
1293
			if rst = '1' and not g.asynchronous_reset then
1294
				sin_0 <= '0' after g.delay;
1295
				sin_1 <= '0' after g.delay;
1296
			else
1297
				sin_0 <=    di after g.delay;
1298
				sin_1 <= sin_0 after g.delay;
1299
			end if;
1300
		end if;
1301
	end process;
1302
	do <= not sin_1 and sin_0;
1303
end architecture;
1304

1305
library ieee, work;
1306
use ieee.std_logic_1164.all;
1307
use work.util.common_generics;
1308

1309
entity rising_edge_detector_tb is
1310
	generic (g: common_generics);
1311
end;
1312

1313
architecture behav of rising_edge_detector_tb is
1314
	constant clock_period: time := 1000 ms / g.clock_frequency;
1315
	signal di:  std_ulogic := '0';
1316
	signal do: std_ulogic := 'X';
1317

1318
	signal clk, rst: std_ulogic := '0';
1319
	signal stop: std_ulogic := '0';
1320
begin
1321
	cs: entity work.clock_source_tb
1322
		generic map (g => g, hold_rst => 2)
1323
		port map (stop => stop, clk => clk, rst => rst);
1324

1325
	uut: entity work.rising_edge_detector
1326
		generic map (g => g)
1327
		port map (clk => clk, rst => rst, di => di, do => do);
1328

1329
	stimulus_process: process
1330
	begin
1331
		wait for clock_period * 5;
1332
		assert do = '0' severity failure;
1333
		wait for clock_period;
1334
		di <= '1';
1335
		wait for clock_period * 0.5;
1336
		assert do = '1' severity failure;
1337
		wait for clock_period * 1.5;
1338
		di <= '0';
1339
		assert do = '0' severity failure;
1340
		wait for clock_period;
1341
		assert do = '0' severity failure;
1342

1343
		assert stop = '0' report "Test bench not run to completion";
1344
		stop <= '1';
1345
		wait;
1346
	end process;
1347
end architecture;
1348

1349
library ieee, work;
1350
use ieee.std_logic_1164.all;
1351
use work.util.common_generics;
1352

1353
entity rising_edge_detectors is
1354
	generic (g: common_generics; N: positive);
1355
	port (
1356
		clk:    in  std_ulogic;
1357
		rst:    in  std_ulogic;
1358
		di:     in  std_ulogic_vector(N - 1 downto 0);
1359
		do:     out std_ulogic_vector(N - 1 downto 0));
1360
end entity;
1361

1362
architecture structural of rising_edge_detectors is
1363
begin
1364
	changes: for i in N - 1 downto 0 generate
1365
		d_instance: work.util.rising_edge_detector
1366
			generic map (g => g)
1367
			port map (clk => clk, rst => rst, di => di(i), do => do(i));
1368
	end generate;
1369
end architecture;
1370

1371
------------------------- Rising Edge Detector --------------------------------------
1372

1373
------------------------- Half Adder ------------------------------------------------
1374
library ieee, work;
1375
use ieee.std_logic_1164.all;
1376
use work.util.common_generics;
1377

1378
entity half_adder is
1379
	generic (g: common_generics);
1380
	port (
1381
		a:     in  std_ulogic;
1382
		b:     in  std_ulogic;
1383
		sum:   out std_ulogic;
1384
		carry: out std_ulogic);
1385
end entity;
1386

1387
architecture rtl of half_adder is
1388
begin
1389
	sum   <= a xor b after g.delay;
1390
	carry <= a and b after g.delay;
1391
end architecture;
1392

1393
------------------------- Half Adder ------------------------------------------------
1394

1395
------------------------- Full Adder ------------------------------------------------
1396

1397
library ieee, work;
1398
use ieee.std_logic_1164.all;
1399
use work.util.common_generics;
1400

1401
entity full_adder is
1402
	generic (g: common_generics);
1403
	port (
1404
		x:     in    std_ulogic;
1405
		y:     in    std_ulogic;
1406
		z:     in    std_ulogic;
1407
		sum:   out   std_ulogic;
1408
		carry: out   std_ulogic);
1409
end entity;
1410

1411
architecture rtl of full_adder is
1412
	signal carry1, carry2, sum1: std_ulogic;
1413
begin
1414
	ha1: entity work.half_adder generic map (g => g) port map (a => x,    b => y, sum => sum1, carry => carry1);
1415
	ha2: entity work.half_adder generic map (g => g) port map (a => sum1, b => z, sum => sum,  carry => carry2);
1416
	carry <= carry1 or carry2 after g.delay;
1417
end architecture;
1418

1419
library ieee, work;
1420
use ieee.std_logic_1164.all;
1421
use work.util.common_generics;
1422

1423
entity full_adder_tb is
1424
	generic (g: common_generics);
1425
end entity;
1426

1427
architecture behav of full_adder_tb is
1428
	constant clock_period: time  := 1000 ms / g.clock_frequency;
1429
	signal x, y, z:    std_ulogic := '0';
1430
	signal sum, carry: std_ulogic := '0';
1431

1432
	type stimulus_data   is array (0 to 7)              of std_ulogic_vector(2 downto 0);
1433
	type stimulus_result is array (stimulus_data'range) of std_ulogic_vector(0 to     1);
1434

1435
	constant data: stimulus_data := (
1436
		0 => "000", 1 => "001",
1437
		2 => "010", 3 => "011",
1438
		4 => "100", 5 => "101",
1439
		6 => "110", 7 => "111");
1440

1441
	constant result: stimulus_result := (
1442
		0 => "00",  1 => "10",
1443
		2 => "10",  3 => "01",
1444
		4 => "10",  5 => "01",
1445
		6 => "01",  7 => "11");
1446

1447
	signal clk, rst: std_ulogic := '0';
1448
	signal stop: std_ulogic     := '0';
1449
begin
1450
	cs: entity work.clock_source_tb
1451
		generic map (g => g, hold_rst => 2)
1452
		port map (stop => stop, clk => clk, rst => rst);
1453

1454
	uut: entity work.full_adder
1455
		generic map (g => g)
1456
		port map (x => x, y => y, z => z, sum => sum, carry => carry);
1457

1458
	stimulus_process: process
1459
	begin
1460
		wait for clock_period;
1461
		for i in data'range loop
1462
			x <= data(i)(0);
1463
			y <= data(i)(1);
1464
			z <= data(i)(2);
1465
			wait for clock_period;
1466
			assert sum = result(i)(0) and carry = result(i)(1)
1467
				report
1468
					"For: "       & std_ulogic'image(x) & std_ulogic'image(y) & std_ulogic'image(z) &
1469
					" Got: "      & std_ulogic'image(sum)          & std_ulogic'image(carry) &
1470
					" Expected: " & std_ulogic'image(result(i)(0)) & std_ulogic'image(result(i)(1))
1471
				severity failure;
1472
			wait for clock_period;
1473
		end loop;
1474

1475
		stop <= '1';
1476
		wait;
1477
	end process;
1478
end architecture;
1479

1480
------------------------- Full Adder ------------------------------------------------
1481

1482
------------------------- FIFO ------------------------------------------------------
1483
library ieee, work;
1484
use ieee.std_logic_1164.all;
1485
use ieee.numeric_std.all;
1486
use work.util.common_generics;
1487

1488
entity fifo is
1489
	generic (g: common_generics;
1490
		data_width: positive;
1491
		fifo_depth: positive;
1492
		read_first: boolean := true);
1493
	port (
1494
		clk:   in  std_ulogic;
1495
		rst:   in  std_ulogic;
1496
		di:    in  std_ulogic_vector(data_width - 1 downto 0);
1497
		we:    in  std_ulogic;
1498
		re:    in  std_ulogic;
1499
		do:    out std_ulogic_vector(data_width - 1 downto 0);
1500

1501
		-- optional
1502
		full:  out std_ulogic := '0';
1503
		empty: out std_ulogic := '1');
1504
end fifo;
1505

1506
architecture behavior of fifo is
1507
	type fifo_data_t is array (0 to fifo_depth - 1) of std_ulogic_vector(di'range);
1508
	signal data: fifo_data_t := (others => (others => '0'));
1509
	function rindex_init return integer is
1510
	begin
1511
		if read_first then
1512
			return 0;
1513
		end if;
1514
		return fifo_depth - 1;
1515
	end function;
1516

1517
	signal count:  integer range 0 to fifo_depth := 0;
1518
	signal windex: integer range 0 to fifo_depth - 1 := 0;
1519
	signal rindex: integer range 0 to fifo_depth - 1 := rindex_init;
1520

1521
	signal is_full:  std_ulogic := '0';
1522
	signal is_empty: std_ulogic := '1';
1523
begin
1524
	do       <= data(rindex) after g.delay;
1525
	full     <= is_full after g.delay;  -- buffer these bad boys
1526
	empty    <= is_empty after g.delay;
1527
	is_full  <= '1' when count = fifo_depth else '0' after g.delay;
1528
	is_empty <= '1' when count = 0          else '0' after g.delay;
1529

1530
	process (rst, clk) is
1531
	begin
1532
		if rst = '1' and g.asynchronous_reset then
1533
			windex <= 0 after g.delay;
1534
			count  <= 0 after g.delay;
1535
			rindex <= rindex_init after g.delay;
1536
		elsif rising_edge(clk) then
1537
			if rst = '1' and not g.asynchronous_reset then
1538
				windex <= 0 after g.delay;
1539
				count  <= 0 after g.delay;
1540
				rindex <= rindex_init after g.delay;
1541
			else
1542
				if we = '1' and re = '0' then
1543
					if is_full = '0' then
1544
						count <= count + 1 after g.delay;
1545
					end if;
1546
				elsif we = '0' and re = '1' then
1547
					if is_empty = '0' then
1548
						count <= count - 1 after g.delay;
1549
					end if;
1550
				end if;
1551

1552
				if re = '1' and is_empty = '0' then
1553
					if rindex = (fifo_depth - 1) then
1554
						rindex <= 0 after g.delay;
1555
					else
1556
						rindex <= rindex + 1 after g.delay;
1557
					end if;
1558
				end if;
1559

1560
				if we = '1' and is_full = '0' then
1561
					if windex = (fifo_depth - 1) then
1562
						windex <= 0 after g.delay;
1563
					else
1564
						windex <= windex + 1 after g.delay;
1565
					end if;
1566
					data(windex) <= di after g.delay;
1567
				end if;
1568
			end if;
1569
		end if;
1570
	end process;
1571
end behavior;
1572

1573
library ieee, work;
1574
use ieee.std_logic_1164.all;
1575
use ieee.numeric_std.all;
1576
use work.util.common_generics;
1577

1578
entity fifo_tb is
1579
	generic (g: common_generics);
1580
end entity;
1581

1582
architecture behavior of fifo_tb is
1583
	constant clock_period: time  := 1000 ms / g.clock_frequency;
1584
	constant data_width: positive := 8;
1585
	constant fifo_depth: positive := 16;
1586

1587
	signal di:       std_ulogic_vector(data_width - 1 downto 0) := (others => '0');
1588
	signal re:       std_ulogic := '0';
1589
	signal we:       std_ulogic := '0';
1590

1591
	signal do:       std_ulogic_vector(data_width - 1 downto 0) := (others => '0');
1592
	signal empty:    std_ulogic := '0';
1593
	signal full:     std_ulogic := '0';
1594

1595
	signal clk, rst: std_ulogic := '0';
1596
	signal stop_w:   std_ulogic := '0';
1597
	signal stop_r:   std_ulogic := '0';
1598
	signal stop:     std_ulogic := '0';
1599
begin
1600
	cs: entity work.clock_source_tb
1601
		generic map (g => g, hold_rst => 2)
1602
		port map (stop => stop, clk => clk, rst => rst);
1603

1604
	stop <= '1' when stop_w = '1' and stop_r = '1' else '0';
1605

1606
	uut: entity work.fifo
1607
		generic map (g => g, data_width => data_width, fifo_depth => fifo_depth)
1608
		port map (
1609
			clk   => clk,
1610
			rst   => rst,
1611
			di    => di,
1612
			we    => we,
1613
			re    => re,
1614
			do    => do,
1615
			full  => full,
1616
			empty => empty);
1617

1618
	write_process: process
1619
		variable counter: unsigned (data_width - 1 downto 0) := (others => '0');
1620
	begin
1621
		wait for clock_period * 20;
1622

1623
		for i in 1 to 32 loop
1624
			counter := counter + 1;
1625
			di <= std_ulogic_vector(counter);
1626
			wait for clock_period * 1;
1627
			we <= '1';
1628
			wait for clock_period * 1;
1629
			we <= '0';
1630
		end loop;
1631

1632
		wait for clock_period * 20;
1633

1634
		for i in 1 to 32 loop
1635
			counter := counter + 1;
1636
			di <= std_ulogic_vector(counter);
1637
			wait for clock_period * 1;
1638
			we <= '1';
1639
			wait for clock_period * 1;
1640
			we <= '0';
1641
		end loop;
1642

1643
		stop_w <= '1';
1644
		wait;
1645
	end process;
1646

1647
	read_process: process
1648
	begin
1649
		wait for clock_period * 60;
1650
		re <= '1';
1651
		wait for clock_period * 60;
1652
		re <= '0';
1653
		wait for clock_period * 256 * 2;
1654
		re <= '1';
1655

1656
		stop_r <= '1';
1657
		wait;
1658
	end process;
1659
end architecture;
1660

1661
------------------------- FIFO ------------------------------------------------------
1662

1663
------------------------- Free running counter --------------------------------------
1664

1665
library ieee, work;
1666
use ieee.std_logic_1164.all;
1667
use ieee.numeric_std.all;
1668
use work.util.common_generics;
1669

1670
entity counter is
1671
	generic (g: common_generics;
1672
		N:                    positive);
1673
	port (
1674
		clk:     in  std_ulogic;
1675
		rst:     in  std_ulogic;
1676
		ce:      in  std_ulogic;
1677
		cr:      in  std_ulogic;
1678
		dout:    out std_ulogic_vector(N - 1 downto 0);
1679

1680
		-- optional
1681
		load_we: in  std_ulogic := '0';
1682
		load_i:  in  std_ulogic_vector(N - 1 downto 0) := (others => '0'));
1683
end entity;
1684

1685
architecture rtl of counter is
1686
	signal c_c, c_n: unsigned(N - 1 downto 0) := (others => '0');
1687
begin
1688
	dout <= std_ulogic_vector(c_c) after g.delay;
1689

1690
	process(clk, rst)
1691
	begin
1692
		if rst = '1' and g.asynchronous_reset then
1693
			c_c <= (others => '0') after g.delay;
1694
		elsif rising_edge(clk) then
1695
			if rst = '1' and not g.asynchronous_reset then
1696
				c_c <= (others => '0') after g.delay;
1697
			else
1698
				c_c <= c_n after g.delay;
1699
			end if;
1700
		end if;
1701
	end process;
1702

1703
	process(c_c, cr, ce, load_we, load_i)
1704
	begin
1705
		c_n <= c_c;
1706
		if load_we = '1' then
1707
			c_n <= unsigned(load_i) after g.delay;
1708
		else
1709
			if cr = '1' then
1710
				c_n <= (others => '0') after g.delay;
1711
			elsif ce = '1' then
1712
				c_n <= c_c + 1 after g.delay;
1713
			end if;
1714
		end if;
1715
	end process;
1716

1717
end architecture;
1718

1719
library ieee, work;
1720
use ieee.std_logic_1164.all;
1721
use ieee.numeric_std.all;
1722
use work.util.common_generics;
1723

1724
entity counter_tb is
1725
	generic (g: common_generics);
1726
end entity;
1727

1728
architecture behavior of counter_tb is
1729
	constant clock_period: time     := 1000 ms / g.clock_frequency;
1730
	constant length:       positive := 2;
1731

1732
	-- inputs
1733
	signal ce: std_ulogic := '0';
1734
	signal cr: std_ulogic := '0';
1735

1736
	-- outputs
1737
	signal dout: std_ulogic_vector(length - 1 downto 0);
1738

1739
	-- test data
1740
	type stimulus_data   is array (0 to 16)             of std_ulogic_vector(1 downto 0);
1741
	type stimulus_result is array (stimulus_data'range) of std_ulogic_vector(0 to     1);
1742

1743
	constant data: stimulus_data := (
1744
		 0 => "00",  1 => "00",
1745
		 2 => "01",  3 => "01",
1746
		 4 => "00",  5 => "00",
1747
		 6 => "10",  7 => "00",
1748
		 8 => "01",  9 => "01",
1749
		10 => "11", 11 => "00",
1750
		12 => "01", 13 => "01",
1751
		14 => "01", 15 => "01",
1752
		16 => "01");
1753

1754
	constant result: stimulus_result := (
1755
		 0 => "00",  1 => "00",
1756
		 2 => "00",  3 => "01",
1757
		 4 => "10",  5 => "10",
1758
		 6 => "10",  7 => "00",
1759
		 8 => "00",  9 => "01",
1760
		10 => "10", 11 => "00",
1761
		12 => "00", 13 => "01",
1762
		14 => "10", 15 => "11",
1763
		16 => "00");
1764

1765
	signal clk, rst: std_ulogic := '0';
1766
	signal stop:     std_ulogic := '0';
1767
begin
1768
	cs: entity work.clock_source_tb
1769
		generic map (g => g, hold_rst => 2)
1770
		port map (stop => stop, clk => clk, rst => rst);
1771

1772
	uut: entity work.counter
1773
		generic map (g => g, N => length)
1774
		port map (
1775
			clk   => clk,
1776
			rst   => rst,
1777
			ce    => ce,
1778
			cr    => cr,
1779
			dout  => dout);
1780

1781
	stimulus_process: process
1782
	begin
1783
		wait for clock_period;
1784
		for i in data'range loop
1785
			ce <= data(i)(0);
1786
			cr <= data(i)(1);
1787
			wait for clock_period;
1788
			assert dout = result(i)
1789
				report
1790
					"For: ce("    & std_ulogic'image(ce) & ") cr(" & std_ulogic'image(cr) & ") " &
1791
					" Got: "      & integer'image(to_integer(unsigned(dout))) &
1792
					" Expected: " & integer'image(to_integer(unsigned(result(i))))
1793
				severity failure;
1794
		end loop;
1795
		stop <= '1';
1796
		wait;
1797
	end process;
1798

1799
end architecture;
1800

1801
------------------------- Free running counter --------------------------------------
1802

1803
------------------------- Linear Feedback Shift Register ----------------------------
1804
-- For good sources on LFSR see
1805
-- * https://sites.ualberta.ca/~delliott/ee552/studentAppNotes/1999f/Drivers_Ed/lfsr.html
1806
-- * https://en.wikipedia.org/wiki/Linear-feedback_shift_register
1807
--
1808
-- Some optimal taps
1809
--
1810
-- Taps start at the left most std_ulogic element of tap at '0' and proceed to
1811
-- the highest bit. To instantiate an instance of the LFSR set tap to a
1812
-- standard logic vector one less the size of LFSR that you want. An 8-bit
1813
-- LFSR can be made by setting it 'tap' to "0111001". The LFSR will need to
1814
-- be loaded with a seed value, set 'do' to that value and assert 'we'. The
1815
-- LFSR will only run when 'ce' is asserted, otherwise it will preserve the
1816
-- current value.
1817
--
1818
-- Number of bits   Taps      Cycle Time
1819
--      8           1,2,3,7    255
1820
--      16          1,2,4,15   65535
1821
--      32          1,5,6,31   4294967295
1822
--
1823
-- This component could also be used to calculate CRCs, which are basically
1824
-- the same computation.
1825
--
1826

1827
library ieee, work;
1828
use ieee.std_logic_1164.all;
1829
use work.util.common_generics;
1830

1831
entity lfsr is
1832
	generic (g: common_generics; constant tap: std_ulogic_vector);
1833
	port
1834
	(
1835
		clk: in  std_ulogic;
1836
		rst: in  std_ulogic;
1837
		ce:  in  std_ulogic := '1';
1838
		we:  in  std_ulogic;
1839
		di:  in  std_ulogic_vector(tap'high + 1 downto tap'low);
1840
		do:  out std_ulogic_vector(tap'high + 1 downto tap'low));
1841
end entity;
1842

1843
architecture rtl of lfsr is
1844
	signal r_c, r_n : std_ulogic_vector(di'range) := (others => '0');
1845
begin
1846
	do <= r_c after g.delay;
1847

1848
	process(rst, clk)
1849
	begin
1850
		if rst = '1' and g.asynchronous_reset then
1851
			r_c <= (others => '0') after g.delay;
1852
		elsif rising_edge(clk) then
1853
			if rst = '1' and not g.asynchronous_reset then
1854
				r_c <= (others => '0') after g.delay;
1855
			else
1856
				r_c <= r_n after g.delay;
1857
			end if;
1858
		end if;
1859
	end process;
1860

1861
	process(r_c, di, we, ce)
1862
	begin
1863
		if we = '1' then
1864
			r_n <= di after g.delay;
1865
		elsif ce = '1' then
1866
			r_n(r_n'high) <= r_c(r_c'low);
1867
			for i in tap'high downto tap'low loop
1868
				if tap(i) = '1' then
1869
					r_n(i) <= r_c(r_c'low) xor r_c(i+1) after g.delay;
1870
				else
1871
					r_n(i) <= r_c(i+1) after g.delay;
1872
				end if;
1873
			end loop;
1874
		else
1875
			r_n <= r_c;
1876
		end if;
1877
	end process;
1878
end architecture;
1879

1880
library ieee, work;
1881
use ieee.std_logic_1164.all;
1882
use work.util.common_generics;
1883

1884
entity lfsr_tb is
1885
	generic (g: common_generics);
1886
end entity;
1887

1888
architecture behavior of lfsr_tb is
1889
	constant clock_period: time     := 1000 ms / g.clock_frequency;
1890
	signal we: std_ulogic := '0';
1891
	signal do, di: std_ulogic_vector(7 downto 0) := (others => '0');
1892

1893
	signal clk, rst: std_ulogic := '0';
1894
	signal stop:     std_ulogic := '0';
1895
begin
1896
	cs: entity work.clock_source_tb
1897
		generic map (g => g, hold_rst => 2)
1898
		port map (stop => stop, clk => clk, rst => rst);
1899

1900
	uut: entity work.lfsr
1901
		generic map (g => g, tap => "0111001")
1902
		port map (clk => clk,
1903
			 rst => rst,
1904
			 we => we,
1905
			 di => di,
1906
			 do => do);
1907

1908
	stimulus_process: process
1909
	begin
1910
		wait for clock_period * 2;
1911
		we   <= '1';
1912
		di   <= "00000001";
1913
		wait for clock_period;
1914
		we   <= '0';
1915
		stop <= '1';
1916
		wait;
1917
	end process;
1918

1919
end architecture;
1920

1921
------------------------- Linear Feedback Shift Register ----------------------------
1922

1923
------------------------- I/O Pin Controller ----------------------------------------
1924
--
1925
-- This is a simple I/O pin control module, there is a control register which
1926
-- sets whether the pins are to be read in (control = '0') or set to the value written to
1927
-- "din" (control = '1').
1928

1929
library ieee, work;
1930
use ieee.std_logic_1164.all;
1931
use work.util.common_generics;
1932

1933
entity io_pins is
1934
	generic (g: common_generics; N: positive);
1935
	port
1936
	(
1937
		clk:         in    std_ulogic;
1938
		rst:         in    std_ulogic;
1939
		control:     in    std_ulogic_vector(N - 1 downto 0);
1940
		control_we:  in    std_ulogic;
1941
		din:         in    std_ulogic_vector(N - 1 downto 0);
1942
		din_we:      in    std_ulogic;
1943
		dout:        out   std_ulogic_vector(N - 1 downto 0);
1944
		pins:        inout std_logic_vector(N - 1 downto 0));
1945
end entity;
1946

1947
architecture rtl of io_pins is
1948
	signal control_o: std_ulogic_vector(control'range) := (others => '0');
1949
	signal din_o:     std_ulogic_vector(din'range)     := (others => '0');
1950
begin
1951

1952
	control_r: entity work.reg generic map (g => g, N => N)
1953
				port map (clk => clk, rst => rst, di => control, we => control_we, do => control_o);
1954
	din_r:     entity work.reg generic map (g => g, N => N)
1955
				port map (clk => clk, rst => rst, di => din,     we => din_we,     do => din_o);
1956

1957
	pins_i: for i in control_o'range generate
1958
		dout(i) <= pins(i)  when control_o(i) = '0' else '0' after g.delay;
1959
		pins(i) <= din_o(i) when control_o(i) = '1' else 'Z' after g.delay;
1960
	end generate;
1961

1962
end architecture;
1963

1964
library ieee, work;
1965
use ieee.std_logic_1164.all;
1966
use work.util.common_generics;
1967

1968
entity io_pins_tb is
1969
	generic (g: common_generics);
1970
end entity;
1971

1972
architecture behavior of io_pins_tb is
1973
	constant clock_period: time := 1000 ms / g.clock_frequency;
1974
	constant N: positive := 8;
1975

1976
	signal control: std_ulogic_vector(N - 1 downto 0) := (others => '0');
1977
	signal din:     std_ulogic_vector(N - 1 downto 0) := (others => '0');
1978
	signal dout:    std_ulogic_vector(N - 1 downto 0) := (others => '0');
1979
	signal pins:    std_logic_vector(N - 1 downto 0)  := (others => 'L'); -- !
1980

1981
	signal control_we: std_ulogic := '0';
1982
	signal din_we: std_ulogic     := '0';
1983

1984

1985
	signal clk, rst: std_ulogic := '0';
1986
	signal stop:     std_ulogic := '0';
1987
begin
1988
	cs: entity work.clock_source_tb
1989
		generic map (g => g, hold_rst => 2)
1990
		port map (stop => stop, clk => clk, rst => rst);
1991

1992
	uut: entity work.io_pins
1993
		generic map (g => g, N => N)
1994
		port map (
1995
			clk         =>  clk,
1996
			rst         =>  rst,
1997
			control     =>  control,
1998
			control_we  =>  control_we,
1999
			din         =>  din,
2000
			din_we      =>  din_we,
2001
			dout        =>  dout,
2002
			pins        =>  pins);
2003

2004
	stimulus_process: process
2005
	begin
2006
		wait for clock_period * 2;
2007
		control    <= x"0f"; -- write lower pins
2008
		control_we <= '1';
2009

2010
		wait for clock_period;
2011
		din        <= x"AA";
2012
		din_we     <= '1';
2013

2014
		wait for clock_period * 2;
2015
		pins <= (others => 'H'); -- !
2016
		wait for clock_period * 2;
2017
		stop <= '1';
2018
		wait;
2019
	end process;
2020

2021
end architecture;
2022

2023
------------------------- I/O Pin Controller ----------------------------------------
2024

2025
------------------------- Single and Dual Port Block RAM ----------------------------
2026
--| @warning The function initialize_ram has to be present in each architecture
2027
--| block ram that uses it (as far as I am aware) which means they could fall
2028
--| out of sync. This could be remedied with VHDL-2008.
2029
---------------------------------------------------------------------------------
2030

2031
--- Dual Port Model ---
2032

2033
library ieee, work;
2034
use ieee.std_logic_1164.all;
2035
use ieee.numeric_std.all;
2036
use std.textio.all;
2037
use work.util.all;
2038

2039
entity dual_port_block_ram is
2040

2041
	-- The dual port Block RAM module can be initialized from a file,
2042
	-- or initialized to all zeros. The model can be synthesized (with
2043
	-- Xilinx's ISE) into BRAM.
2044
	--
2045
	-- Valid file_type options include:
2046
	--
2047
	-- FILE_BINARY - A binary file (ASCII '0' and '1', one number per line)
2048
	-- FILE_HEX    - A Hex file (ASCII '0-9' 'a-f', 'A-F', one number per line)
2049
	-- FILE_NONE   - RAM contents will be defaulted to all zeros, no file will
2050
	--               be read from
2051
	--
2052
	-- The data length must be divisible by 4 if the "hex" option is
2053
	-- given.
2054
	--
2055
	-- These default values for addr_length and data_length have been
2056
	-- chosen so as to fill the block RAM available on a Spartan 6.
2057
	--
2058
	generic (g: common_generics;
2059
		addr_length: positive    := 12;
2060
		data_length: positive    := 16;
2061
		file_name:   string      := "memory.bin";
2062
		file_type:   file_format := FILE_BINARY);
2063
	port (
2064
		--| Port A of dual port RAM
2065
		a_clk:  in  std_ulogic;
2066
		a_dwe:  in  std_ulogic;
2067
		a_dre:  in  std_ulogic;
2068
		a_addr: in  std_ulogic_vector(addr_length - 1 downto 0);
2069
		a_din:  in  std_ulogic_vector(data_length - 1 downto 0);
2070
		a_dout: out std_ulogic_vector(data_length - 1 downto 0) := (others => '0');
2071
		--| Port B of dual port RAM
2072
		b_clk:  in  std_ulogic;
2073
		b_dwe:  in  std_ulogic;
2074
		b_dre:  in  std_ulogic;
2075
		b_addr: in  std_ulogic_vector(addr_length - 1 downto 0);
2076
		b_din:  in  std_ulogic_vector(data_length - 1 downto 0);
2077
		b_dout: out std_ulogic_vector(data_length - 1 downto 0) := (others => '0'));
2078
end entity;
2079

2080
architecture behav of dual_port_block_ram is
2081
	constant ram_size: positive := 2 ** addr_length;
2082

2083
	type ram_type is array ((ram_size - 1 ) downto 0) of std_ulogic_vector(data_length - 1 downto 0);
2084

2085
	impure function initialize_ram(the_file_name: in string; the_file_type: in file_format) return ram_type is
2086
		variable ram_data:   ram_type;
2087
		file     in_file:    text is in the_file_name;
2088
		variable input_line: line;
2089
		variable tmp:        bit_vector(data_length - 1 downto 0);
2090
		variable c:          character;
2091
		variable slv:        std_ulogic_vector(data_length - 1 downto 0);
2092
	begin
2093
		for i in 0 to ram_size - 1 loop
2094
			if the_file_type = FILE_NONE then
2095
				ram_data(i):=(others => '0');
2096
			elsif not endfile(in_file) then
2097
				readline(in_file,input_line);
2098
				if the_file_type = FILE_BINARY then
2099
					read(input_line, tmp);
2100
					ram_data(i) := std_ulogic_vector(to_stdlogicvector(tmp));
2101
				elsif the_file_type = FILE_HEX then
2102
					assert (data_length mod 4) = 0 report "(data_length%4)!=0" severity failure;
2103
					for j in 1 to (data_length/4) loop
2104
						c:= input_line((data_length/4) - j + 1);
2105
						slv((j*4)-1 downto (j*4)-4) := hex_char_to_std_ulogic_vector_tb(c);
2106
					end loop;
2107
					ram_data(i) := slv;
2108
				else
2109
					report "Incorrect file type given: " & file_format'image(the_file_type) severity failure;
2110
				end if;
2111
			else
2112
				ram_data(i) := (others => '0');
2113
			end if;
2114
		end loop;
2115
		file_close(in_file);
2116
		return ram_data;
2117
	end function;
2118

2119
	shared variable ram: ram_type := initialize_ram(file_name, file_type);
2120

2121
begin
2122
	a_ram: process(a_clk)
2123
	begin
2124
		if rising_edge(a_clk) then
2125
			if a_dwe = '1' then
2126
				ram(to_integer(unsigned(a_addr))) := a_din;
2127
			end if;
2128
			if a_dre = '1' then
2129
				a_dout <= ram(to_integer(unsigned(a_addr))) after g.delay;
2130
			else
2131
				a_dout <= (others => '0') after g.delay;
2132
			end if;
2133
		end if;
2134
	end process;
2135

2136
	b_ram: process(b_clk)
2137
	begin
2138
		if rising_edge(b_clk) then
2139
			if b_dwe = '1' then
2140
				ram(to_integer(unsigned(b_addr))) := b_din;
2141
			end if;
2142
			if b_dre = '1' then
2143
				b_dout <= ram(to_integer(unsigned(b_addr))) after g.delay;
2144
			else
2145
				b_dout <= (others => '0') after g.delay;
2146
			end if;
2147
		end if;
2148
	end process;
2149
end architecture;
2150

2151
--- Single Port Model ---
2152

2153
library ieee, work;
2154
use ieee.std_logic_1164.all;
2155
use ieee.numeric_std.all;
2156
use std.textio.all;
2157
use work.util.all;
2158

2159
entity single_port_block_ram is
2160
	generic (g: common_generics;
2161
		addr_length: positive    := 12;
2162
		data_length: positive    := 16;
2163
		file_name:   string      := "memory.bin";
2164
		file_type:   file_format := FILE_BINARY);
2165
	port (
2166
		clk:  in  std_ulogic;
2167
		dwe:  in  std_ulogic;
2168
		dre:  in  std_ulogic;
2169
		addr: in  std_ulogic_vector(addr_length - 1 downto 0);
2170
		din:  in  std_ulogic_vector(data_length - 1 downto 0);
2171
		dout: out std_ulogic_vector(data_length - 1 downto 0) := (others => '0'));
2172
end entity;
2173

2174
architecture behav of single_port_block_ram is
2175
	constant ram_size: positive := 2 ** addr_length;
2176

2177
	type ram_type is array ((ram_size - 1 ) downto 0) of std_ulogic_vector(data_length - 1 downto 0);
2178

2179
	impure function initialize_ram(the_file_name: in string; the_file_type: in file_format) return ram_type is
2180
		variable ram_data:   ram_type;
2181
		file     in_file:    text is in the_file_name;
2182
		variable input_line: line;
2183
		variable tmp:        bit_vector(data_length - 1 downto 0);
2184
		variable c:          character;
2185
		variable slv:        std_ulogic_vector(data_length - 1 downto 0);
2186
	begin
2187
		for i in 0 to ram_size - 1 loop
2188
			if the_file_type = FILE_NONE then
2189
				ram_data(i):=(others => '0');
2190
			elsif not endfile(in_file) then
2191
				readline(in_file,input_line);
2192
				if the_file_type = FILE_BINARY then
2193
					read(input_line, tmp);
2194
					ram_data(i) := std_ulogic_vector(to_stdlogicvector(tmp));
2195
				elsif the_file_type = FILE_HEX then -- hexadecimal
2196
					assert (data_length mod 4) = 0 report "(data_length%4)!=0" severity failure;
2197
					for j in 1 to (data_length/4) loop
2198
						c:= input_line((data_length/4) - j + 1);
2199
						slv((j*4)-1 downto (j*4)-4) := hex_char_to_std_ulogic_vector_tb(c);
2200
					end loop;
2201
					ram_data(i) := slv;
2202
				else
2203
					report "Incorrect file type given: " & file_format'image(the_file_type) severity failure;
2204
				end if;
2205
			else
2206
				ram_data(i) := (others => '0');
2207
			end if;
2208
		end loop;
2209
		file_close(in_file);
2210
		return ram_data;
2211
	end function;
2212

2213
	shared variable ram: ram_type := initialize_ram(file_name, file_type);
2214

2215
begin
2216
	block_ram: process(clk)
2217
	begin
2218
		if rising_edge(clk) then
2219
			if dwe = '1' then
2220
				ram(to_integer(unsigned(addr))) := din;
2221
			end if;
2222

2223
			if dre = '1' then
2224
				dout <= ram(to_integer(unsigned(addr))) after g.delay;
2225
			else
2226
				dout <= (others => '0') after g.delay;
2227
			end if;
2228
		end if;
2229
	end process;
2230
end architecture;
2231

2232
------------------------- Single and Dual Port Block RAM ----------------------------
2233

2234
------------------------- Data Source -----------------------------------------------
2235
--|
2236
--| This module spits out a bunch of data.
2237
--|
2238

2239
library ieee, work;
2240
use ieee.std_logic_1164.all;
2241
use ieee.numeric_std.all;
2242
use work.util.single_port_block_ram;
2243
use work.util.counter;
2244
use work.util.all;
2245

2246
entity data_source is
2247
	generic (g: common_generics;
2248
		addr_length: positive    := 12;
2249
		data_length: positive    := 16;
2250
		file_name:   string      := "memory.bin";
2251
		file_type:   file_format := FILE_BINARY);
2252
	port (
2253
		clk:     in  std_ulogic;
2254
		rst:     in  std_ulogic;
2255

2256
		ce:      in  std_ulogic := '1';
2257
		cr:      in  std_ulogic;
2258

2259
		load:    in  std_ulogic_vector(addr_length - 1 downto 0) := (others => '0');
2260
		load_we: in  std_ulogic := '0';
2261

2262
		dout:    out std_ulogic_vector(data_length - 1 downto 0));
2263
end entity;
2264

2265
architecture structural of data_source is
2266
	signal addr: std_ulogic_vector(addr_length - 1 downto 0);
2267
begin
2268
	count: work.util.counter
2269
		generic map (g => g, N => addr_length)
2270
		port map (
2271
			clk      =>  clk,
2272
			rst      =>  rst,
2273
			ce       =>  ce,
2274
			cr       =>  cr,
2275
			dout     =>  addr,
2276
			load_i   =>  load,
2277
			load_we  =>  load_we);
2278

2279
	ram: work.util.single_port_block_ram
2280
		generic map (
2281
			g           => g,
2282
			addr_length => addr_length,
2283
			data_length => data_length,
2284
			file_name   => file_name,
2285
			file_type   => file_type)
2286
		port map (
2287
			clk  => clk,
2288
			addr => addr,
2289
			dwe  => '0',
2290
			dre  => '1',
2291
			din  => (others => '0'),
2292
			dout => dout);
2293

2294
end architecture;
2295

2296
------------------------- Data Source -----------------------------------------------
2297

2298
------------------------- uCPU ------------------------------------------------------
2299
-- @brief An incredible simple microcontroller
2300
-- @license MIT
2301
-- @author Richard James Howe
2302
-- @copyright Richard James Howe (2017)
2303
--
2304
-- Based on:
2305
-- https://stackoverflow.com/questions/20955863/vhdl-microprocessor-microcontroller
2306
--
2307
--  INSTRUCTION    CYCLES 87 6543210 OPERATION
2308
--  ADD WITH CARRY   2    00 ADDRESS A = A   + MEM[ADDRESS]
2309
--  NOR              2    01 ADDRESS A = A NOR MEM[ADDRESS]
2310
--  STORE            1    10 ADDRESS MEM[ADDRESS] = A
2311
--  JCC              1    11 ADDRESS IF(CARRY) { PC = ADDRESS, CLEAR CARRY }
2312
--
2313
-- It would be interesting to make a customizable CPU in which the
2314
-- instructions could be customized based upon generics. Another interesting
2315
-- possibility is making a simple assembler purely in VHDL, which should
2316
-- be possible, but difficult. A single port version would require another
2317
-- state to fetch the operand and another register, or more states.
2318
--
2319
-- I have another small, bit serial CPU, available at:
2320
--   <https://github.com/howerj/bit-serial>
2321
-- Which is also tiny, but potentially much more useful. 
2322
--
2323

2324
library ieee, work;
2325
use ieee.std_logic_1164.all;
2326
use ieee.numeric_std.all;
2327

2328
entity ucpu is
2329
	generic (
2330
		asynchronous_reset:  boolean := true;  -- use asynchronous reset if true, synchronous if false
2331
		delay:               time    := 0 ns; -- simulation only
2332

2333
		width:               positive range 8 to 32 := 8);
2334
	port (
2335
		clk, rst: in  std_ulogic;
2336

2337
		pc:       out std_ulogic_vector(width - 3 downto 0);
2338
		op:       in  std_ulogic_vector(width - 1 downto 0);
2339

2340
		adr:      out std_ulogic_vector(width - 3 downto 0);
2341
		di:       in  std_ulogic_vector(width - 1 downto 0);
2342
		re, we:   out std_ulogic;
2343
		do:       out std_ulogic_vector(width - 1 downto 0));
2344
end entity;
2345

2346
architecture rtl of ucpu is
2347
	signal a_c,   a_n:       unsigned(di'high + 1 downto di'low) := (others => '0'); -- accumulator
2348
	signal pc_c,  pc_n:      unsigned(pc'range)                  := (others => '0');
2349
	signal alu:              std_ulogic_vector(1 downto 0)       := (others => '0');
2350
	signal state_c, state_n: std_ulogic                          := '0'; -- FETCH/Single cycle instruction or EXECUTE
2351
begin
2352
	pc          <= std_ulogic_vector(pc_n) after delay;
2353
	do          <= std_ulogic_vector(a_c(do'range)) after delay;
2354
	alu         <= op(op'high downto op'high - 1) after delay;
2355
	adr         <= op(adr'range) after delay;
2356
	we          <= '1' when alu = "10" else '0' after delay; -- STORE
2357
	re          <= alu(1) nor state_c after delay;           -- FETCH for ADD and NOR
2358
	state_n     <= alu(1) nor state_c after delay;           -- FETCH not taken or FETCH done
2359
	pc_n        <= unsigned(op(pc_n'range)) when (alu = "11"    and a_c(a_c'high) = '0') else -- Jump when carry set
2360
			pc_c                    when (state_c = '0' and alu(1) = '0')        else -- FETCH
2361
			(pc_c + 1) after delay; -- EXECUTE
2362

2363
	process(clk, rst)
2364
	begin
2365
		if rst = '1' and asynchronous_reset then
2366
			a_c     <= (others => '0') after delay;
2367
			pc_c    <= (others => '0') after delay;
2368
			state_c <= '0' after delay;
2369
		elsif rising_edge(clk) then
2370
			if rst = '1' and not asynchronous_reset then
2371
				a_c     <= (others => '0') after delay;
2372
				pc_c    <= (others => '0') after delay;
2373
				state_c <= '0' after delay;
2374
			else
2375
				a_c     <= a_n after delay;
2376
				pc_c    <= pc_n after delay;
2377
				state_c <= state_n after delay;
2378
			end if;
2379
		end if;
2380
	end process;
2381

2382
	process(op, alu, di, a_c, state_c)
2383
	begin
2384
		a_n     <= a_c after delay;
2385

2386
		if alu = "11" and a_c(a_c'high) = '0' then a_n(a_n'high) <= '0' after delay; end if;
2387

2388
		if state_c = '1' then -- EXECUTE for ADD and NOR
2389
			assert alu(1) = '0' severity failure;
2390
			if alu(0) = '0' then a_n <= '0' & a_c(di'range) + unsigned('0' & di) after delay; end if;
2391
			if alu(0) = '1' then a_n <= a_c nor '0' & unsigned(di) after delay; end if;
2392
		end if;
2393
	end process;
2394
end architecture;
2395

2396
library ieee, work;
2397
use ieee.std_logic_1164.all;
2398
use ieee.numeric_std.all;
2399
use ieee.math_real.all;
2400
use work.util.all;
2401

2402
entity ucpu_tb is
2403
	generic (g: common_generics;
2404
		file_name: string := "ucpu.bin");
2405
end entity;
2406

2407
architecture testing of ucpu_tb is
2408
	constant clock_period:      time     := 1000 ms / g.clock_frequency;
2409

2410
	constant data_length: positive := 8;
2411
	constant addr_length: positive := data_length - 2;
2412

2413
	signal a_addr: std_ulogic_vector(addr_length - 1 downto 0);
2414
	signal a_dout: std_ulogic_vector(data_length - 1 downto 0) := (others => '0');
2415

2416
	signal b_dwe:  std_ulogic;
2417
	signal b_dre:  std_ulogic;
2418
	signal b_addr: std_ulogic_vector(addr_length - 1 downto 0);
2419
	signal b_din:  std_ulogic_vector(data_length - 1 downto 0);
2420
	signal b_dout: std_ulogic_vector(data_length - 1 downto 0) := (others => '0');
2421

2422
	signal clk, rst: std_ulogic := '0';
2423
	signal stop:     std_ulogic := '0';
2424
begin
2425
	cs: entity work.clock_source_tb
2426
		generic map (g => g, hold_rst => 2)
2427
		port map (stop => stop, clk => clk, rst => rst);
2428

2429
	bram_0: entity work.dual_port_block_ram
2430
	generic map (g => g,
2431
		addr_length => addr_length,
2432
		data_length => data_length,
2433
		file_name   => file_name,
2434
		file_type   => FILE_BINARY)
2435
	port map (
2436
		a_clk   =>  clk,
2437
		a_dwe   =>  '0',
2438
		a_dre   =>  '1',
2439
		a_addr  =>  a_addr,
2440
		a_din   =>  (others => '0'),
2441
		a_dout  =>  a_dout,
2442

2443
		b_clk   =>  clk,
2444
		b_dwe   =>  b_dwe,
2445
		b_dre   =>  b_dre,
2446
		b_addr  =>  b_addr,
2447
		b_din   =>  b_din,
2448
		b_dout  =>  b_dout);
2449

2450
	ucpu_0: entity work.ucpu
2451
	generic map (delay => g.delay, width => data_length)
2452
	port map (
2453
		clk => clk,
2454
		rst => rst,
2455
		pc  => a_addr,
2456
		op  => a_dout,
2457

2458
		re  => b_dre,
2459
		we  => b_dwe,
2460
		di  => b_dout,
2461
		do  => b_din,
2462
		adr => b_addr);
2463

2464
	stimulus_process: process
2465
	begin
2466
		wait for clock_period * 1000;
2467
		stop <= '1';
2468
		wait;
2469
	end process;
2470

2471
end architecture;
2472

2473
------------------------- uCPU ------------------------------------------------------
2474

2475
------------------------- Restoring Division ----------------------------------------
2476
--
2477
-- Computes a/b in N cycles
2478
--
2479
-- https://en.wikipedia.org/wiki/Division_algorithm#Restoring_division
2480
--
2481

2482
library ieee, work;
2483
use ieee.std_logic_1164.all;
2484
use ieee.numeric_std.all;
2485
use work.util.common_generics;
2486

2487
entity restoring_divider is
2488
	generic (g: common_generics; N: positive);
2489
	port (
2490
		clk:   in  std_ulogic;
2491
		rst:   in  std_ulogic := '0';
2492

2493
		a:     in  std_ulogic_vector(N - 1 downto 0);
2494
		b:     in  std_ulogic_vector(N - 1 downto 0);
2495
		start: in  std_ulogic;
2496
		done:  out std_ulogic;
2497
		c:     out std_ulogic_vector(N - 1 downto 0));
2498
end entity;
2499

2500
architecture rtl of restoring_divider is
2501
	signal a_c, a_n: unsigned(a'range) := (others => '0');
2502
	signal b_c, b_n: unsigned(b'range) := (others => '0');
2503
	signal m_c, m_n: unsigned(b'range) := (others => '0');
2504
	signal o_c, o_n: unsigned(c'range) := (others => '0');
2505
	signal e_c, e_n: std_ulogic         := '0';
2506
	signal count_c, count_n: unsigned(work.util.n_bits(N) downto 0) := (others => '0');
2507
begin
2508
	c <= std_ulogic_vector(o_n);
2509

2510
	process(clk, rst)
2511
		procedure reset is
2512
		begin
2513
			a_c      <=  (others  =>  '0') after g.delay;
2514
			b_c      <=  (others  =>  '0') after g.delay;
2515
			m_c      <=  (others  =>  '0') after g.delay;
2516
			o_c      <=  (others  =>  '0') after g.delay;
2517
			e_c      <=  '0' after g.delay;
2518
			count_c  <=  (others  =>  '0') after g.delay;
2519
		end procedure;
2520
	begin
2521
		if rst = '1' and g.asynchronous_reset then
2522
			reset;
2523
		elsif rising_edge(clk) then
2524
			if rst = '1' and not g.asynchronous_reset then
2525
				reset;
2526
			else
2527
				a_c      <=  a_n after g.delay;
2528
				b_c      <=  b_n after g.delay;
2529
				m_c      <=  m_n after g.delay;
2530
				o_c      <=  o_n after g.delay;
2531
				e_c      <=  e_n after g.delay;
2532
				count_c  <=  count_n after g.delay;
2533
			end if;
2534
		end if;
2535
	end process;
2536

2537
	divide: process(a, b, start, a_c, b_c, m_c, e_c, o_c, count_c)
2538
		variable m_v: unsigned(b'range) := (others => '0');
2539
	begin
2540
		done     <=  '0';
2541
		a_n      <=  a_c;
2542
		b_n      <=  b_c;
2543
		m_v      :=  m_c;
2544
		e_n      <=  e_c;
2545
		o_n      <=  o_c;
2546
		count_n  <=  count_c;
2547
		if start = '1' then
2548
			a_n   <= unsigned(a) after g.delay;
2549
			b_n   <= unsigned(b) after g.delay;
2550
			m_v   := (others => '0');
2551
			e_n   <= '1' after g.delay;
2552
			o_n   <= (others => '0') after g.delay;
2553
			count_n <= (others => '0') after g.delay;
2554
		elsif e_c = '1' then
2555
			if count_c(count_c'high) = '1' then
2556
				done  <= '1' after g.delay;
2557
				e_n   <= '0' after g.delay;
2558
				o_n   <= a_c after g.delay;
2559
				count_n <= (others => '0') after g.delay;
2560
			else
2561
				m_v(b'high downto 1) := m_v(b'high - 1 downto 0);
2562
				m_v(0) := a_c(a'high);
2563
				a_n(a'high downto 1) <= a_c(a'high - 1 downto 0) after g.delay;
2564
				m_v := m_v - b_c;
2565
				if m_v(m_v'high) = '1' then
2566
					m_v := m_v + b_c;
2567
					a_n(0) <= '0' after g.delay;
2568
				else
2569
					a_n(0) <= '1' after g.delay;
2570
				end if;
2571
				count_n <= count_c + 1 after g.delay;
2572
			end if;
2573
		else
2574
			count_n <= (others => '0') after g.delay;
2575
		end if;
2576
		m_n <= m_v after g.delay;
2577
	end process;
2578
end architecture;
2579

2580
library ieee, work;
2581
use ieee.std_logic_1164.all;
2582
use ieee.numeric_std.all;
2583
use ieee.math_real.all;
2584
use work.util.common_generics;
2585

2586
entity restoring_divider_tb is
2587
	generic (g: common_generics);
2588
end entity;
2589

2590
architecture testing of restoring_divider_tb is
2591
	constant clock_period: time     := 1000 ms / g.clock_frequency;
2592
	constant N:          positive := 8;
2593

2594
	signal a: std_ulogic_vector(N - 1 downto 0) := (others => '0');
2595
	signal b: std_ulogic_vector(N - 1 downto 0) := (others => '0');
2596
	signal c: std_ulogic_vector(N - 1 downto 0) := (others => '0');
2597
	signal start, done: std_ulogic := '0';
2598

2599
	signal clk, rst: std_ulogic := '0';
2600
	signal stop:     std_ulogic := '0';
2601
begin
2602
	cs: entity work.clock_source_tb
2603
		generic map (g => g, hold_rst => 2)
2604
		port map (stop => stop, clk => clk, rst => rst);
2605

2606
	uut: entity work.restoring_divider
2607
		generic map (g => g, N => N)
2608
		port map (
2609
			clk   => clk,
2610
			rst   => rst,
2611
			a     => a,
2612
			b     => b,
2613
			start => start,
2614
			done  => done,
2615
			c     => c);
2616

2617
	stimulus_process: process
2618
	begin
2619
		wait for clock_period * 2;
2620

2621
		a <= x"64";
2622
		b <= x"0A";
2623
		start <= '1';
2624
		wait for clock_period * 1;
2625
		start <= '0';
2626
		wait until done = '1';
2627
		--assert c = x"0A" severity failure;
2628

2629
		wait for clock_period * 10;
2630
		b     <= x"05";
2631
		start <= '1';
2632
		wait for clock_period * 1;
2633
		start <= '0';
2634
		wait until done = '1';
2635
		--assert c = x"14" severity failure;
2636

2637
		stop <= '1';
2638
		wait;
2639
	end process;
2640

2641
end architecture;
2642
------------------------- Restoring Divider ---------------------------------------------------
2643

2644
------------------------- Debouncer -----------------------------------------------------------
2645

2646
library ieee, work;
2647
use ieee.std_logic_1164.all;
2648
use ieee.numeric_std.all;
2649
use work.util.common_generics;
2650

2651
entity debounce_us is
2652
	generic (g: common_generics; timer_period_us: natural);
2653
	port (
2654
		clk:   in  std_ulogic;
2655
		di:    in  std_ulogic;
2656
		do:    out std_ulogic := '0');
2657
end entity;
2658

2659
architecture rtl of debounce_us is
2660
	signal ff: std_ulogic_vector(1 downto 0) := (others => '0');
2661
	signal rst, done: std_ulogic             := '0';
2662
begin
2663
	timer: work.util.timer_us
2664
		generic map (g => g, timer_period_us => timer_period_us)
2665
		port map (
2666
			clk => clk,
2667
			rst => rst,
2668
			co  => done);
2669

2670
	process(clk)
2671
	begin
2672
		if rising_edge(clk) then
2673
			ff(0) <= di    after g.delay;
2674
			ff(1) <= ff(0) after g.delay;
2675
			if (ff(0) xor ff(1)) = '1' then
2676
				rst <= '1' after g.delay;
2677
			elsif done = '1' then
2678
				do  <= ff(1) after g.delay;
2679
			else
2680
				rst   <= '0';
2681
			end if;
2682
		end if;
2683
	end process;
2684
end architecture;
2685

2686
library ieee, work;
2687
use ieee.std_logic_1164.all;
2688
use ieee.numeric_std.all;
2689
use work.util.common_generics;
2690

2691
entity debounce_us_tb is
2692
	generic (g: common_generics);
2693
end entity;
2694

2695
architecture testing of debounce_us_tb is
2696
	constant clock_period: time := 1000 ms / g.clock_frequency;
2697

2698
	signal di,  do:  std_ulogic := '0';
2699
	signal clk, rst: std_ulogic := '0';
2700
	signal stop:     std_ulogic := '0';
2701
begin
2702
	cs: entity work.clock_source_tb
2703
		generic map (g => g, hold_rst => 2)
2704
		port map (stop => stop, clk => clk, rst => rst);
2705

2706
	uut: work.util.debounce_us
2707
		generic map (g => g, timer_period_us => 1)
2708
		port map (clk => clk, di => di, do => do);
2709

2710
	stimulus_process: process
2711
	begin
2712
		wait for clock_period * 2;
2713
		di <= '1';
2714

2715
		wait for 1.5 us;
2716

2717
		stop <= '1';
2718
		wait;
2719
	end process;
2720
end architecture;
2721
------------------------- Debouncer -----------------------------------------------------------
2722

2723
------------------------- Debouncer Block -----------------------------------------------------
2724

2725
library ieee, work;
2726
use ieee.std_logic_1164.all;
2727
use ieee.numeric_std.all;
2728
use work.util.common_generics;
2729

2730
entity debounce_block_us is
2731
	generic (g: common_generics; N: positive; timer_period_us: natural);
2732
	port (
2733
		clk:   in  std_ulogic;
2734
		di:    in  std_ulogic_vector(N - 1 downto 0);
2735
		do:    out std_ulogic_vector(N - 1 downto 0));
2736
end entity;
2737

2738
architecture structural of debounce_block_us is
2739
begin
2740
	debouncer: for i in (N - 1) downto 0 generate
2741
		d_instance: work.util.debounce_us
2742
			generic map (g => g, timer_period_us => timer_period_us)
2743
			port map (clk => clk, di => di(i), do => do(i));
2744
	end generate;
2745
end architecture;
2746

2747
------------------------- Debouncer Block -----------------------------------------------------
2748

2749
------------------------- State Changed -------------------------------------------------------
2750
library ieee, work;
2751
use ieee.std_logic_1164.all;
2752
use ieee.numeric_std.all;
2753
use work.util.common_generics;
2754

2755
entity state_changed is
2756
	generic (g: common_generics);
2757
	port (
2758
		clk: in  std_ulogic;
2759
		rst: in  std_ulogic;
2760
		di:  in  std_ulogic;
2761
		do:  out std_ulogic);
2762
end entity;
2763

2764
architecture rtl of state_changed is
2765
	signal state_c, state_n: std_ulogic_vector(1 downto 0) := (others => '0');
2766
begin
2767
	process(clk, rst)
2768
	begin
2769
		if rst = '1' and g.asynchronous_reset then
2770
			state_c <= (others => '0') after g.delay;
2771
		elsif rising_edge(clk) then
2772
			if rst = '1' and not g.asynchronous_reset then
2773
				state_c <= (others => '0') after g.delay;
2774
			else
2775
				state_c <= state_n after g.delay;
2776
			end if;
2777
		end if;
2778
	end process;
2779

2780
	do <= '1' when (state_c(0) xor state_c(1)) = '1' else '0';
2781

2782
	process(di, state_c)
2783
	begin
2784
		state_n(0) <= state_c(1) after g.delay;
2785
		state_n(1) <= di after g.delay;
2786
	end process;
2787
end architecture;
2788

2789
------------------------- Change State --------------------------------------------------------
2790

2791
------------------------- Change State Block --------------------------------------------------
2792
library ieee, work;
2793
use ieee.std_logic_1164.all;
2794
use ieee.numeric_std.all;
2795
use work.util.common_generics;
2796

2797
entity state_block_changed is
2798
	generic (g: common_generics; N: positive);
2799
	port (
2800
		clk: in  std_ulogic;
2801
		rst: in  std_ulogic;
2802
		di:  in  std_ulogic_vector(N - 1 downto 0);
2803
		do:  out std_ulogic_vector(N - 1 downto 0));
2804
end entity;
2805

2806
architecture structural of state_block_changed is
2807
begin
2808
	changes: for i in (N - 1) downto 0 generate
2809
		d_instance: work.util.state_changed
2810
			generic map (g => g)
2811
			port map (clk => clk, rst => rst, di => di(i), do => do(i));
2812
	end generate;
2813
end architecture;
2814

2815
------------------------- Change State Block --------------------------------------------------
2816

2817
------------------------- Reset Signal Generator ----------------------------------------------
2818
library ieee, work;
2819
use ieee.std_logic_1164.all;
2820
use ieee.numeric_std.all;
2821
use work.util.all;
2822

2823
entity reset_generator is
2824
	generic (g: common_generics; reset_period_us:  natural := 0);
2825
	port (
2826
		clk: in  std_logic := 'X';
2827
		rst: out std_logic := '0'); -- reset out!
2828
end entity;
2829

2830
architecture behavior of reset_generator is
2831
	constant cycles:  natural := (g.clock_frequency / 1000000) * reset_period_us;
2832
	subtype  counter is unsigned(max(1, n_bits(cycles) - 1) downto 0);
2833
	signal   c_c, c_n: counter := (others => '0');
2834
begin
2835
	process (clk)
2836
	begin
2837
		if rising_edge(clk) then
2838
			c_c <= c_n after g.delay;
2839
		end if;
2840
	end process;
2841

2842
	process (c_c)
2843
	begin
2844
		if c_c = (cycles - 1) then
2845
			c_n <= c_c after g.delay;
2846
			rst <= '0' after g.delay;
2847
		else
2848
			c_n <= c_c + 1 after g.delay;
2849
			rst <= '1' after g.delay;
2850
		end if;
2851
	end process;
2852
end architecture;
2853

2854
library ieee, work;
2855
use ieee.std_logic_1164.all;
2856
use work.util.common_generics;
2857

2858
entity reset_generator_tb is
2859
	generic (g: common_generics);
2860
end entity;
2861

2862
architecture testing of reset_generator_tb is
2863
	constant clock_period:      time     := 1000 ms / g.clock_frequency;
2864
	signal stop, clk, rst: std_ulogic := '0';
2865
begin
2866
	cs: entity work.clock_source_tb
2867
		generic map (g => g, hold_rst => 2)
2868
		port map (stop => stop, clk => clk, rst => open);
2869

2870
	uut: entity work.reset_generator
2871
		generic map (g => g, reset_period_us => 1)
2872
		port map (clk => clk, rst => rst);
2873

2874
	stimulus_process: process
2875
	begin
2876
		wait for clock_period;
2877
		assert rst = '1' severity failure;
2878
		wait for 1 us;
2879
		assert rst = '0' severity failure;
2880
		stop <= '1';
2881
		wait;
2882
	end process;
2883

2884
end architecture;
2885

2886
------------------------- Reset Signal Generator ----------------------------------------------
2887

2888
------------------------- Bit Count -----------------------------------------------------------
2889

2890
library ieee, work;
2891
use ieee.std_logic_1164.all;
2892
use ieee.numeric_std.all;
2893
use work.util.n_bits;
2894
use work.util.common_generics;
2895

2896
entity bit_count is
2897
	generic (g: common_generics; N: positive);
2898
	port (
2899
		bits:   in std_ulogic_vector(N - 1 downto 0);
2900
		count: out std_ulogic_vector(n_bits(N) downto 0));
2901
end entity;
2902

2903
architecture behavior of bit_count is
2904
begin
2905
	process (bits)
2906
		constant zero: unsigned(count'high - 1 downto count'low)  := (others => '0');
2907
		variable t: unsigned(count'range) := (others => '0');
2908
	begin
2909
		t := (others => '0');
2910
		for i in bits'low to bits'high loop
2911
			t := t + (zero & bits(i));
2912
		end loop;
2913
		count <= std_ulogic_vector(t) after g.delay;
2914
	end process;
2915
end architecture;
2916

2917
library ieee, work;
2918
use ieee.std_logic_1164.all;
2919
use work.util.n_bits;
2920
use work.util.common_generics;
2921

2922
entity bit_count_tb is
2923
	generic (g: common_generics);
2924
end entity;
2925

2926
architecture testing of bit_count_tb is
2927
	constant clock_period: time     := 1000 ms / g.clock_frequency;
2928
	constant N:            positive := 3;
2929
	signal bits:  std_ulogic_vector(N - 1 downto 0)     := (others => '0');
2930
	signal count: std_ulogic_vector(n_bits(N) downto 0) := (others => '0');
2931
begin
2932
	uut: entity work.bit_count
2933
		generic map (g => g, N => N)
2934
		port map (bits => bits, count => count);
2935

2936
	stimulus_process: process
2937
		procedure test(b: std_ulogic_vector; c: std_ulogic_vector)  is
2938
		begin
2939
			bits <= b;
2940
			wait for clock_period;
2941
			assert count = c severity failure;
2942
		end procedure;
2943
	begin
2944
		test("000", "000");
2945
		test("001", "001");
2946
		test("010", "001");
2947
		test("011", "010");
2948
		test("100", "001");
2949
		test("101", "010");
2950
		test("110", "010");
2951
		test("111", "011");
2952
		wait;
2953
	end process;
2954

2955
end architecture;
2956

2957
------------------------- Bit Count -----------------------------------------------------------
2958

2959
------------------------- Majority Voter ------------------------------------------------------
2960
--
2961
-- NB. This could be constructed from a more generic 'assert output if bit
2962
-- count greater than N' module.
2963
--
2964

2965
library ieee, work;
2966
use ieee.std_logic_1164.all;
2967
use ieee.numeric_std.all;
2968
use work.util.all;
2969

2970
entity majority is
2971
	generic (g: common_generics; N: positive; even_wins: boolean := false);
2972
	port (
2973
		bits: in std_ulogic_vector(N - 1 downto 0);
2974
		vote: out std_ulogic;
2975
		tie:  out std_ulogic);
2976
end entity;
2977

2978
architecture behavior of majority is
2979
	signal count: std_ulogic_vector(n_bits(N) downto 0) := (others => '0');
2980
	-- It might be worth handling up to five or so bits in combinatorial
2981
	-- logic, or it might not.
2982
begin
2983
	majority_1: if N = 1 generate
2984
		vote <= bits(0) after g.delay;
2985
		tie  <= '0' after g.delay;
2986
	end generate;
2987

2988
	majority_2: if N = 2 generate
2989
		ew_2:  if     even_wins generate vote <= bits(0)  or bits(1) after g.delay; end generate;
2990
		enw_2: if not even_wins generate vote <= bits(0) and bits(1) after g.delay; end generate;
2991
		tie  <= bits(0) or bits(1);
2992
	end generate;
2993

2994
	majority_3: if N = 3 generate
2995
		vote <= (bits(0) and bits(1)) or (bits(1) and bits(2)) or (bits(0) and bits(2)) after g.delay;
2996
		tie  <= '0' after g.delay;
2997
	end generate;
2998

2999
	majority_n: if N > 3 generate
3000
		bit_counter: entity work.bit_count
3001
			generic map (g => g, N => N)
3002
			port map (bits => bits, count => count);
3003

3004
		tie <= '1' when (unsigned(count) = N/2) and (N mod 2) = 0 else '0' after g.delay;
3005

3006
		process (count)
3007
		begin
3008
			if even_wins and (N mod 2) = 0 then
3009
				if unsigned(count) >= (N/2) then
3010
					vote <= '1' after g.delay;
3011
				else
3012
					vote <= '0' after g.delay;
3013
				end if;
3014
			else
3015
				if unsigned(count) > (N/2) then
3016
					vote <= '1' after g.delay;
3017
				else
3018
					vote <= '0' after g.delay;
3019
				end if;
3020
			end if;
3021
		end process;
3022
	end generate;
3023
end architecture;
3024

3025
library ieee, work;
3026
use ieee.std_logic_1164.all;
3027
use ieee.numeric_std.all;
3028
use work.util.all;
3029

3030
entity majority_tb is
3031
	generic (g: common_generics);
3032
end entity;
3033

3034
architecture testing of majority_tb is
3035
	constant clock_period: time := 1000 ms / g.clock_frequency;
3036

3037
	constant N_3:    positive := 3;
3038
	constant N_4_t:  positive := 4;
3039
	constant N_4_m:  positive := 4;
3040

3041
	signal bits_3:   std_ulogic_vector(N_3   - 1 downto 0) := (others => '0');
3042
	signal bits_4_t: std_ulogic_vector(N_4_t - 1 downto 0) := (others => '0');
3043
	signal bits_4_m: std_ulogic_vector(N_4_m - 1 downto 0) := (others => '0');
3044

3045
	signal vote_3,     tie_3: std_ulogic := '0';
3046
	signal vote_4_t, tie_4_t: std_ulogic := '0';
3047
	signal vote_4_m, tie_4_m: std_ulogic := '0';
3048
begin
3049
	uut_3: entity work.majority
3050
		generic map (g => g, N => N_3)
3051
		port map (bits => bits_3, vote => vote_3, tie => tie_3);
3052

3053
	uut_4_t: entity work.majority
3054
		generic map (g => g, N => N_4_t, even_wins => true)
3055
		port map (bits => bits_4_t, vote => vote_4_t, tie => tie_4_t);
3056

3057
	uut_4_m: entity work.majority
3058
		generic map (g => g, N => N_4_m)
3059
		port map (bits => bits_4_m, vote => vote_4_m, tie => tie_4_m);
3060

3061
	stimulus_process: process
3062
		procedure test_3(b: std_ulogic_vector; vote, tie: std_ulogic)  is
3063
		begin
3064
			bits_3 <= b;
3065
			wait for clock_period;
3066
			assert vote_3 = vote and tie_3 = tie severity failure;
3067
		end procedure;
3068

3069
		procedure test_4_t(b: std_ulogic_vector; vote, tie: std_ulogic)  is
3070
		begin
3071
			bits_4_t <= b;
3072
			wait for clock_period;
3073
			assert vote_4_t = vote and tie_4_t = tie severity failure;
3074
		end procedure;
3075

3076
		procedure test_4_m(b: std_ulogic_vector; vote, tie: std_ulogic)  is
3077
		begin
3078
			bits_4_m <= b;
3079
			wait for clock_period;
3080
			assert vote_4_m = vote and tie_4_m = tie severity failure;
3081
		end procedure;
3082
	begin
3083
		test_3("000", '0', '0');
3084
		test_3("001", '0', '0');
3085
		test_3("010", '0', '0');
3086
		test_3("011", '1', '0');
3087
		test_3("100", '0', '0');
3088
		test_3("101", '1', '0');
3089
		test_3("110", '1', '0');
3090
		test_3("111", '1', '0');
3091

3092
		test_4_t("0000", '0', '0');
3093
		test_4_t("0001", '0', '0');
3094
		test_4_t("0010", '0', '0');
3095
		test_4_t("0011", '1', '1');
3096
		test_4_t("0100", '0', '0');
3097
		test_4_t("0101", '1', '1');
3098
		test_4_t("0110", '1', '1');
3099
		test_4_t("0111", '1', '0');
3100
		test_4_t("1000", '0', '0');
3101
		test_4_t("1001", '1', '1');
3102
		test_4_t("1010", '1', '1');
3103
		test_4_t("1011", '1', '0');
3104
		test_4_t("1100", '1', '1');
3105
		test_4_t("1101", '1', '0');
3106
		test_4_t("1110", '1', '0');
3107
		test_4_t("1111", '1', '0');
3108

3109
		test_4_m("0000", '0', '0');
3110
		test_4_m("0001", '0', '0');
3111
		test_4_m("0010", '0', '0');
3112
		test_4_m("0011", '0', '1');
3113
		test_4_m("0100", '0', '0');
3114
		test_4_m("0101", '0', '1');
3115
		test_4_m("0110", '0', '1');
3116
		test_4_m("0111", '1', '0');
3117
		test_4_m("1000", '0', '0');
3118
		test_4_m("1001", '0', '1');
3119
		test_4_m("1010", '0', '1');
3120
		test_4_m("1011", '1', '0');
3121
		test_4_m("1100", '0', '1');
3122
		test_4_m("1101", '1', '0');
3123
		test_4_m("1110", '1', '0');
3124
		test_4_m("1111", '1', '0');
3125

3126
		wait;
3127
	end process;
3128
end architecture;
3129

3130
------------------------- Majority Voter ------------------------------------------------------
3131

3132
------------------------- Delay Line ----------------------------------------------------------
3133
-- 'DEPTH' * clock period delay line. Minimum delay of 0.
3134
--
3135
-- NB. It would be possible to create a delay line that would allow you to delay samples by
3136
-- varying amounts with a FIFO and a counter, which is sort of line a Run
3137
-- Length Compression Decoder. A sample and a counter would be pushed to the
3138
-- FIFO, the delay line mechanism would pull a sample/counter and hold the value
3139
-- for that amount of time.
3140

3141
library ieee, work;
3142
use ieee.std_logic_1164.all;
3143
use work.util.all;
3144

3145
entity delay_line is
3146
	generic (g: common_generics; width: positive; depth: natural);
3147
	port (
3148
		clk:  in std_ulogic;
3149
		rst:  in std_ulogic;
3150
		ce:   in std_ulogic := '1';
3151
		di:   in std_ulogic_vector(width - 1 downto 0);
3152
		do:  out std_ulogic_vector(width - 1 downto 0));
3153
end entity;
3154

3155
architecture behavior of delay_line is
3156
	type delay_line_t is array(integer range 0 to depth) of std_ulogic_vector(di'range);
3157
	signal sigs: delay_line_t := (others => (others => '0'));
3158
begin
3159
	sigs(0) <= di;
3160
	delay_line_generate: for i in 0 to depth generate
3161
		rest: if i > 0 generate
3162
			ux: work.util.reg
3163
				generic map (g => g, N => width)
3164
				port map (clk => clk, rst => rst, we => ce, di => sigs(i - 1), do => sigs(i));
3165
		end generate;
3166
	end generate;
3167
	do <= sigs(depth);
3168
end architecture;
3169

3170
library ieee, work;
3171
use ieee.std_logic_1164.all;
3172
use work.util.all;
3173

3174
entity delay_line_tb is
3175
	generic (g: common_generics);
3176
end entity;
3177

3178
architecture testing of delay_line_tb is
3179
	constant clock_period:  time     := 1000 ms / g.clock_frequency;
3180
	constant depth:       natural    := 2;
3181
	constant width:       positive   := 8;
3182
	signal clk, rst:      std_ulogic := '0';
3183
	signal stop:          std_ulogic := '0';
3184

3185
	signal di, do: std_ulogic_vector(width - 1 downto 0) := (others => '0');
3186
begin
3187
	cs: entity work.clock_source_tb
3188
		generic map (g => g, hold_rst => 2)
3189
		port map (stop => stop, clk => clk, rst => rst);
3190

3191
	uut: entity work.delay_line
3192
	generic map (g => g, depth => depth, width => width) port map (clk => clk, rst => rst, di => di, do => do, ce => '1');
3193

3194
	stimulus_process: process
3195
	begin
3196
		-- put a bit into the shift register and wait
3197
		-- for it to come out the other size
3198
		wait until rst = '0';
3199
		di <= x"AA";
3200
		wait for clock_period * 1;
3201
		di <= x"55";
3202
		wait for clock_period * 1;
3203
		di <= x"CC";
3204
		wait for clock_period * 1;
3205
		di <= x"DD";
3206
		assert do = x"AA" severity failure;
3207
		wait for clock_period * 1;
3208
		di <= x"00";
3209
		assert do = x"55" severity failure;
3210
		wait for clock_period * 1;
3211
		assert do = x"CC" severity failure;
3212
		wait for clock_period * 1;
3213
		assert do = x"DD" severity failure;
3214
		wait for clock_period * 1;
3215
		assert do = x"00" severity failure;
3216
		stop <= '1';
3217
		wait;
3218
	end process;
3219
end architecture;
3220

3221
------------------------- Delay Line ----------------------------------------------------------
3222

3223
------------------------- Gray CODEC ----------------------------------------------------------
3224

3225
library ieee, work;
3226
use ieee.std_logic_1164.all;
3227
use work.util.all;
3228

3229
entity gray_encoder is
3230
	generic (g: common_generics; N: positive);
3231
	port (di: in std_ulogic_vector(N - 1 downto 0);
3232
	     do: out std_ulogic_vector(N - 1 downto 0));
3233
end entity;
3234

3235
architecture behavior of gray_encoder is
3236
begin
3237
	gry: for i in N - 1 downto 0 generate
3238
		first: if i = (N - 1) generate
3239
			do(i) <= di(i);
3240
		end generate;
3241

3242
		rest: if i < (N - 1) generate
3243
			do(i) <= di(i + 1) xor di(i);
3244
		end generate;
3245
	end generate;
3246
end architecture;
3247

3248
library ieee, work;
3249
use ieee.std_logic_1164.all;
3250
use work.util.all;
3251

3252
entity gray_decoder is
3253
	generic (g: common_generics; N: positive);
3254
	port (di: in std_ulogic_vector(N - 1 downto 0);
3255
	     do: out std_ulogic_vector(N - 1 downto 0));
3256
end entity;
3257

3258
architecture behavior of gray_decoder is
3259
begin
3260
	gry: for i in N - 1 downto 0 generate
3261
		first: if i = (N - 1) generate
3262
			do(i) <= di(i) after g.delay;
3263
		end generate;
3264

3265
		rest: if i < (N - 1) generate
3266
			do(i) <= parity(di(N - 1 downto i), true) after g.delay;
3267
		end generate;
3268
	end generate;
3269
end architecture;
3270

3271
library ieee, work;
3272
use ieee.std_logic_1164.all;
3273
use work.util.all;
3274

3275
entity gray_tb is
3276
	generic (g: common_generics);
3277
end entity;
3278

3279
architecture testing of gray_tb is
3280
	constant clock_period:  time     := 1000 ms / g.clock_frequency;
3281
	constant n:           positive   := 3;
3282
	signal clk, rst:      std_ulogic := '0';
3283
	signal stop:          std_ulogic := '0';
3284

3285
	signal di, gray, do: std_ulogic_vector(n - 1 downto 0) := (others => '0');
3286
begin
3287
	cs: entity work.clock_source_tb
3288
		generic map (g => g, hold_rst => 2)
3289
		port map (stop => stop, clk => clk, rst => rst);
3290

3291
	uut_encode: entity work.gray_encoder
3292
	generic map (g => g, n => n) port map (di => di, do => gray);
3293

3294
	uut_decode: entity work.gray_decoder
3295
	generic map (g => g, n => n) port map (di => gray, do => do);
3296

3297
	stimulus_process: process
3298
		procedure test(slv: std_ulogic_vector) is
3299
		begin
3300
			di <= slv;
3301
			wait for clock_period * 1;
3302
			assert di = do severity failure;
3303
			wait for clock_period * 1;
3304
		end procedure;
3305
	begin
3306
		di <= (others => '0');
3307
		wait until rst = '0';
3308
		test("000");
3309
		test("001");
3310
		test("010");
3311
		test("011");
3312
		test("100");
3313
		test("101");
3314
		test("110");
3315
		test("111");
3316
		stop <= '1';
3317
		wait;
3318
	end process;
3319
end architecture;
3320

3321
------------------------- Gray CODEC ----------------------------------------------------------
3322

3323
------------------------- Parity Module -------------------------------------------------------
3324

3325
library ieee, work;
3326
use ieee.std_logic_1164.all;
3327
use work.util.all;
3328

3329
entity parity_module is
3330
	generic (g: common_generics; N: positive; even: boolean);
3331
	port (di: in std_ulogic_vector(N - 1 downto 0); do: out std_ulogic);
3332
end entity;
3333

3334
architecture behavior of parity_module is
3335
begin
3336
	do <= parity(di, even) after g.delay;
3337
end architecture;
3338

3339
------------------------- Parity Module -------------------------------------------------------
3340

3341
------------------------- Hamming CODEC  ------------------------------------------------------
3342
-- This is a Hamming encoder/decoder, with an extra parity bit. This can be used for error
3343
-- correction and detection across a noisy line.
3344
--
3345
-- See <https://en.wikipedia.org/wiki/Hamming_code> for more information.
3346
--
3347

3348
library ieee, work;
3349
use ieee.std_logic_1164.all;
3350
use work.util.all;
3351

3352
entity hamming_7_4_encoder is
3353
	generic (g: common_generics);
3354
	port (
3355
		di:      in std_ulogic_vector(3 downto 0);
3356
		do:     out std_ulogic_vector(6 downto 0);
3357
		parity: out std_ulogic);
3358
end entity;
3359

3360
architecture behavior of hamming_7_4_encoder is
3361
	signal p1, p2, p3: std_ulogic := '0';
3362
begin
3363
	p1 <= di(0) xor di(1) xor di(3) after g.delay;
3364
	p2 <= di(0) xor di(2) xor di(3) after g.delay;
3365
	p3 <= di(1) xor di(2) xor di(3) after g.delay;
3366
	do(0) <= p1    after g.delay;
3367
	do(1) <= p2    after g.delay;
3368
	do(2) <= di(0) after g.delay;
3369
	do(3) <= p3    after g.delay;
3370
	do(4) <= di(1) after g.delay;
3371
	do(5) <= di(2) after g.delay;
3372
	do(6) <= di(3) after g.delay;
3373
	parity <= p1 xor p2 xor p3 xor di(0) xor di(1) xor di(2) xor di(3);
3374
end architecture;
3375

3376
library ieee, work;
3377
use ieee.std_logic_1164.all;
3378
use ieee.numeric_std.all;
3379
use work.util.all;
3380

3381
entity hamming_7_4_decoder is
3382
	generic (g: common_generics; secdec: boolean := true);
3383
	port (
3384
		di:      in std_ulogic_vector(6 downto 0);
3385
		parity:  in std_ulogic;
3386
		do:     out std_ulogic_vector(3 downto 0);
3387
		single, double: out std_ulogic);
3388
end entity;
3389

3390
architecture behavior of hamming_7_4_decoder is
3391
	signal s:  std_ulogic_vector(2 downto 0) := (others => '0');
3392
	signal co, ct, dip: std_ulogic_vector(di'high + 1 downto 0)   := (others => '0');
3393
	signal cp: std_ulogic := '0';
3394
	signal unequal: std_ulogic := '0';
3395
begin
3396
	s(2) <= di(3) xor di(4) xor di(5) xor di(6) after g.delay;
3397
	s(1) <= di(1) xor di(2) xor di(5) xor di(6) after g.delay;
3398
	s(0) <= di(0) xor di(2) xor di(4) xor di(6) after g.delay;
3399

3400
	do(0) <= co(2) after g.delay;
3401
	do(1) <= co(4) after g.delay;
3402
	do(2) <= co(5) after g.delay;
3403
	do(3) <= co(6) after g.delay;
3404

3405
	cp <= '0' when not secdec else di(0) xor di(1) xor di(2) xor di(3) xor di(4) xor di(5) xor di(6) after g.delay;
3406

3407
	dip(dip'high) <= parity when secdec else '0' after g.delay;
3408
	dip(di'range) <= di after g.delay;
3409

3410
	unequal <= '1' when ct(di'range) /= dip(di'range) else '0' after g.delay;
3411

3412
	process (dip, s)
3413
	begin
3414
		ct <= dip after g.delay;
3415
		ct(to_integer(unsigned(s) - 1)) <= not dip(to_integer(unsigned(s) - 1)) after g.delay;
3416
	end process;
3417

3418
	process (s, dip, parity, ct, cp, unequal)
3419
	begin
3420
		co <= dip;
3421
		single <= '0';
3422
		double <= '0';
3423

3424
		if secdec and parity /= cp then
3425
			if unequal = '1' then
3426
				single <= '1';
3427
				co <= ct;
3428
			end if;
3429
		else
3430
			if unequal = '1' then
3431
				if secdec then
3432
					double <= '1';
3433
				else
3434
					single <= '1';
3435
					co <= ct;
3436
				end if;
3437
			end if;
3438
		end if;
3439
	end process;
3440
end architecture;
3441

3442
library ieee, work;
3443
use ieee.std_logic_1164.all;
3444
use work.util.all;
3445
use ieee.numeric_std.all;
3446
use ieee.math_real.all;
3447

3448
entity hamming_7_4_tb is
3449
	generic (g: common_generics);
3450
end entity;
3451

3452
architecture testing of hamming_7_4_tb is
3453
	constant clock_period:  time     := 1000 ms / g.clock_frequency;
3454
	constant n:           positive   := 3;
3455
	signal clk, rst:      std_ulogic := '0';
3456
	signal stop:          std_ulogic := '0';
3457
	signal di, do, do_s: std_ulogic_vector(3 downto 0) := (others => '0');
3458
	signal encoded_tx, encoded_rx, ebit: std_ulogic_vector(6 downto 0) := (others => '0');
3459
	signal parity, single, double: std_ulogic := '0';
3460
	signal parity_s, single_s, double_s: std_ulogic := '0';
3461
begin
3462
	cs: entity work.clock_source_tb
3463
		generic map (g => g, hold_rst => 2)
3464
		port map (stop => stop, clk => clk, rst => rst);
3465

3466
	uut_encode: entity work.hamming_7_4_encoder
3467
	generic map (g => g) port map (di => di, do => encoded_tx, parity => parity);
3468

3469
	lossy_channel: process(encoded_tx)
3470
		variable seed1, seed2: positive;
3471
		variable r: real;
3472
		variable i: integer range 0 to 7;
3473
	begin
3474
		encoded_rx    <= encoded_tx;
3475
		uniform(seed1, seed2, r);
3476
		if r > 0.5 then
3477
			uniform(seed1, seed2, r);
3478
			i := integer(floor(r * 6.99));
3479
			encoded_rx(i) <= not encoded_tx(i);
3480
			uniform(seed1, seed2, r);
3481
		end if;
3482
		if r > 0.5 then
3483
			uniform(seed1, seed2, r);
3484
			i := integer(floor(r * 6.99));
3485
			encoded_rx(i) <= not encoded_tx(i);
3486
		end if;
3487
	end process;
3488

3489
	ebit <= encoded_tx xor encoded_rx;
3490

3491
	uut_decode_secdec: entity work.hamming_7_4_decoder
3492
	generic map (g => g) port map (di => encoded_rx, do => do, parity => parity, single => single, double => double);
3493

3494
	uut_decode_single: entity work.hamming_7_4_decoder
3495
	generic map (g => g, secdec => false) port map (di => encoded_rx, do => do_s, parity => parity_s, single => single_s, double => double_s);
3496

3497
	stimulus_process: process
3498
		procedure test(slv: std_ulogic_vector) is
3499
		begin
3500
			di <= slv;
3501
			wait for clock_period * 2;
3502
			if bit_count_f(ebit) = 2 then
3503
				assert double = '1' severity failure;
3504
				assert single = '0' severity failure;
3505
			elsif bit_count_f(ebit) = 1 then
3506
				assert di = do severity failure;
3507
				assert single = '1' severity failure;
3508
				assert double = '0' severity failure;
3509

3510
				assert di = do_s severity failure;
3511
				assert single_s = '1' severity failure;
3512
			else
3513
				assert di = do severity failure;
3514
				assert double = '0' severity failure;
3515
				assert single = '0' severity failure;
3516

3517
				assert di = do_s severity failure;
3518
				assert single_s = '0' severity failure;
3519
			end if;
3520
			wait for clock_period * 2;
3521
		end procedure;
3522
		variable ii: unsigned(7 downto 0) := (others => '1');
3523
	begin
3524
		di <= (others => '0');
3525
		wait until rst = '0';
3526

3527
		while ii /= x"00" loop
3528
			ii := ii - 1;
3529
			test(std_ulogic_vector(ii(3 downto 0)));
3530
		end loop;
3531
		stop <= '1';
3532
		wait;
3533
	end process;
3534

3535
end architecture;
3536

3537
------------------------- Hamming CODEC  ------------------------------------------------------
3538

3539
------------------------- VGA Controller ------------------------------------------------------
3540
-- VGA Controller
3541
--
3542
-- See:
3543
--  * <https://en.wikipedia.org/wiki/Video_Graphics_Array>
3544
--  * <http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/1998_w/Altera_UP1_Board_Map/vga.html>
3545
--  * <https://www.digikey.com/eewiki/pages/viewpage.action?pageId=15925278>
3546
--
3547
-- This purpose of this VGA controller is to provide the necessary VGA
3548
-- timings for a given resolution (which has to be determined at instantiation
3549
-- time and cannot be configured on the fly). The VGA controller will generate
3550
-- the correct HSYNC and VSYNCH signals needed, as well as the current row and
3551
-- column that is currently being drawn. This can be used to generate an image.
3552
--
3553
-- Example timing for 640 x 480:
3554
--
3555
--  |-----800 pixels / 31.778 us---------|
3556
--  |-----640 Pixels--------|-160 Pixels-|
3557
--  |-----25.422 us---------|--5.75 us---|
3558
--  
3559
--  +-----------------------+------------+   VSYNC
3560
--  |                       |         ^  |     |
3561
--  |                       |         |  |     |
3562
--  |                       |         |  |     |
3563
--  |    Display Period     |   480 Rows |     |
3564
--  |                       |         |  |     |
3565
--  |                       |         |  |     |
3566
--  |                       |         |  |     |
3567
--  |                       |         v  |     |
3568
--  +-----------------------+        --- |     |
3569
--  |                                 ^  |    _| <- Front porch 0.318 ms (10 rows)
3570
--  |                                 |  |   |
3571
--  |      Blanking Period       45 Rows |   | <--- VSYNC pulse 0.064 ms (2 rows)
3572
--  |                                 |  |   |_
3573
--  |                                 v  |     | <- Back porch 1.048 ms (33 rows)
3574
--  +------------------------------------+     |
3575
--                                 
3576
--                              ___
3577
--  ___________________________|   |_____ HSYNC
3578
--                            ^  ^  ^
3579
--  0.636 us   Front Porch __/  /  / <-(16 pixels)
3580
--  3.813 us   HSYNC Pulse ____/  /  <-(96 pixels)
3581
--  1.907 us   Back Porch _______/   <-(48 pixels)
3582
--
3583

3584
library ieee, work;
3585
use ieee.std_logic_1164.all;
3586
use work.util.all;
3587

3588
entity vga_controller is
3589
	generic (
3590
		g: common_generics;
3591
		pixel_clock_frequency:  positive := 25_000_000;
3592
		constant cfg: vga_configuration  := vga_640x480);
3593
	port (
3594
		clk, rst:          in std_ulogic;
3595
		h_sync, v_sync:   out std_ulogic;
3596
		h_blank, v_blank: out std_ulogic;
3597
		column, row:      out integer);
3598
end entity;
3599

3600
architecture behavior of vga_controller is
3601
	constant h_period: integer := cfg.h_pulse + cfg.h_back_porch + cfg.h_pixels + cfg.h_front_porch; -- number of pixel clocks in a row
3602
	constant v_period: integer := cfg.v_pulse + cfg.v_back_porch + cfg.v_pixels + cfg.v_front_porch; -- number of rows in column
3603
	signal h_sync_internal, v_sync_internal: std_ulogic := '0';
3604
begin
3605
	-- The clock does not need to be exactly the correct value
3606
	assert pixel_clock_frequency <= (cfg.clock_frequency + 250_000)
3607
		and pixel_clock_frequency >= (cfg.clock_frequency - 250_000) severity warning;
3608

3609
	h_sync <= h_sync_internal xor cfg.h_polarity;
3610
	v_sync <= v_sync_internal xor cfg.v_polarity;
3611

3612
	process (clk, rst)
3613
		constant h_start: integer := cfg.h_pixels + cfg.h_front_porch;
3614
		constant h_end:   integer := cfg.h_pixels + cfg.h_front_porch + cfg.h_pulse;
3615
		constant v_start: integer := cfg.v_pixels + cfg.v_front_porch;
3616
		constant v_end:   integer := cfg.v_pixels + cfg.v_front_porch + cfg.v_pulse;
3617
		variable h_count: integer range 0 to h_period - 1 := 0;  -- horizontal counter (counts the columns)
3618
		variable v_count: integer range 0 to v_period - 1 := 0;  -- vertical counter (counts the rows)
3619
		procedure reset is
3620
		begin
3621
			h_count         := 0;
3622
			v_count         := 0;
3623
			h_blank         <= '0' after g.delay;
3624
			v_blank         <= '0' after g.delay;
3625
			column          <= 0 after g.delay;
3626
			row             <= 0 after g.delay;
3627
		end procedure;
3628
	begin
3629
		if rst = '1' and g.asynchronous_reset then
3630
			reset;
3631
		elsif rising_edge(clk) then
3632
			if rst = '1' and not g.asynchronous_reset then
3633
				reset;
3634
			else
3635
				if h_count < (h_period - 1) then -- pixel count
3636
					h_count := h_count + 1;
3637
				else
3638
					if v_count < (v_period - 1) then -- row count
3639
						v_count := v_count + 1;
3640
					else
3641
						v_count := 0;
3642
					end if;
3643
					h_count := 0;
3644
				end if;
3645

3646
				h_sync_internal <= not logical((h_count < h_start) or (h_count >= h_end)) after g.delay;
3647
				v_sync_internal <= not logical((v_count < v_start) or (v_count >= v_end)) after g.delay;
3648

3649
				column <= cfg.h_pixels - 1;
3650
				row    <= cfg.v_pixels - 1;
3651

3652
				if h_count < cfg.h_pixels then h_blank <= '0'; column <= h_count; else h_blank <= '1'; end if;
3653
				if v_count < cfg.v_pixels then v_blank <= '0'; row    <= v_count; else v_blank <= '1'; end if;
3654
			end if;
3655
		end if;
3656
	end process;
3657
end architecture;
3658

3659
library ieee, work;
3660
use ieee.std_logic_1164.all;
3661
use ieee.numeric_std.all;
3662
use work.util.all;
3663

3664
entity vga_tb is
3665
	generic (g: common_generics; pixel_clock_frequency: positive := 25_000_000; simulation_us: time := 20000 us);
3666
end entity;
3667

3668
architecture testing of vga_tb is
3669
	constant pixel_clock_period: time   := 1000 ms / pixel_clock_frequency;
3670
	signal rst, clk:        std_ulogic  := '1';
3671
	signal stop:            boolean     := false;
3672
	signal h_sync, v_sync:  std_ulogic  := 'X';
3673
	signal h_blank, v_blank: std_ulogic := 'X';
3674
	signal column, row:     integer     := 0;
3675
begin
3676
	duration: process begin wait for simulation_us; stop <= true; wait; end process;
3677
	clk_process: process
3678
	begin
3679
		rst <= '1';
3680
		wait for pixel_clock_period * 5;
3681
		rst <= '0';
3682
		while not stop loop
3683
			clk <= '1';
3684
			wait for pixel_clock_period / 2;
3685
			clk <= '0';
3686
			wait for pixel_clock_period / 2;
3687
		end loop;
3688
		wait;
3689
	end process;
3690

3691
	uut: work.util.vga_controller
3692
		generic map (g => g, pixel_clock_frequency => pixel_clock_frequency)
3693
		port map (
3694
			rst     => rst,
3695
			clk     => clk,
3696
			h_sync  => h_sync,
3697
			v_sync  => v_sync,
3698
			h_blank => h_blank,
3699
			v_blank => v_blank,
3700
			column  => column,
3701
			row     => row);
3702
end architecture;
3703

3704
------------------------- VGA Controller ------------------------------------------------------
3705

3706
------------------------- LED Controller ------------------------------------------------------
3707
--| This module implements a 7 segment display (plus decimal point) driver,
3708
--|  with 4 displays in total:
3709
--|
3710
--|    _____________________ an (selects segment)
3711
--|    |     |     |     |
3712
--|   __    __    __    __
3713
--|  |  |  |  |  |  |  |  |
3714
--|  |__|  |__|  |__|  |__|
3715
--|  |  |  |  |  |  |  |  |
3716
--|  |__|. |__|. |__|. |__|.
3717
--|   |____|_____|_____|____ ka (value to display on segment)
3718
--|
3719
--| Each of the display shares a common anode for all of its LEDs, this can be
3720
--| used to select an individual display
3721

3722
library ieee, work;
3723
use ieee.std_logic_1164.all;
3724
use ieee.numeric_std.all;
3725
use work.util.all;
3726

3727
entity led_7_segment_display is
3728
	generic (
3729
		g:                      common_generics;
3730
		use_bcd_not_hex:        boolean  := true;
3731
		refresh_rate_us:        natural  := 1500;
3732
		number_of_led_displays: positive := 4);
3733
	port (
3734
		clk:      in   std_ulogic;
3735
		rst:      in   std_ulogic;
3736

3737
		leds_we:  in   std_ulogic;
3738
		leds:     in   std_ulogic_vector((number_of_led_displays * led_7_segment_character_length) - 1 downto 0);
3739

3740
		-- Physical outputs
3741
		an:       out  std_ulogic_vector(number_of_led_displays - 1 downto 0);  -- anodes, controls on/off
3742
		ka:       out  std_ulogic_vector(7 downto 0)); -- cathodes, data on display
3743
end;
3744

3745
architecture rtl of led_7_segment_display is
3746

3747
	-- This lookup table converts a BCD character into a value
3748
	-- that can be displayed on an 7 segment display. The layout of which
3749
	-- is as follows:
3750
	--
3751
	--       A
3752
	--      ---
3753
	--   F |   | B
3754
	--     |___|
3755
	--   E | G | C
3756
	--     |___| . DP
3757
	--       D
3758
	--
3759
	-- The following encoding is used to convert the input BCD character
3760
	-- into a value that can be put onto the display.
3761
	--
3762
	--  -----------------------------------------
3763
	-- |   | DP| G | F | E | D | C | B | A | Hex |
3764
	-- |BCD| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |Hi Lo|
3765
	--  -----------------------------------------
3766
	-- | 0 |   |   | 1 | 1 | 1 | 1 | 1 | 1 | 3 F |
3767
	-- | 1 |   |   |   |   |   | 1 | 1 |   | 0 6 |
3768
	-- | 2 |   | 1 |   | 1 | 1 |   | 1 | 1 | 5 B |
3769
	-- | 3 |   | 1 |   |   | 1 | 1 | 1 | 1 | 4 F |
3770
	-- | 4 |   | 1 | 1 |   |   | 1 | 1 |   | 6 6 |
3771
	-- | 5 |   | 1 | 1 |   | 1 | 1 |   | 1 | 6 D |
3772
	-- | 6 |   | 1 | 1 | 1 | 1 | 1 |   | 1 | 7 D |
3773
	-- | 7 |   |   |   |   |   | 1 | 1 | 1 | 0 7 |
3774
	-- | 8 |   | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 7 F |
3775
	-- | 9 |   | 1 | 1 |   | 1 | 1 | 1 | 1 | 6 F |
3776
	-- |   |   |   |   |   |   |   |   |   | 0 0 |
3777
	-- | . | 1 |   |   |   |   |   |   |   | 8 0 |
3778
	-- | - |   | 1 |   |   |   |   |   |   | 4 0 |
3779
	--  -----------------------------------------
3780
	-- | A |   | 1 | 1 | 1 |   | 1 | 1 | 1 | 7 7 |
3781
	-- | b |   | 1 | 1 | 1 | 1 | 1 |   |   | 7 C |
3782
	-- | C |   |   | 1 | 1 | 1 |   |   | 1 | 3 9 |
3783
	-- | d |   | 1 |   | 1 | 1 | 1 | 1 |   | 5 E |
3784
	-- | E |   | 1 | 1 | 1 | 1 |   |   | 1 | 7 9 |
3785
	-- | F |   | 1 | 1 | 1 |   |   |   | 1 | 7 1 |
3786
	--  -----------------------------------------
3787
	--
3788
	-- The table is then inverted before it goes to the output.
3789
	--
3790

3791
	function hex_to_7_segment(a: led_7_segment_character) return led_7_segment is
3792
		variable r: std_ulogic_vector(7 downto 0) := x"00";
3793
	begin
3794
		-- NB. You may have thought a case statement would be the best
3795
		-- way of doing this, and you would be right. However, Xilinx ISE
3796
		-- issues annoying 'INFO' statements when you do - thanks Xilinx!
3797
		-- The generated hardware is the same however.
3798
		   if a = "0000" then r := x"3F"; -- 0
3799
		elsif a = "0001" then r := x"06"; -- 1
3800
		elsif a = "0010" then r := x"5B"; -- 2
3801
		elsif a = "0011" then r := x"4F"; -- 3
3802
		elsif a = "0100" then r := x"66"; -- 4
3803
		elsif a = "0101" then r := x"6D"; -- 5
3804
		elsif a = "0110" then r := x"7D"; -- 6
3805
		elsif a = "0111" then r := x"07"; -- 7
3806
		elsif a = "1000" then r := x"7F"; -- 8
3807
		elsif a = "1001" then r := x"6F"; -- 9
3808
		elsif a = "1010" then r := x"77"; -- A
3809
		elsif a = "1011" then r := x"7C"; -- b
3810
		elsif a = "1100" then r := x"39"; -- C
3811
		elsif a = "1101" then r := x"5E"; -- d
3812
		elsif a = "1110" then r := x"79"; -- E
3813
		elsif a = "1111" then r := x"71"; -- F
3814
		end if;
3815
		return r;
3816
	end function;
3817

3818
	function bcd_to_7_segment(a: led_7_segment_character) return led_7_segment is
3819
		variable r: std_ulogic_vector(7 downto 0) := x"00";
3820
	begin
3821
		case a is
3822
			when "0000" => r := x"3F"; -- 0
3823
			when "0001" => r := x"06"; -- 1
3824
			when "0010" => r := x"5B"; -- 2
3825
			when "0011" => r := x"4F"; -- 3
3826
			when "0100" => r := x"66"; -- 4
3827
			when "0101" => r := x"6D"; -- 5
3828
			when "0110" => r := x"7D"; -- 6
3829
			when "0111" => r := x"07"; -- 7
3830
			when "1000" => r := x"7F"; -- 8
3831
			when "1001" => r := x"6F"; -- 9
3832
			when "1010" => r := x"00"; -- Blank
3833
			when "1011" => r := x"80"; -- .
3834
			when "1100" => r := x"40"; -- -
3835
			when "1101" => r := x"00"; -- Unused
3836
			when "1110" => r := x"00"; -- Unused
3837
			when "1111" => r := x"00"; -- Unused
3838
			when others => r := x"00"; -- Unused
3839
		end case;
3840
		return r;
3841
	end function;
3842

3843
	function char_to_7_segment(a: led_7_segment_character) return led_7_segment is
3844
	begin
3845
		if use_bcd_not_hex then
3846
			return invert(bcd_to_7_segment(a));
3847
		else
3848
			return invert(hex_to_7_segment(a));
3849
		end if;
3850
	end function;
3851

3852
	signal leds_o: std_ulogic_vector(leds'range) := (others => '0');
3853

3854
	signal do_shift:  std_ulogic := '0';
3855
	signal shift_reg: std_ulogic_vector(number_of_led_displays - 1 downto 0);
3856

3857
	signal leds_reg_o: std_ulogic_vector(leds'range) := (others => '0');
3858
	signal leds_reg_we_o: std_ulogic := '0';
3859
begin
3860
	an <= invert(shift_reg) after g.delay;
3861

3862
	segment_reg: entity work.reg
3863
		generic map (g => g, N => number_of_led_displays * led_7_segment_character_length)
3864
		port map (
3865
			clk => clk,
3866
			rst => rst,
3867
			we  => leds_we,
3868
			di  => leds,
3869
			do  => leds_reg_o);
3870

3871
	segment_reg_re: entity work.reg
3872
		generic map (g => g, N => 1)
3873
		port map (
3874
			clk   => clk,
3875
			rst   => rst,
3876
			we    => '1',
3877
			di(0) => leds_we,
3878
			do(0) => leds_reg_we_o);
3879

3880
	led_gen: for i in number_of_led_displays - 1 downto 0 generate
3881
		led_i: entity work.reg
3882
			generic map (g => g, N => led_7_segment_character_length)
3883
			port map (
3884
				clk => clk,
3885
				rst => rst,
3886
				we  => leds_reg_we_o,
3887
				di  => leds_reg_o((i*led_7_segment_character_length) + led_7_segment_character_length - 1 downto (i*led_7_segment_character_length)),
3888
				do  => leds_o((i*led_7_segment_character_length) + led_7_segment_character_length - 1 downto (i*led_7_segment_character_length)));
3889
	end generate;
3890

3891
	timer: entity work.timer_us
3892
		generic map (g => g, timer_period_us => refresh_rate_us)
3893
		port map (
3894
			clk             => clk,
3895
			rst             => rst,
3896
			co              => do_shift);
3897

3898
	process(rst, clk, do_shift, shift_reg)
3899
	begin
3900
		if rst = '1' and g.asynchronous_reset then
3901
			shift_reg    <= (others => '0') after g.delay;
3902
			shift_reg(0) <= '1' after g.delay;
3903
		elsif rising_edge(clk) then
3904
			if rst = '1' and not g.asynchronous_reset then
3905
				shift_reg    <= (others => '0') after g.delay;
3906
				shift_reg(0) <= '1' after g.delay;
3907
			else
3908
				if do_shift = '1' then
3909
					shift_reg <= shift_reg(number_of_led_displays - 2 downto 0) & shift_reg(number_of_led_displays - 1) after g.delay;
3910
				else
3911
					shift_reg <= shift_reg after g.delay;
3912
				end if;
3913
			end if;
3914
		end if;
3915
	end process;
3916

3917
	process(leds_o, shift_reg)
3918
	begin
3919
		ka <= (others => '0');
3920
		for i in  number_of_led_displays - 1 downto 0 loop
3921
			if '1' = shift_reg(number_of_led_displays - i - 1) then
3922
				ka <= char_to_7_segment(leds_o(i*led_7_segment_character_length + led_7_segment_character_length - 1 downto (i*led_7_segment_character_length))) after g.delay;
3923
			end if;
3924
		end loop;
3925
	end process;
3926
end architecture;
3927

3928
library ieee, work;
3929
use ieee.std_logic_1164.all;
3930
use ieee.numeric_std.all;
3931
use work.util.all;
3932

3933
entity led_7_segment_display_tb is
3934
	generic (g: common_generics);
3935
end entity;
3936

3937
architecture testing of led_7_segment_display_tb is
3938
	constant clock_period:  time     := 1000 ms / g.clock_frequency;
3939
	signal clk, rst:      std_ulogic := '0';
3940
	signal stop:          std_ulogic := '0';
3941

3942
	constant number_of_led_displays: positive := 4;
3943
	signal an: std_ulogic_vector(number_of_led_displays - 1 downto 0);
3944
	signal ka: std_ulogic_vector(7 downto 0);
3945
	signal leds_we: std_ulogic;
3946
	signal leds:    std_ulogic_vector((number_of_led_displays * led_7_segment_character_length) - 1 downto 0);
3947
begin
3948
	cs: entity work.clock_source_tb
3949
		generic map (g => g, hold_rst => 2)
3950
		port map (stop => stop, clk => clk, rst => rst);
3951

3952
	-- We have a very fast refresh rate here, just for testing purposes.
3953
	uut: entity work.led_7_segment_display
3954
		generic map (g => g, refresh_rate_us => 1)
3955
		port map (clk => clk, rst => rst, leds_we => leds_we, leds => leds, an => an, ka => ka);
3956

3957
	stimulus_process: process
3958
	begin
3959
		wait for clock_period * 2;
3960
		leds_we <= '1';
3961
		leds <= x"1234";
3962
		wait for clock_period * 1;
3963
		leds_we <= '0';
3964
		wait for clock_period * 1000;
3965
		stop <= '1';
3966
		wait;
3967
	end process;
3968

3969
end architecture;
3970

3971
------------------------- LED Controller ------------------------------------------------------
3972

3973
------------------------- Sine / Cosine  ------------------------------------------------------
3974
-- Sine / Cosine calculation using multiplication
3975
-- Half-inched from <https://github.com/jamesbowman/sincos>
3976
-- Angles are input as signed Furmans (1 Furman = (1/pow(2, 16) of a circle))
3977
-- 1 Degree is ~182 Furmans. 1 rad is ~10430 Furmans.
3978
-- Result is signed scaled 16-bit integer; -1 = -32767, +1 = 32767
3979
--
3980
library ieee, work;
3981
use ieee.std_logic_1164.all;
3982
use ieee.numeric_std.all;
3983
use work.util.all;
3984

3985
entity sine is
3986
	generic (g: common_generics; pipeline: boolean := true);
3987
	port (
3988
		clk, rst, xwe: in std_ulogic;
3989
		x:  in  std_ulogic_vector(15 downto 0);
3990
		s:  out std_ulogic_vector(15 downto 0));
3991
end entity;
3992

3993
architecture behavior of sine is
3994
	subtype val is signed(x'range);
3995
	subtype mul is signed((val'high * 2) + 1 downto 0);
3996
	function half_multiply_add(a, b, c: val) return val is
3997
		variable t: mul;
3998
		variable r: val;
3999
	begin
4000
		t := a * b;
4001
		r := t(t'high downto r'high + 1) + c;
4002
		return r;
4003
	end function;
4004
	signal n: signed(2 downto 0);
4005
	signal xn, z, y, sums, sumc, sum1, cc,  t0, t1, t0n, t1n, sa, so: val;
4006
	signal cc32: mul;
4007
	signal xnslv, t0nslv, t1nslv: std_ulogic_vector(x'range);
4008
begin
4009
	pipe_0: if pipeline generate
4010
		reg_in: work.util.reg
4011
			generic map (g => g, N => x'length)
4012
			port map (clk => clk, rst => rst, we => xwe, di => x, do => xnslv);
4013
		reg_out: work.util.reg
4014
			generic map (g => g, N => x'length)
4015
			port map (clk => clk, rst => rst, we => '1', di => std_ulogic_vector(so), do => s);
4016
		xn  <= signed(xnslv);
4017
		t0n <= signed(t0); -- also need to delay n
4018
		t1n <= signed(t1); -- also need to delay n
4019
	end generate;
4020
	no_pipe_0: if not pipeline generate
4021
		xn <= signed(x);
4022
		s  <= std_ulogic_vector(so) after g.delay;
4023
		t0n <= t0;
4024
		t1n <= t1;
4025
	end generate;
4026

4027
	y(1 downto 0)  <= (others => '0') after g.delay;
4028
	y(15 downto 2) <= signed(xn(13 downto 0)) after g.delay;
4029
	n    <= signed(xn(15 downto 13)) + "01" after g.delay;
4030
	z    <= half_multiply_add(y, y,        x"0000") after g.delay;
4031
	sumc <= half_multiply_add(z, x"0FBD", -x"4EE9") after g.delay;
4032
	sums <= half_multiply_add(z, x"04F8", -x"2953") after g.delay;
4033
	sum1 <= half_multiply_add(z, sums,     x"6487") after g.delay;
4034
	t0   <= z    when n(1) = '1' else y after g.delay;
4035
	t1   <= sumc when n(1) = '1' else sum1 after g.delay;
4036
	cc32 <= t0n * t1n after g.delay;
4037
	cc   <= cc32(cc32'high - 1 downto cc'high) after g.delay;
4038
	sa   <= cc + x"7FFF" when n(1) = '1' else cc after g.delay;
4039
	so   <= -sa when n(2) = '1' else sa after g.delay;
4040
end architecture;
4041

4042
library ieee, work;
4043
use ieee.std_logic_1164.all;
4044
use ieee.numeric_std.all;
4045
use work.util.all;
4046

4047
entity cosine is
4048
	generic (g: common_generics; pipeline: boolean := true);
4049
	port (
4050
		clk, rst, xwe: in std_ulogic;
4051
		x:  in  std_ulogic_vector(15 downto 0);
4052
		c:  out std_ulogic_vector(15 downto 0));
4053
end entity;
4054

4055
architecture behavior of cosine is
4056
	signal xn: std_ulogic_vector(c'range);
4057
begin
4058
	xn <= std_ulogic_vector(signed(x) + x"4000");
4059
	calc: entity work.sine
4060
		generic map(g => g, pipeline => pipeline) port map(clk => clk, rst => rst, xwe => xwe, x => xn, s => c);
4061
end architecture;
4062

4063
library ieee, work;
4064
use ieee.std_logic_1164.all;
4065
use ieee.numeric_std.all;
4066
use work.util.all;
4067

4068
entity sine_tb is
4069
	generic (g: common_generics);
4070
end entity;
4071

4072
architecture testing of sine_tb is
4073
	constant clock_period:  time     := 1000 ms / g.clock_frequency;
4074
	signal clk, rst:      std_ulogic := '0';
4075
	signal stop:          std_ulogic := '0';
4076

4077
	constant number_of_led_displays: positive := 4;
4078
	signal x: std_ulogic_vector(15 downto 0);
4079
	signal s, c: std_ulogic_vector(x'range);
4080
begin
4081
	cs: entity work.clock_source_tb
4082
		generic map (g => g, hold_rst => 2)
4083
		port map (stop => stop, clk => clk, rst => rst);
4084

4085
	uut_c: entity work.sine   generic map (g => g) port map (clk => clk, rst => rst, xwe => '1', x => x, s => s);
4086
	uut_s: entity work.cosine generic map (g => g) port map (clk => clk, rst => rst, xwe => '1', x => x, c => c);
4087

4088
	stimulus_process: process
4089
		variable cnt: integer := -32768;
4090
	begin
4091
		x <= std_ulogic_vector(to_signed(cnt, x'length));
4092
		wait for clock_period * 2;
4093
		while cnt < 32768 loop
4094
			x <= std_ulogic_vector(to_signed(cnt, x'length));
4095
			wait for clock_period * 10;
4096
			cnt := cnt + 182;
4097
		end loop;
4098
		stop <= '1';
4099
		wait;
4100
	end process;
4101
end architecture;
4102
------------------------- Sine / Cosine  ------------------------------------------------------
4103

4104

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

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

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

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