1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.read_intel_hex_pack.all;
entity tb_pic is
generic (
CLK_FREQ : positive := 50_000_000; -- 50M, GW5A clock
BAUD_RATE : positive := 115_200
);
end entity tb_pic;
architecture behavioural of tb_pic is
constant T_clk : time := 20 ns; -- 50M
constant HEX_FILE : string := "build/program.hex";
constant SIM_CYCLES : integer := 800_000;
signal clk : std_logic := '0';
signal reset : std_logic := '1';
signal opcode : std_logic_vector(13 downto 0);
signal program_counter : std_logic_vector(12 downto 0);
signal work_reg : std_logic_vector(7 downto 0);
signal status : std_logic_vector(2 downto 0);
signal port_a : std_logic_vector(7 downto 0);
signal port_b : std_logic_vector(7 downto 0);
signal done : boolean := false;
signal uart_tx : std_logic;
signal uart_rx : std_logic := '1'; -- idle high (no incoming bytes)
-- program memory: 1024 x 14-bit
signal prog_mem : program_array := (others => (others => '0'));
signal byte_in : std_logic_vector(7 downto 0);
signal tx_should_send : std_logic;
begin
clk <= not clk after T_clk / 2 when not done else unaffected;
-- drive opcode from program memory using PC
opcode <= prog_mem(to_integer(unsigned(program_counter)));
dut : entity work.PIC(rtl)
generic map (
CLK_FREQ => 50_000_000 -- 10 MHz, matches T_clk = 100 ns
)
port map (
clk => clk,
reset => reset,
opcode => opcode,
program_counter => program_counter,
work_reg => work_reg,
status => status,
port_a => port_a,
port_b => port_b,
uart_tx => uart_tx,
uart_rx => uart_rx
);
tx_should_send <= '1';
byte_in <= x"FC";
uart_master: entity work.uart
generic map (
CLK_FREQ => CLK_FREQ,
BAUD_RATE => BAUD_RATE,
CLKS_PER_BIT => CLK_FREQ / BAUD_RATE)
port map (
clk => clk,
tx_should_send => tx_should_send,
byte_in => byte_in,
tx_done => open,
baud_tick => open,
uart_tx => uart_rx,
uart_rx => uart_tx,
rd_en => '0',
rx_data => open,
rx_empty => open,
rx_full => open);
stimulus : process is
variable mem : program_array;
begin
-- load hex file into program memory
read_ihex_file(HEX_FILE, mem);
prog_mem <= mem;
-- reset pulse
reset <= '1';
wait for T_clk * 2;
reset <= '0';
-- run for SIM_CYCLES instruction cycles
for i in 0 to SIM_CYCLES - 1 loop
wait until rising_edge(clk);
end loop;
report "simulation done. port_a=" & integer'image(to_integer(unsigned(port_a)))
& " port_b=" & integer'image(to_integer(unsigned(port_b)))
severity note;
done <= true;
wait;
end process stimulus;
end architecture behavioural;
|