fpga: bench: Add self-checking test bench for bootrom
This commit is contained in:
parent
ba299e537b
commit
297d340d6a
239
fpga/hdl/bench/bench_top_neorv32.vhd
Normal file
239
fpga/hdl/bench/bench_top_neorv32.vhd
Normal 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;
|
Loading…
Reference in New Issue
Block a user