----------------------------------------------------------------- -- uCore 1.90 - bench.vhd -- ----------------------------------------------------------------- -- -- Author: KLAUS SCHLEISIEK -- Last change: KS 08.12.2015 12:02:27 -- -- Do not use this file except in compliance with the License. You may -- obtain a copy of the License at http://www.microcore.org/License/ -- Software distributed under the License is distributed on an "AS IS" basis, -- WITHOUT WARRANTY OF ANY KIND, either express or implied. -- See the License for the specific language governing rights and limitations -- under the License. -- -- The Initial Developer of the Original Code is Klaus.Schleisiek AT microcore.org. -- -- Test bench for MicroCore with RS232 debug interface. -- After reset, the object code will be loaded via the umbilical and executed -- when prog_len > 0, otherwise boot_rom.vhd will be executed LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_signed.ALL; USE work.functions.ALL; USE work.constants.ALL; ENTITY bench IS END bench; ARCHITECTURE testbench OF bench IS COMPONENT fpga PORT (reset_n : IN STD_LOGIC; clk_in : IN STD_LOGIC; -- system clock from global clock buffer int_n : IN STD_LOGIC; -- external interrupt input -- data space io_ce_n : OUT STD_LOGIC; io_we_n : OUT STD_LOGIC; io_oe_n : OUT STD_LOGIC; io_addr : OUT data_addr; io_data : INOUT data_bus; -- umbilical port for debugging rxd : IN STD_LOGIC; -- incoming asynchronous data stream txd : OUT STD_LOGIC -- outgoing data stream ); END COMPONENT; COMPONENT program_rom PORT (addr : IN program_addr; data : OUT inst_bus); END COMPONENT; SIGNAL reset_n : STD_LOGIC; SIGNAL clk : STD_LOGIC; SIGNAL int_n : STD_LOGIC; SIGNAL io_ce_n : STD_LOGIC; SIGNAL io_we_n : STD_LOGIC; SIGNAL io_oe_n : STD_LOGIC; SIGNAL io_addr : data_addr; SIGNAL io_data : data_bus; SIGNAL debug_data : inst_bus; SIGNAL debug_addr : program_addr; SIGNAL tx_buf : byte; SIGNAL send_ack : STD_LOGIC; SIGNAL send_debug : STD_LOGIC; SIGNAL sending : STD_LOGIC; SIGNAL host_reg : STD_LOGIC_VECTOR((data_nibbles*8)-1 DOWNTO 0); SIGNAL out_buf : STD_LOGIC_VECTOR((data_nibbles*8)-1 DOWNTO 0); SIGNAL host_buf : byte; SIGNAL host_ready : STD_LOGIC; SIGNAL host_full : STD_LOGIC; SIGNAL ack_read : STD_LOGIC; SIGNAL resp_read : STD_LOGIC; SIGNAL host_read : STD_LOGIC; SIGNAL rxd : STD_LOGIC; SIGNAL txd : STD_LOGIC; CONSTANT cycle : TIME := (1000000000/sys_frequency)*1 ns; CONSTANT baud : TIME := (cycle*sys_frequency)/umbilical_rate; CONSTANT prog_len : NATURAL := 0; --2460; CONSTANT int_time : TIME := 29 us + 6 * 80 ns; BEGIN ------------------------------------------------------------------ -- Test vector generation ------------------------------------------------------------------ make_initROM: IF prog_len /= 0 GENERATE debug_mem: program_rom PORT MAP(debug_addr, debug_data); END GENERATE make_initROM; int_n <= '1', '0' AFTER int_time, '1' AFTER int_time + 2 us; host_read <= to_X01(ack_read) OR to_X01(resp_read); reset_core: PROCESS PROCEDURE send_byte (number : IN byte) IS BEGIN WHILE sending = '1' LOOP WAIT FOR cycle; END LOOP; send_debug <= '1'; tx_buf <= number; WAIT UNTIL sending = '1'; send_debug <= '0'; tx_buf <= (OTHERS => 'Z'); END send_byte; PROCEDURE send2core (number : IN data_bus) IS BEGIN out_buf <= (OTHERS => '0'); out_buf(data_width-1 DOWNTO 0) <= number; FOR i IN data_nibbles DOWNTO 1 LOOP send_byte(out_buf(i*8-1 DOWNTO (i-1)*8)); END LOOP; END send2core; PROCEDURE wait_ack IS BEGIN WHILE (host_full = '0' OR host_buf /= mark_ack) LOOP WAIT FOR cycle/2; END LOOP; ack_read <= '1'; WAIT UNTIL host_full = '0'; ack_read <= '0'; END wait_ack; PROCEDURE wait_response (number : IN data_bus) IS BEGIN WHILE (host_full = '0' OR host_reg /= number) LOOP WAIT FOR cycle/2; END LOOP; resp_read <= '1'; WAIT UNTIL host_full = '0'; resp_read <= '0'; END wait_response; PROCEDURE tx_debug ( number : IN data_bus) IS BEGIN send_byte(mark_debug); send2core(number); wait_ack; END tx_debug; BEGIN reset_n <= '0'; send_debug <= '0'; tx_buf <= "ZZZZZZZZ"; ack_read <= 'L'; resp_read <= 'L'; debug_addr <= (OTHERS => '0'); WAIT FOR 600 ns; reset_n <= '1'; WAIT FOR 50 us; IF prog_len /= 0 THEN -- send a Start_1 mark without reset send_byte(mark_start); -- $33 send2core(to_vec(16#55#, data_width)); -- addr send2core(to_vec(0, data_width)); -- length wait_ack; -- load memory with reset send_byte(mark_reset); -- $CC send2core(to_vec(0, data_width)); -- start address send2core(to_vec(prog_len, data_width)); -- length FOR i IN 0 TO prog_len-1 LOOP -- transfer memory image debug_addr <= to_vec(i, prog_addr_width); send_byte(debug_data); END LOOP; wait_ack; END IF; WAIT FOR 10 us; send2core(to_vec(0, data_width)); -- send a string of NAK's, just in case -- debugger initialisation handshake wait_response (to_vec(-1, data_width)); tx_debug(to_vec(16#5F5#, data_width)); wait_response (to_vec(16#505#, data_width)); tx_debug(to_vec(0, data_width)); -- entering monitor loop wait_response (to_vec(0, data_width)); -- now monitor waits for executable address WAIT; END PROCESS reset_core; to_target: PROCESS VARIABLE number : byte := (OTHERS => 'Z'); PROCEDURE tx_uart IS BEGIN txd <= '0'; WAIT FOR baud; FOR i IN 0 TO 7 LOOP txd <= number(i); WAIT FOR baud; END LOOP; txd <= '1'; WAIT FOR baud; -- wait for full stop bit END tx_uart; BEGIN txd <= '1'; sending <= '0'; WAIT FOR 1 ns; LOOP sending <= '0'; WHILE send_ack = '0' AND send_debug = '0' LOOP WAIT FOR cycle; END LOOP; IF send_ack = '1' THEN number := mark_ack; ELSE number := tx_buf; END IF; WAIT FOR 1 ns; sending <= '1'; tx_uart; END LOOP; END PROCESS to_target; from_target: PROCESS PROCEDURE rx_uart IS BEGIN host_ready <= '0'; WHILE rxd = '1' LOOP WAIT FOR cycle; END LOOP; WAIT FOR baud/2; FOR i IN 0 TO 7 LOOP WAIT FOR baud; host_buf(i) <= rxd; END LOOP; host_ready <= '1'; WAIT FOR baud*2/3; -- skip stop bit END rx_uart; BEGIN send_ack <= '0'; host_full <= '0'; host_buf <= (OTHERS => '1'); host_reg <= (OTHERS => '0'); WAIT FOR 1 ns; LOOP host_full <= '0'; WHILE rxd = '1' LOOP WAIT FOR cycle; END LOOP; host_reg <= (OTHERS => '0'); rx_uart; IF host_buf = mark_debug THEN FOR i IN 0 TO data_nibbles-1 LOOP rx_uart; host_reg <= host_reg(((data_nibbles-1)*8)-1 DOWNTO 0) & host_buf; END LOOP; WHILE sending = '1' LOOP WAIT FOR cycle/2; END LOOP; send_ack <= '1'; WAIT UNTIL sending = '1'; send_ack <= '0'; host_full <= '1'; WAIT FOR cycle*10; ELSIF host_buf = mark_ack THEN host_full <= '1'; END IF; WHILE host_read = '0' AND host_buf /= mark_nack LOOP WAIT FOR cycle/2; END LOOP; END LOOP; END PROCESS from_target; clock: PROCESS BEGIN clk <= '0'; WAIT FOR 500 ns; LOOP clk <= '1'; WAIT FOR cycle/2; clk <= '0'; WAIT FOR cycle/2; END LOOP; END PROCESS clock; myFPGA: fpga PORT MAP ( reset_n => reset_n, clk_in => clk, int_n => int_n, -- external data memory io_ce_n => io_ce_n, io_we_n => io_we_n, io_oe_n => io_oe_n, io_addr => io_addr, io_data => io_data, -- umbilical port for debugging rxd => txd, -- incoming data stream txd => rxd -- outgoing data stream ); data_memory: external_ram GENERIC MAP(data_width, data_addr_width) PORT MAP(ce_n => io_ce_n, oe_n => io_oe_n, we_n => io_we_n, addr => io_addr, data => io_data ); END testbench;