Commit 4bc47c7d authored by kblantos's avatar kblantos

Testbench added for wishbone cores

parent 6b2c8891
`define ADDR_UART_SR 5'h0
`define UART_SR_TX_BUSY_OFFSET 0
`define UART_SR_TX_BUSY 32'h00000001
`define UART_SR_RX_RDY_OFFSET 1
`define UART_SR_RX_RDY 32'h00000002
`define UART_SR_RX_FIFO_SUPPORTED_OFFSET 2
`define UART_SR_RX_FIFO_SUPPORTED 32'h00000004
`define UART_SR_TX_FIFO_SUPPORTED_OFFSET 3
`define UART_SR_TX_FIFO_SUPPORTED 32'h00000008
`define UART_SR_RX_FIFO_VALID_OFFSET 4
`define UART_SR_RX_FIFO_VALID 32'h00000010
`define UART_SR_TX_FIFO_EMPTY_OFFSET 5
`define UART_SR_TX_FIFO_EMPTY 32'h00000020
`define UART_SR_TX_FIFO_FULL_OFFSET 6
`define UART_SR_TX_FIFO_FULL 32'h00000040
`define UART_SR_RX_FIFO_OVERFLOW_OFFSET 7
`define UART_SR_RX_FIFO_OVERFLOW 32'h00000080
`define UART_SR_RX_FIFO_BYTES_OFFSET 8
`define UART_SR_RX_FIFO_BYTES 32'h0000ff00
`define ADDR_UART_BCR 5'h4
`define ADDR_UART_TDR 5'h8
`define UART_TDR_TX_DATA_OFFSET 0
`define UART_TDR_TX_DATA 32'h000000ff
`define ADDR_UART_RDR 5'hc
`define UART_RDR_RX_DATA_OFFSET 0
`define UART_RDR_RX_DATA 32'h000000ff
`define ADDR_UART_HOST_TDR 5'h10
`define UART_HOST_TDR_DATA_OFFSET 0
`define UART_HOST_TDR_DATA 32'h000000ff
`define UART_HOST_TDR_RDY_OFFSET 8
`define UART_HOST_TDR_RDY 32'h00000100
`define ADDR_UART_HOST_RDR 5'h14
`define UART_HOST_RDR_DATA_OFFSET 0
`define UART_HOST_RDR_DATA 32'h000000ff
`define UART_HOST_RDR_RDY_OFFSET 8
`define UART_HOST_RDR_RDY 32'h00000100
`define UART_HOST_RDR_COUNT_OFFSET 9
`define UART_HOST_RDR_COUNT 32'h01fffe00
`define ADDR_UART_CR 5'h18
`define UART_CR_RX_FIFO_PURGE_OFFSET 0
`define UART_CR_RX_FIFO_PURGE 32'h00000001
`define UART_CR_TX_FIFO_PURGE_OFFSET 1
`define UART_CR_TX_FIFO_PURGE 32'h00000002
action = "simulation"
target = "generic"
sim_top = "tb_wb16_to_wb32"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../",
"../../../modules/wishbone",
"../../../sim/vhdl"] };
files = ["tb_wb16_to_wb32.vhd"]
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_wb16_to_wb32
echo "Running simulation for $TB"
echo "Mode = PIPELINED"
ghdl -r --std=08 -frelaxed-rules $TB
echo "*******************************************************************************"
action = "simulation"
target = "generic"
sim_top = "tb_xwb_async_bridge"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../",
"../../../modules/wishbone",
"../../../sim/vhdl"] };
files = ["tb_xwb_async_bridge.vhd"]
Testbench for Atmel EBI asynchronous bus <-> Wishbone bridge. It is using OSVVM methodology with all the input signals in the stimulus to be get random values in each clock cycle. The simulation time, can be changed in the `stim` process, by changing the value of `NOW`. Regarding on the values that the generics of the core have, there are at least 4 test cases presented:
- g_simulation : 1 / 0
- g_address_granularity : WORD / BYTE
- g_cpu_address_width : 32 / 64
Self-Checking: A few assertions are being implemented, in order to test the functionality of the core. First of all, they check if there is an address mismatch, between the RTL and the testbench's output address. There is another assertion that checks if there is a mismatch in output data as well, when the read and write pulse are both asserted.
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_xwb_async_bridge
echo "Running simulation for $TB"
echo " TEST CASE 1 "
echo "Simulation mode = ON, Address Granularity = WORD, CPU address width = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_simulation=1 -gg_address_granularity=WORD -gg_cpu_address_width=32
echo "*******************************************************************************"
echo " TEST CASE 2 "
echo "Simulation mode = ON, Address Granularity = BYTE, CPU address width = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_simulation=1 -gg_address_granularity=BYTE -gg_cpu_address_width=32
echo "*******************************************************************************"
echo " TEST CASE 3 "
echo "Simulation mode = OFF, Address Granularity = WORD, CPU address width = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_simulation=0 -gg_address_granularity=WORD -gg_cpu_address_width=64
echo "*******************************************************************************"
echo " TEST CASE 4 "
echo "Simulation mode = OFF, Address Granularity = BYTE, CPU address width = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_simulation=1 -gg_address_granularity=BYTE -gg_cpu_address_width=32
echo "*******************************************************************************"
------------------------------------------------------------------------------
-- Title : Testbench for Atmel EBI asynchronous bus <-> Wishbone bridge
-- Project : White Rabbit Switch
------------------------------------------------------------------------------
-- Author : Konstantinos Blantos
-- Company : CERN BE-CEM-EDL
-- Created : 2022-01-28
-- Last update:
-- Platform : FPGA-generic
-- Standard : VHDL'08
-------------------------------------------------------------------------------
-- Copyright (c) 2010 CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
-------------------------------------------------------------------------------
--==============================================================================
-- Libraries & Packages --
--==============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.wishbone_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_xwb_async_bridge --
--=============================================================================
entity tb_xwb_async_bridge is
generic (
g_seed : natural;
g_simulation : integer := 0;
g_interface_mode : t_wishbone_interface_mode;
g_address_granularity : t_wishbone_address_granularity := WORD;
g_cpu_address_width : integer := 32);
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_xwb_async_bridge is
-- These functions from wb_slave_adapter, are used in
-- the self-checking process for the address
function f_num_byte_address_bits
return integer is
begin
case c_wishbone_data_width is
when 8 => return 0;
when 16 => return 1;
when 32 => return 2;
when 64 => return 3;
when others =>
report "wb_slave_adapter: invalid c_wishbone_data_width (we support 8, 16, 32 and 64)" severity failure;
end case;
return 0;
end function f_num_byte_address_bits;
function f_zeros(size : integer)
return std_logic_vector is
begin
return std_logic_vector(to_unsigned(0, size));
end function f_zeros;
-- Constants
constant C_CLK_SYS_PERIOD : time := 10 ns;
-- Signals
signal tb_rst_n_i : std_logic;
signal tb_clk_sys_i : std_logic;
signal tb_cpu_cs_n_i : std_logic := '0';
signal tb_cpu_wr_n_i : std_logic := '0';
signal tb_cpu_rd_n_i : std_logic := '0';
signal tb_cpu_bs_n_i : std_logic_vector(3 downto 0) := (others=>'0');
signal tb_cpu_addr_i : std_logic_vector(g_cpu_address_width-1 downto 0) := (others=>'0');
signal tb_cpu_data_b : std_logic_vector(31 downto 0);
signal tb_cpu_nwait_o : std_logic;
signal tb_master_o : t_wishbone_master_out;
signal tb_master_i : t_wishbone_master_in;
signal stop : boolean;
signal s_wr_pulse : std_logic;
signal s_rd_pulse : std_logic;
signal s_cs_synced : std_logic;
signal s_addr_o : std_logic_vector(g_cpu_address_width-1 downto 0) := (others=>'0');
signal s_busy : std_logic;
signal s_data_o : std_logic_vector(31 downto 0);
begin
-- Unit Under Test
UUT : entity work.xwb_async_bridge
generic map (
g_simulation => g_simulation,
g_interface_mode => g_interface_mode,
g_address_granularity => g_address_granularity,
g_cpu_address_width => g_cpu_address_width)
port map (
rst_n_i => tb_rst_n_i,
clk_sys_i => tb_clk_sys_i,
cpu_cs_n_i => tb_cpu_cs_n_i,
cpu_wr_n_i => tb_cpu_wr_n_i,
cpu_rd_n_i => tb_cpu_rd_n_i,
cpu_bs_n_i => tb_cpu_bs_n_i,
cpu_addr_i => tb_cpu_addr_i,
cpu_data_b => tb_cpu_data_b,
cpu_nwait_o => tb_cpu_nwait_o,
master_o => tb_master_o,
master_i => tb_master_i);
-- Clock generation
clk_sys_proc : process
begin
while not stop loop
tb_clk_sys_i <= '1';
wait for C_CLK_SYS_PERIOD/2;
tb_clk_sys_i <= '0';
wait for C_CLK_SYS_PERIOD/2;
end loop;
wait;
end process;
-- reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_SYS_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING Slave] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while (NOW < 2 ms) loop
wait until rising_edge(tb_clk_sys_i);
tb_cpu_cs_n_i <= data.randSlv(1)(1);
tb_cpu_wr_n_i <= data.randSlv(1)(1);
tb_cpu_rd_n_i <= data.randSlv(1)(1);
tb_cpu_bs_n_i <= data.randSlv(4);
tb_cpu_addr_i <= data.randSlv(g_cpu_address_width);
tb_master_i.ack <= data.randSlv(1)(1);
tb_master_i.dat <= data.randSlv(32);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions
--------------------------------------------------------------------------------
g_simulation_on : if (g_simulation = 1) generate
s_wr_pulse <= not tb_cpu_wr_n_i;
s_rd_pulse <= not tb_cpu_rd_n_i;
s_cs_synced<= tb_cpu_cs_n_i;
end generate;
-- the address signals have one clock delay
addr_self_check : process(tb_clk_sys_i)
begin
if (rising_edge(tb_clk_sys_i)) then
if (tb_rst_n_i = '1') then
if (s_cs_synced='0') then
if (g_address_granularity = WORD) then
s_addr_o <= tb_cpu_addr_i;
assert (tb_master_o.adr = s_addr_o)
report "Address mismatch when WORD granularity"
severity failure;
elsif (g_address_granularity = BYTE) then
s_addr_o <= tb_cpu_addr_i(c_wishbone_address_width-f_num_byte_address_bits-1 downto 0)& f_zeros(f_num_byte_address_bits);
assert (tb_master_o.adr = s_addr_o)
report "Address mismatch when BYTE granularity"
severity failure;
else
s_addr_o <= f_zeros(f_num_byte_address_bits) & tb_cpu_addr_i(c_wishbone_address_width-1 downto f_num_byte_address_bits);
assert (tb_master_o.adr = s_addr_o)
report "Address mismatch"
severity failure;
end if;
end if;
end if;
end if;
end process;
process(tb_clk_sys_i)
begin
if(rising_edge(tb_clk_sys_i)) then
if(tb_rst_n_i = '0') then
s_busy <= '0';
s_data_o <= (others=>'0');
else
if(s_cs_synced = '0') then
if(s_busy = '1') then
if(tb_master_i.ack = '1') then
s_busy <= '0';
end if;
elsif(s_rd_pulse = '1' or s_wr_pulse = '1') then
if(s_wr_pulse = '1') then
s_data_o <= tb_cpu_data_b;
assert (tb_master_o.dat = s_data_o)
report "Data mismatch"
severity failure;
end if;
s_busy <= '1';
end if;
end if;
end if;
end if;
end process;
end tb;
action = "simulation"
target = "generic"
sim_top = "tb_xwb_axi4lite_bridge"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../",
"../../../modules/wishbone",
"../../../modules/axi"] };
files = ["tb_xwb_axi4lite_bridge.vhd"]
Testbench for AXI4Lite-to-WB bridge wrapper. It is using OSVVM methodology with all the input signals in the stimulus to be get random values in each clock cycle. The simulation time, can be changed in the `stim` process, by changing the value of `NOW`. There is only one test case and actually, test the functionality of this bridge core, through FSM coverage and assertions.
FSM coverage: In the RTL core, there is a FSM where it describes the behavior of the bridge. This testbench, covers all the possible changes of the states and also investigate if there are illigal transitions through the states. The goal is to reach 100% and all states covered at least once. The checking is done in every clock cycle, so when the state remains the some for some clock cycles is also covered.
Self-Checking: Assertions are massively used in order to verify the correctness of the functionality of Wishbone and AXI4-lite protocols. All of them are taken from the specification of these protocols.
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_xwb_axi4lite_bridge
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM
echo "*******************************************************************************"
action = "simulation"
target = "generic"
sim_top = "tb_xwb_clock_bridge"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../"]}
files = ["tb_xwb_clock_bridge.vhd"]
This is a testbench to verify the xwb_clock_bridge core. As input, this test has random values, with random seed with OSVVM methodology. The behavior of this testbench is very similar to the one in the RTL core. For simulation reasons, it contains also the 2 FIFOs that the core uses, mostly because the write and read enable signals are useful for the test. There are two assertions processes, which compare always the output of the RTL (master_o and slave_o) with the output of the testbench (output of second FIFO and data stored in an array).
As for the generics, `g_slave_port_wb_mode` and `g_master_port_wb_mode` are `PIPELINED` and they can not be changed. The only generic that can be changed is the `g_size`, which is the depth of FIFOs and for simulation reasons, it is preferable not to have a high number.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_xwb_clock_bridge
echo "Running simulation for $TB"
echo "************************************************************************"
echo " TEST CASE 1: size = 32 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_size=32 --wave=waveform.ghw
echo "************************************************************************"
action = "simulation"
target = "generic"
sim_top = "tb_xwb_clock_crossing"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../"]}
files = ["tb_xwb_clock_crossing.vhd"]
This is a testbench to verify the functionality of the xwb_clock_crossing. It is a cross clock domain wishbone adapter. It has been tested to use both for fast -> slow and slow -> fast clock domains. It contains 2 generic FIFOs (generic_async_fifo_dual_rst), one for Master (slave input to master output) and one for Slave (master input to slave output).
The only generic that this core has, is the `g_size` which is then passed to the FIFOs. That means, that the generic values that the FIFOs have, can define the behavior of the core itself.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_xwb_clock_crossing
echo "Running simulation for $TB"
echo "************************************************************************"
echo " TEST CASE 1: size = 32 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_size=32
echo "************************************************************************"
action = "simulation"
target = "generic"
sim_top = "tb_sdb_rom"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../"]}
files = ["tb_sdb_rom.vhd"]
This is a simple testbench to verify the sdb_rom core. Because the rom and the values that has inside, can be changed, by changing the values of the generics, this testbench is very specific. It run for these specific values:
- g_seed : is the generic value used from OSVVM, to generate numbers with randomized seed
- g_layout : one array with all bits set to zero
- g_bus_end : all 64-bits set to '1'
- g_wb_mode : the wishbone interface mode has been set to CLASSIC
- g_sdb_name : string which is specific, "WB4-Crossbar-GSI"
There are some test cases tested, depending on the number of masters. It can be 1, 2, 4 (or any other integer number).
What it is being tested in all cases is if the output slave has the correct data (from this non-generic ROM). In addition, it verifies that the slave has the correct values, as they supposed to be, regarding the specification (ERR, RTY, STALL, ACK) and they agree, with the ones generated from RTL core.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_sdb_rom
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 1 : number of masters = 1 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_masters=1
echo "*******************************************************************************"
echo "*******************************************************************************"
echo " TEST CASE 2 : number of masters = 2 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_masters=1
echo "*******************************************************************************"
echo "*******************************************************************************"
echo " TEST CASE 3 : number of masters = 4 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_masters=1
echo "*******************************************************************************"
--------------------------------------------------------------------------------
-- CERN (BE-CEM-EDL)
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: tb_sdb_rom
--
-- author: Konstantinos Blantos
--
-- description: Testbench for SDB ROM for WB crossbar
--
--------------------------------------------------------------------------------
-- Copyright CERN 2022
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=================================================================================================
-- Entity declaration for tb_sdb_rom
--=================================================================================================
entity tb_sdb_rom is
generic (
g_seed : natural;
g_layout : t_sdb_record_array := (0=>(others=>'0'));
g_masters : natural;
g_bus_end : unsigned(63 downto 0) := (others=>'1');
g_wb_mode : t_wishbone_interface_mode := CLASSIC;
g_sdb_name : string := "WB4-Crossbar-GSI ");
end entity;
--=================================================================================================
-- Architecture declaration
--=================================================================================================
architecture tb of tb_sdb_rom is
-- Alias
alias c_layout : t_sdb_record_array(g_layout'length downto 1) is g_layout;
-- Constants
constant C_CLK_SYS_PERIOD : time := 10 ns;
constant C_WB_SLAVE_IN : t_wishbone_slave_in :=
('0', '0', (others=>'0'), (others=>'0'), '0', (others=>'0'));
type t_rom_memory is array (0 to 31) of std_logic_vector(31 downto 0);
-- copied from RTL core
-- The ROM must describe all slaves, the crossbar itself and the optional information records
constant c_used_entries : natural := c_layout'high + 1;
constant c_rom_entries : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
constant c_sdb_words : natural := c_sdb_device_length / c_wishbone_data_width;
constant c_rom_words : natural := c_rom_entries * c_sdb_words;
constant c_rom_depth : natural := f_ceil_log2(c_rom_words);
constant c_rom_lowbits : natural := f_ceil_log2(c_wishbone_data_width / 8);
constant c_sdb_name : string := f_string_fix_len(g_sdb_name , 19, ' ', false);
-- Signals
signal tb_clk_sys_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_master_i : std_logic_vector(g_masters-1 downto 0);
signal tb_slave_i : t_wishbone_slave_in := C_WB_SLAVE_IN;
signal tb_slave_o : t_wishbone_slave_out;
signal stop : boolean;
signal s_ack : std_logic := '0';
signal s_addr : unsigned(c_rom_depth-1 downto 0);
signal s_data : std_logic_vector(c_wishbone_data_width-1 downto 0);
signal s_rom : t_rom_memory :=
(0 => x"5344422D",
1 => x"00020100",
2 => x"00000000",
3 => x"00000000",
4 => x"FFFFFFFF",
5 => x"FFFFFFFF",
6 => x"00000000",
7 => x"00000651",
8 => x"E6A542C9",
9 => x"00000003",
10 => x"20120511",
11 => x"5742342D",
12 => x"43726F73",
13 => x"73626172",
14 => x"2D475349",
15 => x"20202000",
16 => x"00000000",
17 => x"00000000",
18 => x"00000000",
19 => x"00000000",
20 => x"00000000",
21 => x"00000000",
22 => x"00000000",
23 => x"00000000",
24 => x"00000000",
25 => x"00000000",
26 => x"00000000",
27 => x"00000000",
28 => x"00000000",
29 => x"00000000",
30 => x"00000000",
31 => x"00000000");
begin
-- Unit Under Test
UUT : entity work.sdb_rom
generic map (
g_layout => g_layout,
g_masters => g_masters,
g_bus_end => g_bus_end,
g_wb_mode => g_wb_mode,
g_sdb_name => g_sdb_name)
port map (
clk_sys_i => tb_clk_sys_i,
rst_n_i => tb_rst_n_i,
master_i => tb_master_i,
slave_i => tb_slave_i,
slave_o => tb_slave_o);
-- Clock generation
clk_sys_proc : process
begin
while not stop loop
tb_clk_sys_i <= '1';
wait for C_CLK_SYS_PERIOD/2;
tb_clk_sys_i <= '0';
wait for C_CLK_SYS_PERIOD/2;
end loop;
wait;
end process clk_sys_proc;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_SYS_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while NOW < 2 ms loop
wait until rising_edge(tb_clk_sys_i);
tb_master_i <= data.randSlv(g_masters);
-- Slave signals
tb_slave_i.cyc <= data.randSlv(1)(1);
tb_slave_i.stb <= data.randSlv(1)(1);
tb_slave_i.we <= data.randSlv(1)(1);
tb_slave_i.sel <= data.randSlv(4);
tb_slave_i.adr <= data.randSlv(32);
tb_slave_i.dat <= data.randSlv(32);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= true;
report "Test PASS!";
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
s_addr <= unsigned(tb_slave_i.adr(c_rom_depth+c_rom_lowbits-1 downto c_rom_lowbits));
-- the rom that simulates the one that RTL generates with these
-- specific generic values
-- check that the output signals of the slave
-- behaves like the specification
-- ack signal is the cyc and stb of the slave_i
check_ack : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if tb_rst_n_i = '1' then
s_ack <= tb_slave_i.cyc and tb_slave_i.stb;
if s_ack then
assert (tb_slave_o.ack = s_ack)
report "ACK mismatch in output slave" severity failure;
end if;
end if;
end if;
end process;
-- Err, Rty and stall should be zero
err_rty_stall_check : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if tb_rst_n_i = '1' then
assert (tb_slave_o.err = '0' and tb_slave_o.rty = '0' and tb_slave_o.stall = '0')
report "ERR of slave_o should be zero" severity failure;
end if;
end if;
end process;
-- store the output data from testbench
-- Output data should take values only from ROM (for this testcase)
check_data : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
s_data <= s_rom(to_integer(s_addr));
assert (tb_slave_o.dat = s_data)
report "Output data of the slave should have value from ROM"
severity error;
end if;
end process;
end tb;
action = "simulation"
target = "generic"
sim_top = "tb_xwb_crossbar"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../"]}
files = ["tb_xwb_crossbar.vhd"]
This is a testbench for xwb_crossbar. This simple self-checking testbench, is for the case where there are 1 master and 2 slaves. The core can be used for MxN.
OSVVM methodology is used and random inputs drive the testbench (based on randomized seed number).
When no master granted access to SDB, the slaves are in stall and wait for access. When this signal `sdb_sel_o` is not zero, the output master and slaves, are equal to the pointing slaves and master respectively.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_xwb_crossbar
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 1 "
echo " Number of masters = 2, Number of slaves = 1 "
echo " Registered = False , Verbose = True "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_masters=2 -gg_num_slaves=1 -gg_registered=false -gg_verbose=true --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo " TEST CASE 2 "
echo " Number of masters = 2, Number of slaves = 1 "
echo " Registered = False , Verbose = False "
#ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_masters=2 -gg_num_slaves=1 -gg_registered=false -gg_verbose=false --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo " TEST CASE 3 "
echo " Number of masters = 2, Number of slaves = 1 "
echo " Registered = True , Verbose = False "
#ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_masters=2 -gg_num_slaves=1 -gg_registered=true -gg_verbose=false --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo " TEST CASE 4 "
echo " Number of masters = 2, Number of slaves = 1 "
echo " Registered = True , Verbose = True "
#ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_masters=2 -gg_num_slaves=1 -gg_registered=true -gg_verbose=true --wave=waveform.ghw
echo "*******************************************************************************"
--------------------------------------------------------------------------------
-- CERN (BE-CEM-EDL)
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
--! unit name: tb_xwb_crossbar
--!
--! author: Konstantinos Blantos
--!
--! description: Testbench for an MxS Wishbone crossbar switch
--! All masters, slaves, and the crossbar itself must share the same WB clock.
--! All participants must support the same data bus width.
--!
--! If a master raises STB_O with an address not mapped by the crossbar,
--! ERR_I will be raised. If two masters address the same slave
--! simultaneously, the lowest numbered master is granted access.
--!
--! The implementation of this crossbar locks a master to a slave so long as
--! CYC_O is held high.
--
-- Synthesis/timing relevant facts:
-- (m)asters, (s)laves, masked (a)ddress bits
--
-- Area required = O(ms log(ma))
-- Arbitration depth = O(log(msa))
-- Master->Slave depth = O(log(m))
-- Slave->Master depth = O(log(s))
--
-- If g_registered = false, arbitration depth is added to M->S and S->M.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2022
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_xwb_crossbar is
generic (
g_seed : natural := 1992;
g_num_masters : integer := 2;
g_num_slaves : integer := 1;
g_registered : boolean := false;
g_address : t_wishbone_address_array := (0=>x"00000000"); --(0 => x"11110000", 1 => x"1111110C");
g_mask : t_wishbone_address_array := (0=>x"00000000"); --(0 => x"1111110C", 1 => x"1111110C");
g_verbose : boolean := true);
end entity;
architecture tb of tb_xwb_crossbar is
-- Constants
constant C_CLK_SYS_PERIOD : time := 10 ns;
constant C_WISHBONE_SLAVE_I : t_wishbone_slave_in :=
('0', '0', x"00000000", x"0", '0', x"00000000");
constant C_WISHBONE_MASTER_I: t_wishbone_master_in :=
('0', '0', '0', '0', x"00000000");
-- Signals
signal tb_clk_sys_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_slave_i : t_wishbone_slave_in_array(g_num_masters-1 downto 0) := (others => C_WISHBONE_SLAVE_I);
signal tb_slave_o : t_wishbone_slave_out_array(g_num_masters-1 downto 0);
signal tb_master_i : t_wishbone_master_in_array(g_num_slaves-1 downto 0) := (others => C_WISHBONE_MASTER_I);
signal tb_master_o : t_wishbone_master_out_array(g_num_slaves-1 downto 0);
signal tb_sdb_sel_o : std_logic_vector(g_num_masters-1 downto 0);
signal stop : boolean;
signal s_sdb_sel : integer;
begin
-- Unit Under Test
UUT : entity work.xwb_crossbar
generic map (
g_num_masters => g_num_masters,
g_num_slaves => g_num_slaves,
g_registered => g_registered,
g_address => g_address,
g_mask => g_mask,
g_verbose => g_verbose)
port map (
clk_sys_i => tb_clk_sys_i,
rst_n_i => tb_rst_n_i,
master_i => tb_master_i,
master_o => tb_master_o,
slave_i => tb_slave_i,
slave_o => tb_slave_o,
sdb_sel_o => tb_sdb_sel_o);
-- Clock generation
clk_sys_proc : process
begin
while not stop loop
tb_clk_sys_i <= '1';
wait for C_CLK_SYS_PERIOD/2;
tb_clk_sys_i <= '0';
wait for C_CLK_SYS_PERIOD/2;
end loop;
wait;
end process clk_sys_proc;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_SYS_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while NOW < 1 ms loop
wait until rising_edge(tb_clk_sys_i);
for i in 0 to g_num_slaves-1 loop
tb_master_i(i).ack <= data.randSlv(1)(1);
tb_master_i(i).dat <= data.randSlv(32);
tb_master_i(i).err <= data.randSlv(1)(1);
tb_master_i(i).rty <= data.randSlv(1)(1);
tb_master_i(i).stall <= data.randSlv(1)(1);
end loop;
for j in 0 to g_num_masters-1 loop
tb_slave_i(j).adr <= data.randSlv(c_wishbone_address_width);
tb_slave_i(j).cyc <= data.randSlv(1)(1);
tb_slave_i(j).dat <= data.randSlv(c_wishbone_data_width);
tb_slave_i(j).sel <= data.randSlv(c_wishbone_address_width/8);
tb_slave_i(j).stb <= data.randSlv(1)(1);
tb_slave_i(j).we <= data.randSlv(1)(1);
end loop;
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= true;
report "Test PASS!";
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
-- Convert sdb_sel_o into integer
-- this is used like a pointer to point to the which slave
-- or master of the output side we are using everytime
s_sdb_sel <= to_integer(unsigned(tb_sdb_sel_o)-1);
-- Everytime that the sbd_sel_o is not zero
-- and regarding of its value, these assertions are used
-- to verify that the crossbar behaves properly
-- comparison between input master and output slaves
compare_master_slave : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if tb_sdb_sel_o /= "00" then
assert (tb_master_i(0) = tb_slave_o(s_sdb_sel))
report "Mismatch between master_i and slave_o" severity failure;
else
assert (tb_slave_o(0).stall = '1' and tb_slave_o(1).stall = '1')
report "Not in stall when no-one is selected" severity failure;
end if;
end if;
end process;
-- comparison between input slaves and output master
compare_slave_master : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if tb_sdb_sel_o /= "00" then
assert (tb_master_o(0) = tb_slave_i(s_sdb_sel))
report "Mismatch between slave_i and master_o" severity failure;
end if;
end if;
end process;
end tb;
action = "simulation"
target = "xilinx"
syn_device="xc6slx45t"
sim_top = "tb_xwb_dpram"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../"]}
files = ["tb_xwb_dpram.vhd"]
This is a testbench for the xwb_dpram. In the input side there are 2 slave (slave1 and slave2), both of their inputs are randomized, with random seed in every run. In the output side there are again 2 slave (slave1 and slave2). This purpose of the test is to verify the functionality of the core. In order to cover all the possible ways that someone can use this core, regarding the values of the generics. Some of the values remain steady:
- `g_size` : 32-bits
- `g_init_file` : none
- `g_must_have_init_file` : true
The testcases are created based on the:
- `g_slave1_interface_mode` : CLASSIC / PIPELINED
- `g_slave2_interface_mode` : CLASSIC / PIPELINED
- `g_slave1_granularity` : WORD / BYTE
- `g_slave2_granularity` : WORD / BYTE
OSVVM is used as the verification methodology of the testbench. Various assertions are used in order to confirm that:
- ACK signals are behave as they supposed to be (depending the `stb` and `cyc` of the input
- ERR, RTY, and STALL are always zero in the output
- Output data of the slaves is the expected (regarding the value of the interface mode and granularity, the output data can have different behavior)
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_xwb_dpram
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 1 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = CLASSIC / CLASSIC "
echo " Slave 1,2 granularity = WORD / WORD "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=CLASSIC -gg_slave2_interface_mode=CLASSIC -gg_slave1_granularity=WORD -gg_slave2_granularity=WORD --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 2 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = PIPELINED / PIPELINED "
echo " Slave 1,2 granularity = WORD / WORD "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=PIPELINED -gg_slave2_interface_mode=PIPELINED -gg_slave1_granularity=WORD -gg_slave2_granularity=WORD --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 3 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = CLASSIC / PIPELINED "
echo " Slave 1,2 granularity = WORD / WORD "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=CLASSIC -gg_slave2_interface_mode=PIPELINED -gg_slave1_granularity=WORD -gg_slave2_granularity=WORD --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 4 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = PIPELINED / CLASSIC "
echo " Slave 1,2 granularity = WORD / WORD "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=PIPELINED -gg_slave2_interface_mode=CLASSIC -gg_slave1_granularity=WORD -gg_slave2_granularity=WORD --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 5 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = CLASSIC / CLASSIC "
echo " Slave 1,2 granularity = WORD / BYTE "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=CLASSIC -gg_slave2_interface_mode=CLASSIC -gg_slave1_granularity=WORD -gg_slave2_granularity=BYTE --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 6 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = PIPELINED / PIPELINED "
echo " Slave 1,2 granularity = BYTE / WORD "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=PIPELINED -gg_slave2_interface_mode=PIPELINED -gg_slave1_granularity=BYTE -gg_slave2_granularity=WORD --wave=waveform.ghw
echo "*******************************************************************************"
echo "*******************************************************************************"
echo "Running simulation for $TB"
echo "*******************************************************************************"
echo " TEST CASE 7 : Size = 32 "
echo " Must have init file = True "
echo " Slave 1,2 interface mode = CLASSIC / PIPELINED "
echo " Slave 1,2 granularity = BYTE / BYTE "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed_1=$RANDOM -gg_seed_2=$RANDOM -gg_size=32 -gg_must_have_init_file=true -gg_slave1_interface_mode=CLASSIC -gg_slave2_interface_mode=PIPELINED -gg_slave1_granularity=BYTE -gg_slave2_granularity=BYTE --wave=waveform.ghw
echo "*******************************************************************************"
This diff is collapsed.
......@@ -7,7 +7,6 @@ vcom_opt="-mixedsvvh l -2008"
sim_top="main"
syn_device="xc7k70t"
include_dirs=["../../../sim", "../include" ]
modelsim_ini_path="~/eda/modelsim-lib-2016.4"
files = [ "main.sv" ]
......
......@@ -32,13 +32,13 @@ class IBusDevice;
endfunction // new
virtual task write32( uint32_t addr, uint32_t val );
m_acc.write(m_base +addr, val);
m_acc.write(m_base + addr, val);
endtask // write
virtual task read32( uint32_t addr, output uint32_t val );
uint64_t val64;
m_acc.read(m_base +addr, val64);
m_acc.read(m_base + addr, val64);
val = val64;
endtask // write
......@@ -79,7 +79,7 @@ class FinePulseGenDriver extends IBusDevice;
write32( `ADDR_FPG_ODELAY_CALIB, 0 );
#100ns;
while(1)
while(1)
begin
read32( `ADDR_FPG_ODELAY_CALIB, rv );
$display("odelay = %x", rv);
......@@ -279,7 +279,7 @@ module main;
drv = new( acc, 0 );
drv.calibrate();
// drv.calibrate();
......
#vlog -sv main.sv +incdir+. +incdir+../../include/wb +incdir+../include/vme64x_bfm +incdir+../../include +incdir+../include +incdir+../../sim
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
#set StdArithNoWarnings 1
#set NumericStdNoWarnings 1
vsim -modelsimini /home/twl/eda/modelsim-lib-2016.4/modelsim.ini -L unisim -L secureip -L XilinxCoreLib work.main work.glbl -voptargs=+acc -t 10fs
#vsim -modelsimini /home/twl/eda/modelsim-lib-2016.4/modelsim.ini -L unisim -L secureip -L XilinxCoreLib work.main work.glbl -voptargs=+acc -t 10fs
vsim -quiet -t 10fs -L unisim -L secureip -L XilinxCoreLib work.main -voptargs=+acc -suppress 1270,8617,8683,8684,8822
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
#do wave.do
radix -hexadecimal
run 15us
wave zoomfull
\ No newline at end of file
wave zoomfull
action = "simulation"
target = "generic"
sim_top = "tb_wb_i2c_bridge"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../", "../../../sim/wb_i2c_bridge"] };
files = ["tb_wb_i2c_bridge.vhd"]
This is a testbench to verify some of the functionalites of the wishbone I2C bridge. In this test there are 2 bridges (slave) and one i2c_master_byte_ctrl (master). An i2c_bus_model is used to connect the master and the slaves. In addition, the main implementation of the test is based on an Finite State Machine which is controlled by a stimuli process at the end of the test. The purpose of this FSM is to control the signals of the master, to implement the I2C protocol (as it is defined together with ELMA SNMP Specification).
The OSVVM methodology is used in this test in order to have fsm coverage. Since the input signals are not randomized, it is not expected to reach the *ERR* state which means that there is an error. There are some other states that are not covered, like the *WR* and *WR_ACK* and this is happening because it tests the reading process.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_wb_i2c_bridge
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_fsm_wdt=65535 --wave=waveform.ghw
This diff is collapsed.
action = "simulation"
target = "generic"
sim_top = "tst_bench_top"
sim_tool = "modelsim"
modules = { "local" : ["../../../",
"../../../modules/wishbone"]};
files = ["tst_bench_top.v",
"i2c_slave_model.v",
"wb_master_model.v",
"timescale.v"]
This diff is collapsed.
vsim -quiet -t 10fs work.tst_bench_top -suppress 1270,8617,8683,8684,8822 -voptargs="+acc"
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
radix -hexadecimal
run -all
This diff is collapsed.
///////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 Wishbone Master model ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/mem_ctrl ////
//// ////
///////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
///////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: wb_master_model.v,v 1.4 2004-02-28 15:40:42 rherveille Exp $
//
// $Date: 2004-02-28 15:40:42 $
// $Revision: 1.4 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
//
`include "timescale.v"
module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty);
parameter dwidth = 32;
parameter awidth = 32;
input clk, rst;
output [awidth -1:0] adr;
input [dwidth -1:0] din;
output [dwidth -1:0] dout;
output cyc, stb;
output we;
output [dwidth/8 -1:0] sel;
input ack, err, rty;
////////////////////////////////////////////////////////////////////
//
// Local Wires
//
reg [awidth -1:0] adr;
reg [dwidth -1:0] dout;
reg cyc, stb;
reg we;
reg [dwidth/8 -1:0] sel;
reg [dwidth -1:0] q;
////////////////////////////////////////////////////////////////////
//
// Memory Logic
//
initial
begin
//adr = 32'hxxxx_xxxx;
//adr = 0;
adr = {awidth{1'bx}};
dout = {dwidth{1'bx}};
cyc = 1'b0;
stb = 1'bx;
we = 1'hx;
sel = {dwidth/8{1'bx}};
#1;
$display("\nINFO: WISHBONE MASTER MODEL INSTANTIATED (%m)\n");
end
////////////////////////////////////////////////////////////////////
//
// Wishbone write cycle
//
task wb_write;
input delay;
integer delay;
input [awidth -1:0] a;
input [dwidth -1:0] d;
begin
// wait initial delay
repeat(delay) @(posedge clk);
// assert wishbone signal
#1;
adr = a;
dout = d;
cyc = 1'b1;
stb = 1'b1;
we = 1'b1;
sel = {dwidth/8{1'b1}};
@(posedge clk);
// wait for acknowledge from slave
while(~ack) @(posedge clk);
// negate wishbone signals
#1;
cyc = 1'b0;
stb = 1'bx;
adr = {awidth{1'bx}};
dout = {dwidth{1'bx}};
we = 1'hx;
sel = {dwidth/8{1'bx}};
end
endtask
////////////////////////////////////////////////////////////////////
//
// Wishbone read cycle
//
task wb_read;
input delay;
integer delay;
input [awidth -1:0] a;
output [dwidth -1:0] d;
begin
// wait initial delay
repeat(delay) @(posedge clk);
// assert wishbone signals
#1;
adr = a;
dout = {dwidth{1'bx}};
cyc = 1'b1;
stb = 1'b1;
we = 1'b0;
sel = {dwidth/8{1'b1}};
@(posedge clk);
// wait for acknowledge from slave
while(~ack) @(posedge clk);
// negate wishbone signals
#1;
cyc = 1'b0;
stb = 1'bx;
adr = {awidth{1'bx}};
dout = {dwidth{1'bx}};
we = 1'hx;
sel = {dwidth/8{1'bx}};
d = din;
end
endtask
////////////////////////////////////////////////////////////////////
//
// Wishbone compare cycle (read data from location and compare with expected data)
//
task wb_cmp;
input delay;
integer delay;
input [awidth -1:0] a;
input [dwidth -1:0] d_exp;
begin
wb_read (delay, a, q);
if (d_exp !== q)
$display("Data compare error. Received %h, expected %h at time %t", q, d_exp, $time);
end
endtask
endmodule
action = "simulation"
target = "generic"
sim_top = "tb_wb_indirect"
sim_tool = ""
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../", "../../../sim/vhdl"] };
......
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_wb_indirect
echo "Running simulation for $TB"
echo "Mode = PIPELINED"
ghdl -r --std=08 -frelaxed-rules $TB
echo "*******************************************************************************"
......@@ -8,6 +8,9 @@ entity tb_wb_indirect is
end tb_wb_indirect;
architecture arch of tb_wb_indirect is
constant C_CLK_PERIOD : time := 8 ns;
signal rst_n : std_logic;
signal clk : std_logic;
signal wb_in : t_wishbone_slave_in;
......@@ -19,21 +22,23 @@ architecture arch of tb_wb_indirect is
signal last_data : std_logic_vector (31 downto 0);
-- For end of test.
signal done : boolean := False;
begin
-- Clock.
process
begin
clk <= '0';
wait for 4 ns;
clk <= '1';
wait for 4 ns;
wait for C_CLK_PERIOD/2;
clk <= '0';
wait for C_CLK_PERIOD/2;
if done then
report "end of test";
wait;
end if;
end process;
rst_n <= '0', '1' after 8 ns;
rst_n <= '0', '1' after 2*C_CLK_PERIOD;
-- Test process.
process
......@@ -49,22 +54,34 @@ begin
write32_pl (clk, wb_in, wb_out, x"0000_0000", x"0000_2300");
wait until rising_edge (clk);
-- Read data.
read32_pl (clk, wb_in, wb_out, x"0000_0004", data);
assert data = x"0000_2300";
assert data = x"0000_2300"
report "wrong data"
severity failure;
wait until rising_edge (clk);
write32_pl (clk, wb_in, wb_out, x"0000_0004", x"1234_5678");
assert last_addr = x"0000_2304";
assert last_data = x"1234_5678";
assert last_addr = x"0000_2304"
report "wrong last address"
severity failure;
assert last_data = x"1234_5678"
report "wrong last data"
severity failure;
read32_pl (clk, wb_in, wb_out, x"0000_0004", data);
assert data = x"0000_2308";
assert last_data = x"1234_5678";
assert data = x"0000_2308"
report "wrong last read data"
severity failure;
assert last_data = x"1234_5678"
report "wrong last read address"
severity failure;
done <= true;
report "Test PASS with no failures!";
wait;
end process;
......
action = "simulation"
target = "generic"
sim_top = "tb_xwb_metadata"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../",
"../../../modules/wishbone",
"../../../sim/vhdl"] };
files = ["tb_xwb_metadata.vhd"]
Simple testbench for this little ROM which provides metadata for the "Convention". It uses OSVVM methodology and random inputs, based on random seed, are assigned in every clock cycle to the (input wishbone) signals. When the core is busy, and regarding of the value of the incoming address, the output data can receive a different value, as it is specified in the core's specifications.
Self-Checking: There are various assertions which can verify the proper functionality of the core by checking the value of the output wishbone data if it matches the expected one.
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_xwb_metadata
echo "Running simulation for $TB"
echo "This test is running with seed = 123456789"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM --wave=waveform.ghw
echo "*******************************************************************************"
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: tb_xwb_metadata
--
-- description: Testbench for this little ROM which provides metadata for the
-- 'convention'.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2019
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
--==============================================================================
-- Libraries & Packages --
--==============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.wishbone_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_xwb_metadata --
--=============================================================================
entity tb_xwb_metadata is
generic (
-- Seed of the test
g_seed : natural;
-- The vendor ID. Official PCI VID are valid.
-- The default is the CERN PCI VID.
g_VENDOR_ID : std_logic_vector(31 downto 0) := x"000010dc";
-- Device ID, defined by the vendor.
-- non accurate value given for test
g_DEVICE_ID : std_logic_vector(31 downto 0) := x"FFFFFFFF";
-- Version (semantic version).
-- non accurate value given for test
g_VERSION : std_logic_vector(31 downto 0) := x"00000001";
-- Capabilities. Specific to the device.
-- non accurate value given for test
g_CAPABILITIES : std_logic_vector(31 downto 0):=x"00000010";
-- Git commit ID.
-- non accurate value given for test
g_COMMIT_ID : std_logic_vector(127 downto 0) := x"AAAAAAAABBBBBBBB0000001010001010");
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_xwb_metadata is
-- Constants
constant C_CLK_PERIOD : time := 10 ns;
-- Signals
signal tb_clk_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_wb_i : t_wishbone_master_out;
signal tb_wb_o : t_wishbone_master_in;
signal stop : boolean;
signal s_busy : std_logic;
signal s_select : std_logic_vector(3 downto 0);
begin
-- Unit Under Test
UUT : entity work.xwb_metadata
generic map (
g_VENDOR_ID => g_VENDOR_ID,
g_DEVICE_ID => g_DEVICE_ID,
g_VERSION => g_VERSION,
g_CAPABILITIES => g_CAPABILITIES,
g_COMMIT_ID => g_COMMIT_ID)
port map(
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
wb_i => tb_wb_i,
wb_o => tb_wb_o);
-- Clock generation
clk_proc : process
begin
while STOP = FALSE loop
tb_clk_i <= '1';
wait for C_CLK_PERIOD/2;
tb_clk_i <= '0';
wait for C_CLK_PERIOD/2;
end loop;
wait;
end process clk_proc;
-- reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_SEED);
report "[STARTING Slave] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while (NOW < 2 ms) loop
wait until rising_edge(tb_clk_i);
tb_wb_i.cyc <= data.randSlv(1)(1);
tb_wb_i.stb <= data.randSlv(1)(1);
tb_wb_i.we <= data.randSlv(1)(1);
tb_wb_i.adr <= data.randSlv(c_wishbone_address_width);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process stim;
-- used to describe when the core is busy
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
s_busy <= '0';
else
s_busy <= '0';
if (s_busy='0' and tb_wb_i.cyc = '1' and tb_wb_i.stb = '1') then
s_busy <= '1';
if (s_busy = '1') then
assert (tb_wb_o.ack = '1')
report "wrong ACK"
severity failure;
end if;
end if;
end if;
end if;
end process;
s_select <= tb_wb_i.adr(5 downto 2) when (tb_wb_i.stb='1' and tb_wb_i.cyc='1' and s_busy='0')
else x"0";
--------------------------------------------------------------------------------
-- Assertions - Self Checking --
--------------------------------------------------------------------------------
-- The following assertions will ensure that we have the appropriate output data
-- as it is described in RTL
process
begin
while not stop loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
wait until (s_busy = '1');
case s_select is
when x"0" =>wait for C_CLK_PERIOD;
assert (tb_wb_o.dat = g_VENDOR_ID)
report "Data should be VENDOR_ID"
severity failure;
when x"1" => assert (tb_wb_o.dat = g_DEVICE_ID)
report "Data should be DEVICE_ID"
severity failure;
when x"2" => assert (tb_wb_o.dat = g_VERSION)
report "Data should be VERSION"
severity failure;
when x"3" => assert (tb_wb_o.dat = x"FFFE0000")
report "Data should be FFFE0000"
severity failure;
when x"4" => assert (tb_wb_o.dat = g_COMMIT_ID(127 downto 96))
report "Data should be COMMIT_ID(127:96)"
severity failure;
when x"5" => assert (tb_wb_o.dat = g_COMMIT_ID(95 downto 64))
report "Data should be COMMIT_ID(95 downto 64)"
severity failure;
when x"6" => assert (tb_wb_o.dat = g_COMMIT_ID(63 downto 32))
report "Data should be COMMIT_ID(63 downto 32)"
severity failure;
when x"7" => assert (tb_wb_o.dat = g_COMMIT_ID(31 downto 0))
report "Data should be COMMIT_ID(31 downto 0)"
severity failure;
when x"8" => assert (tb_wb_o.dat = g_CAPABILITIES)
report "Data should be CAPABILITIES"
severity error;
when others => assert (tb_wb_o.dat = x"00000000")
report "Data should be 0"
severity error;
end case;
end loop;
wait;
end process;
end tb;
action = "simulation"
target = "generic"
sim_top = "tb_wb_skidpad"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../"]}
files = ["tb_wb_skidpad.vhd"]
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_wb_skidpad
echo "*******************************************************************************"
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM
echo "*******************************************************************************"
This diff is collapsed.
action = "simulation"
target = "generic"
sim_top = "tb_xwb_register"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../",
"../../../../modules/wishbone",
"../../../../sim/vhdl"] };
files = ["tb_xwb_register.vhd"]
Testbench for a simple Wishbone Register. It is using OSVVM methodology with all the input signals in the stimulus to be get random values in each clock cycle. The simulation time, can be changed in the `stim` process, by changing the value of `NOW`. There are two test cases, one for CLASSIC and one for PIPELINED wishbone method. They test the functionality of this core, through FSM coverage and assertions.
FSM coverage: In the RTL core, there is a FSM which describes the behavior of the core. This testbench, covers all the possible changes of the states and also investigate if there are illigal transitions through the states. The goal is to reach 100% and all states covered at least once. The checking is done in every clock cycle, so when the state remains the some for some clock cycles is also covered.
Self-Checking: Various assertions are being implemented to verify the specifications of the core for the two different modes. There is also one general assertion to check if there is a mismatch between slave's output and master's input.
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_xwb_register
echo "Running simulation for $TB"
echo " TEST CASE 1 "
echo "Wishbone Mode = CLASSIC"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WB_MODE=CLASSIC
echo "*******************************************************************************"
echo " TEST CASE 2 "
echo "Wishbone Mode = PIPELINED"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WB_MODE=PIPELINED
echo "*******************************************************************************"
action = "simulation"
target = "generic"
sim_top = "tb_xwb_register_link"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../../",
"../../../../modules/wishbone",
"../../../../sim/vhdl"] };
files = ["tb_xwb_register_link.vhd"]
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_xwb_register_link
echo "*******************************************************************************"
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM --wave=waveform.ghw
echo "*******************************************************************************"
action = "simulation"
target = "generic"
sim_top = "tb_xwb_remapper"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
modules = { "local" : ["../../../",
"../../../modules/wishbone",
"../../../sim/vhdl"] };
files = ["tb_xwb_remapper.vhd"]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment