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;