fpga: bench: Add self-checking test bench for bootrom

This commit is contained in:
Markus Koch 2024-09-27 14:45:07 +02:00
parent ba299e537b
commit 297d340d6a

View File

@ -0,0 +1,239 @@
-- -------------------------------------------------------------------------- --
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
-- -------------------------------------------------------------------------- --
-- VUnit test bench for the aps6404l Wishbone IF
-- -------------------------------------------------------------------------- --
-- Author : Markus Koch <markus@notsyncing.net>
-- Contributors : None
-- License : Mozilla Public License (MPL) Version 2
-- -------------------------------------------------------------------------- --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library design;
use design.all;
library generics;
use generics.wishbone_pkg.all;
library device_models;
use device_models.all;
library vunit_lib;
context vunit_lib.vunit_context;
library osvvm;
context osvvm.osvvmContext;
use osvvm.ScoreboardPkg_slv.all;
entity bench_top_neorv32_wb is
generic(
runner_cfg : string := runner_cfg_default
);
end entity bench_top_neorv32_wb;
architecture RTL of bench_top_neorv32_wb is
constant UART_BAUD : integer := 250000;
signal clk_in : std_logic;
signal uart_tx : std_logic;
signal uart_rx : std_logic;
signal eth_rx_p : std_logic;
signal eth_tx_p : std_logic_vector(3 downto 0);
signal eth_tx_n : std_logic_vector(3 downto 0);
signal eth_led_green_n : std_logic;
signal eth_led_orange_n : std_logic;
signal led_user : std_logic;
signal psram_ce_n : std_logic;
signal psram_sclk : std_logic;
signal psram_sio : std_logic_vector(3 downto 0);
signal flash_ce_n : std_logic;
signal flash_sclk : std_logic;
signal flash_sio : std_logic_vector(3 downto 0);
signal pmod : std_logic_vector(7 downto 0);
signal SB : ScoreboardIDType;
begin
top_inst : entity design.top
generic map(
F_IN => 50000000,
F_CLK => 25000000,
F_CLK_PHY => 50000000,
UART_BAUD => UART_BAUD,
CPU => "neorv32"
)
port map(
clk_in => clk_in,
uart_tx => uart_tx,
uart_rx => uart_rx,
eth_rx_p => eth_rx_p,
eth_tx_p => eth_tx_p,
eth_tx_n => eth_tx_n,
eth_led_green_n => eth_led_green_n,
eth_led_orange_n => eth_led_orange_n,
led_user => led_user,
psram_ce_n => psram_ce_n,
psram_sclk => psram_sclk,
psram_sio => psram_sio,
flash_ce_n => flash_ce_n,
flash_sclk => flash_sclk,
flash_sio => flash_sio,
pmod => pmod
);
aps6404l_inst : entity device_models.aps6404l
generic map(
LOG_EN => false
)
port map(
ce_n => psram_ce_n,
sclk => psram_sclk,
sio => psram_sio
);
uart_decoder : process is
constant DELAY : time := (1 sec / UART_BAUD);
variable d : std_logic_vector(7 downto 0);
begin
wait until falling_edge(uart_tx);
wait for 0.5 * DELAY;
for i in 0 to 7 loop
wait for DELAY;
d(i) := uart_tx;
end loop;
wait for 1.0 * DELAY;
Check(SB, d);
end process uart_decoder;
test : process is
procedure uart_tx(d : std_logic_vector(7 downto 0)) is
constant DELAY : time := (1 sec / UART_BAUD);
begin
uart_rx <= '0';
wait for DELAY;
for i in d'low to d'high loop
uart_rx <= d(i);
wait for DELAY;
end loop;
uart_rx <= '1';
wait for DELAY;
end procedure uart_tx;
begin
test_runner_setup(runner, runner_cfg);
SB <= NewID("UART RX");
report "Waiting for internal reset to be complete...";
wait for 10 us;
report "Starting tests...";
while test_suite loop
if run("bootloader") then
uart_rx <= '1';
wait for (1 sec / UART_BAUD) * 10;
report ("Writing ABCD+jalr0 to RAM...");
-- WRITE
uart_tx(x"01");
-- to RAM
uart_tx(x"40");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
-- 8 bytes
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"08");
-- with this data ("ABCD", jalr zero)
uart_tx(x"41");
uart_tx(x"42");
uart_tx(x"43");
uart_tx(x"44");
uart_tx(x"e7");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
report ("Reading back from RAM...");
-- READ
uart_tx(x"02");
-- from RAM
uart_tx(x"40");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
-- 4 bytes ("ABCD")
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"04");
Push(SB, x"41");
Push(SB, x"42");
Push(SB, x"43");
Push(SB, x"44");
wait for (1 sec / UART_BAUD) * 10 * 5;
report ("Jumping to RAM+4...");
-- JUMP
uart_tx(x"03");
-- to RAM (+4, jalr zero)
uart_tx(x"40");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"04");
-- The program will jump back to the loader, so we should be able to read again
wait for 100 us;
report ("Reading from RAM again...");
-- READ
uart_tx(x"02");
-- from RAM
uart_tx(x"40");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
-- 4 bytes
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"00");
uart_tx(x"04");
Push(SB, x"41");
Push(SB, x"42");
Push(SB, x"43");
Push(SB, x"44");
wait for (1 sec / UART_BAUD) * 10 * 5;
assert ScoreboardEmpty(SB) report "UART RX Scoreboard not empty at end of test!" severity error;
end if;
end loop;
test_runner_cleanup(runner);
end process test;
test_runner_watchdog(runner, 50 ms);
clock_driver : process
constant period : time := 20 ns;
begin
clk_in <= '0';
wait for period / 2;
clk_in <= '1';
wait for period - (period / 2);
end process clock_driver;
end architecture RTL;