Commit 7a9aa82a authored by kblantos's avatar kblantos

Testbench added for Common core. Makefile and .yml file added to run CI for Gateware Simulations

parent d091832e
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
---
variables:
KOJI_TARGET: 'ohwr7'
KOJI_DISTTAG: '.el7.cern'
DIST_PATH: distribution
BUILD_PATH: distribution/rpmbuild
SRPM_PATH: distribution/rpmbuild/SRPMS/dkms-${CI_PROJECT_NAME}*src.rpm
GIT_SUBMODULE_STRATEGY: normal
GIT_DEPTH: "1"
stages:
- static-analysis
- build
- srpm
- kscratch
- kbuild
reuse:
stage: static-analysis
image: fsfe/reuse:latest
script:
- reuse lint
allow_failure: true
- simulation
build:
stage: build
vhdl_cores_simulation:
tags:
- ghdl_ohwrcs8
stage: simulation
script:
- yum install -y kernel-devel git
- export LINUX=/usr/src/kernels/*/
- make -C software
- /entrypoint.sh
- cd testbench/
- make
# artifacts:
# paths:
build-dkms:
stage: build
script:
- yum install -y kernel-devel lua git dkms
- export LINUX=/usr/src/kernels/*/
- export PREFIX=$(mktemp -d)
- make -C software/ -f dkms.mk dkms_install
- make -C ${PREFIX}/usr/src/${CI_PROJECT_NAME}*/
build_srpm:
stage: srpm
script:
- yum-builddep -y ${DIST_PATH}/*.spec
- export LINUX=/usr/src/kernels/*/
- make -C distribution rpmbuild-source
artifacts:
paths:
- ${SRPM_PATH}
expire_in: 1 day
.koji_deps_template: &koji_deps
before_script:
- yum install -y koji krb5-workstation rpm-build
- echo ${OHWR_PASSWORD} | kinit ${OHWR_USER}
kscratch:
<<: *koji_deps
stage: kscratch
script:
- koji --config=.koji build --wait --scratch ${KOJI_TARGET} ${SRPM_PATH}
kbuild-ohwr:
<<: *koji_deps
stage: kbuild
only:
- /^v[0-9]+\.[0-9]+\.[0-9]+$/
except:
- branches
script:
- koji --config=.koji build --wait ${KOJI_TARGET} ${SRPM_PATH}
#wb_i2c_master_simulation:
# tags:
# - modelsim_10_2a
# stage: simulation
# script:
# - /entrypoint.sh
# - source ~/setup_modelsim.sh
# - cd testbench/wishbone/wb_i2c_master
# - cp /opt/compiled_libs_ise14.7/modelsim.ini .
# - hdlmake makefile
# - cat Makefile
# - make
# - vsim -c -do run.do
## artifacts:
## paths:
## - hdl/testbench/wishbone/wb_fine_pulse_gen
#wb_fine_pulse_gen_simulate:
# tags:
# - modelsim_10_2a
# stage: simulation
# script:
# - /entrypoint.sh
# - source ~/setup_modelsim.sh
# - cd testbench/wishbone/wb_fine_pulse_gen
# - git submodule init && git submodule update
# - cp /opt/compiled_libs_ise14.7/modelsim.ini .
# - hdlmake makefile
# - cat Makefile
# - make
# - vsim -c -do run.do
# artifacts:
# paths:
# - hdl/testbench/wishbone/wb_fine_pulse_gen
#wb_xilinx_fpga_loader_simulate:
# tags:
# - modelsim_10_2a
# stage: simulation
# script:
# - /entrypoint.sh
# - source ~/setup_modelsim.sh
# - cd testbench/wishbone/wb_xilinx_fpga_loader
# - git submodule init && git submodule update
# - cp /opt/compiled_libs_ise14.7/modelsim.ini .
# - hdlmake makefile
# - make
# - vsim -c -do run.do
# artifacts:
# paths:
# - hdl/testbench/wishbone/wb_fine_pulse_gen
#wb_uart_simulate:
# tags:
# - modelsim_10_2a
# stage: simulation
# script:
# - /entrypoint.sh
# - source ~/setup_modelsim.sh
# - cd testbench/wishbone/wb_uart
# - git submodule init && git submodule update
# - cp /opt/compiled_libs_ise14.7/modelsim.ini .
# - hdlmake makefile
# - make
# - vsim -c -do run.do
# artifacts:
# paths:
# - hdl/testbench/wishbone/wb_fine_pulse_gen
#wb_gpio_port_simulate:
# tags:
# - modelsim_10_2a
# stage: simulation
# script:
# - /entrypoint.sh
# - source ~/setup_modelsim.sh
# - cd testbench/wishbone/wb_gpio_port
# - git submodule init && git submodule update
# - cp /opt/compiled_libs_ise14.7/modelsim.ini .
# - hdlmake makefile
# - make
# - vsim -c -do run.do
# artifacts:
# paths:
# - hdl/testbench/wishbone/
#wb_simple_pwm_simulate:
# tags:
# - modelsim_10_2a
# stage: simulation
# script:
# - /entrypoint.sh
# - source ~/setup_modelsim.sh
# - cd testbench/wishbone/wb_simple_pwm
# - git submodule init && git submodule update
# - cp /opt/compiled_libs_ise14.7/modelsim.ini .
# - hdlmake makefile
# - make
# - vsim -c -do run.do
## artifacts:
## paths:
## - hdl/testbench/wishbone/wb_fine_pulse_gen
#---
#variables:
# KOJI_TARGET: 'ohwr7'
# KOJI_DISTTAG: '.el7.cern'
# DIST_PATH: distribution
# BUILD_PATH: distribution/rpmbuild
# SRPM_PATH: distribution/rpmbuild/SRPMS/dkms-${CI_PROJECT_NAME}*src.rpm
#stages:
# - static-analysis
# - build
# - srpm
# - kscratch
# - kbuild
#reuse:
# stage: static-analysis
# image: fsfe/reuse:latest
# script:
# - reuse lint
# allow_failure: true
#build:
# stage: build
# script:
# - yum install -y kernel-devel git
# - export LINUX=/usr/src/kernels/*/
# - make -C software
#build-dkms:
# stage: build
# script:
# - yum install -y kernel-devel lua git dkms
# - export LINUX=/usr/src/kernels/*/
# - export PREFIX=$(mktemp -d)
# - make -C software/ -f dkms.mk dkms_install
# - make -C ${PREFIX}/usr/src/${CI_PROJECT_NAME}*/
#build_srpm:
# stage: srpm
# script:
# - yum-builddep -y ${DIST_PATH}/*.spec
# - export LINUX=/usr/src/kernels/*/
# - make -C distribution rpmbuild-source
# artifacts:
# paths:
# - ${SRPM_PATH}
# expire_in: 1 day
#.koji_deps_template: &koji_deps
# before_script:
# - yum install -y koji krb5-workstation rpm-build
# - echo ${OHWR_PASSWORD} | kinit ${OHWR_USER}
#kscratch:
# <<: *koji_deps
# stage: kscratch
# script:
# - koji --config=.koji build --wait --scratch ${KOJI_TARGET} ${SRPM_PATH}
#kbuild-ohwr:
# <<: *koji_deps
# stage: kbuild
# only:
# - /^v[0-9]+\.[0-9]+\.[0-9]+$/
# except:
# - branches
# script:
# - koji --config=.koji build --wait ${KOJI_TARGET} ${SRPM_PATH}
# This Makefile can be called by the Continuous Integration (CI) tool to execute all
# testbenches added for CI
# AXI4 cores
TB_DIRS+=axi/axi4lite_wb_bridge
TB_DIRS+=axi/z7_axi_gpio_expander
TB_DIRS+=axi/axi4lite32_axi4full64_bridge
TB_DIRS+=axi/axi4lite_axi4full_bridge
# Common Cores
TB_DIRS+=common/gc_edge_detect
TB_DIRS+=common/gc_pulse_synchronizer2
TB_DIRS+=common/gc_reset_multi_aasd
TB_DIRS+=common/gc_sync
TB_DIRS+=common/gc_sync_ffs
TB_DIRS+=common/gc_sync_register
TB_DIRS+=common/gc_sync_word_rd
TB_DIRS+=common/gc_sync_word_wr
TB_DIRS+=common/gc_arbitrated_mux
TB_DIRS+=common/gc_delay_gen
TB_DIRS+=common/gc_delay_line
TB_DIRS+=common/gc_dyn_extend_pulse
TB_DIRS+=common/gc_glitch_filt
TB_DIRS+=common/gc_extend_pulse
TB_DIRS+=common/gc_dyn_extend_pulse
TB_DIRS+=common/gc_fsm_watchdog
TB_DIRS+=common/gc_async_counter_diff
TB_DIRS+=common/gc_async_signals_input_stage
TB_DIRS+=common/gc_multichannel_frequency_meter
TB_DIRS+=common/gc_negedge
TB_DIRS+=common/gc_posedge
TB_DIRS+=common/gc_reset
#TB_DIRS+=common/gc_prio_encoder
TB_DIRS+=common/gc_rr_arbiter
TB_DIRS+=common/gc_simple_spi_master
TB_DIRS+=common/gc_serial_dac
TB_DIRS+=common/gc_bicolor_led_ctrl
TB_DIRS+=common/gc_big_adder
TB_DIRS+=common/gc_comparator
TB_DIRS+=common/gc_moving_average
TB_DIRS+=common/gc_dual_pi_controller
TB_DIRS+=common/gc_word_packer
TB_DIRS+=common/gc_i2c_slave
TB_DIRS+=common/gc_ds182x_readout
# Genram cores
TB_DIRS+=genrams/common/inferred_async_fifo_dual_rst
TB_DIRS+=genrams/generic/generic_async_fifo_dual_rst
TB_DIRS+=genrams/xilinx/generic_dpram
TB_DIRS+=genrams/generic/generic_async_fifo
TB_DIRS+=genrams/generic/generic_sync_fifo
TB_DIRS+=genrams/altera/gc_shiftreg
TB_DIRS+=genrams/xilinx/generic_simple_dpram
TB_DIRS+=genrams/xilinx/generic_spram
TB_DIRS+=genrams/xilinx/generic_dpram_split
TB_DIRS+=genrams/xilinx/generic_dpram_sameclock
TB_DIRS+=genrams/xilinx/generic_dpram_dualclock
TB_DIRS+=genrams/xilinx/gc_shiftreg
TB_DIRS+=genrams/common/inferred_sync_fifo
TB_DIRS+=genrams/common/inferred_async_fifo
# Wishbone Cores
TB_DIRS+=wishbone/wb_axi4lite_bridge
TB_DIRS+=wishbone/wb_split
TB_DIRS+=wishbone/wb_dpram/xwb_dpram
TB_DIRS+=wishbone/wb_clock_crossing/xwb_clock_crossing
TB_DIRS+=wishbone/wb_clock_crossing/xwb_clock_bridge
TB_DIRS+=wishbone/wb_slave_adapter
TB_DIRS+=wishbone/wb_indirect
TB_DIRS+=wishbone/wb16_to_wb32
TB_DIRS+=wishbone/wb_metadata
TB_DIRS+=wishbone/wb_remapper
TB_DIRS+=wishbone/wb_async_bridge
TB_DIRS+=wishbone/wb_register/xwb_register
TB_DIRS+=wishbone/wb_register/xwb_register_link
TB_DIRS+=wishbone/wb_register/wb_skidpad
TB_DIRS+=wishbone/wb_crossbar/sdb_rom
TB_DIRS+=wishbone/wb_crossbar/xwb_crossbar
.PHONY: $(TB_DIRS)
all: $(TB_DIRS) summary
$(TB_DIRS):
@echo "Compime OSVVM"
cd "$@"; \
/usr/local/lib/ghdl/vendors/compile-osvvm.sh --all 2>&1
@echo $@
@echo "Run HDLMAKE"
cd "$@"; \
hdlmake 2>&1
@echo "Run make"
$(MAKE) -C $@ $(TARGET)
@echo "Run ghdl"
cd "$@" ;\
./run.sh
echo "ghdl returned $$?"
summary: $(TB_DIRS)
@echo "-------------------------------------------------------------------"
@echo "Summary:"
@for d in $(TB_DIRS); do \
if [ -f $$d/transcript ]; then \
echo "Warnings for $$d:"; \
cat $$d/transcript | grep Warning; \
if [ $$? -eq 1 ]; then echo "None"; fi ;\
echo "Errors for $$d:"; \
cat $$d/transcript | grep Error; \
if [ $$? -eq 1 ]; then echo "None"; fi ;\
else \
echo "No transcript file for $$d"; \
fi \
done
clean:
@for d in $(TB_DIRS); do \
if [ -f $$d/Makefile ]; then \
$(MAKE) -C $$d $@; \
rm -f $$d/Makefile; \
fi \
done
The majority of the general cores has each own testbench written in VHDL and is using OSVVM as a verification methodology. Below, there are the requirements, that the user should fullfil, in order to run the tests locally:
1. Install `HDLMAKE`, `GHDL` and `OSVVM(2020.05+)`
2. Add in `usr/local/lib/ghdl/vendors/config.sh` the path of the downloaded OSVVM
There are two options for the user, in order to run these testbenches. One is to run them all through the Makefile that exist in this directory. This Makefile, contains all the tests, so with `make`, all the tests will run. The other option is to run a specific one seperately. For that option, these are the steps that need to be followed:
1. Compile OSVVM by running the script: `/usr/local/lib/ghdl/vendors/compile-osvvm --all`
2. Run `hdlmake makefile`
3. Run `make`
4. Run `./run.sh`
5. (Optional) add in the run.sh --wave=waveform.ghw to see waveform with gtkwave
6. See the results of the test in the terminal
action="simulation"
sim_tool="ghdl"
sim_top="tb_gc_arbitrated_mux"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
files="tb_gc_arbitrated_mux.vhd"
modules={"local" : ["../../../",
"../../../modules/common",
"../../../modules/genrams"]}
This is a simple test which verify the functionality of the gc_arbitrated_mux.
Various cases are being tested, regarding the number of inputs and the data width.
In additions, assertions are being used to verify that the output that comes from
RTL core is the same as the one that the testbench has.
The testing process is:
- Randomized inputs are given to the Design Under Test in order to check the functionality of the RTL core.
For a given number of inputs, there are randomized inputs for a given data width.
- A simple coverage metric, where counting the number of valid outputs.
- An assertion is used to verify that the output and input data is the same.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_arbitrated_mux
echo "Running simulation for $TB"
echo "************************************"
echo " TEST CASE 1 "
echo "Number of inputs = 1, data width = 1"
echo "************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_inputs=1 -gg_width=1
echo "************************************"
echo " TEST CASE 2 "
echo "Number of inputs = 2, data width = 2"
echo "************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_inputs=2 -gg_width=2
echo "************************************"
echo " TEST CASE 3 "
echo "Number of inputs = 2, data width = 8"
echo "************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_inputs=2 -gg_width=8
echo "*************************************"
echo " TEST CASE 4 "
echo "Number of inputs = 8, data width = 32"
echo "*************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_num_inputs=8 -gg_width=32
-------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- Title : Multiplexer with round-robin arbitration
-- Project : General Cores Collection library
-------------------------------------------------------------------------------
-- File : tb_gc_arbitrated_mux.vhd
-- Author : Konstantinos Blantos
-- Company : CERN (BE-CEM-EDL)
-- Created : 2020-11-17
-- Last update:
-- Platform : FPGA-generic
-- Standard : VHDL'08
-------------------------------------------------------------------------------
-- Description: Test bench for the arbitrated mux which is an N-channel
-- time-division multiplexer with round robin arbitration
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011 CERN / BE-CO-HT
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); 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-0.51.
-- 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.
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.genram_pkg.all;
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_arbitrated_mux is
generic (
g_seed : natural;
g_num_inputs : integer := 2;
g_width : integer := 2);
end entity;
architecture tb of tb_gc_arbitrated_mux 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_d_i : std_logic_vector(g_num_inputs * g_width-1 downto 0);
signal tb_d_valid_i : std_logic_vector(g_num_inputs-1 downto 0);
signal tb_d_req_o : std_logic_vector(g_num_inputs-1 downto 0);
signal tb_q_o : std_logic_vector(g_width-1 downto 0);
signal tb_q_valid_o : std_logic;
signal tb_q_input_id_o : std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0);
signal stop : boolean;
type t_data_array is array(0 to g_num_inputs-1) of std_logic_vector(g_width-1 downto 0);
signal s_regs_i : t_data_array;
signal s_data_i : std_logic_vector((g_num_inputs * g_width)-1 downto 0);
signal s_data_o : std_logic_vector((g_num_inputs * g_width)-1 downto 0);
signal s_cnt : unsigned(g_num_inputs-1 downto 0) := (others=>'0');
-- for coverage
shared variable cp_q_valid_o : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_arbitrated_mux
generic map (
g_num_inputs => g_num_inputs,
g_width => g_width)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
d_i => tb_d_i,
d_valid_i => tb_d_valid_i,
d_req_o => tb_d_req_o,
q_o => tb_q_o,
q_valid_o => tb_q_valid_o,
q_input_id_o => tb_q_input_id_o);
-- Clock and reset
clk_process : 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;
tb_rst_n_i <= '0', '1' after 2 * C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while (NOW < 2 ms) loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
for i in 0 to g_num_inputs-1 loop
if tb_d_req_o(i) = '1' then
tb_d_valid_i(i) <= data.randSlv(1)(1);
tb_d_i <= data.randSlv(g_num_inputs*g_width);
else
tb_d_valid_i <= (others=>'0');
end if;
end loop;
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
wait;
end process;
--------------------------------------------------------------------------
-- Assertions - Self Checking --
--------------------------------------------------------------------------
-- Storing the valid input data in a register
input_side : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '1' then
for i in 0 to g_num_inputs-1 loop
if tb_d_valid_i(i) = '1' then
s_regs_i(i) <= tb_d_i(g_width*(i+1)-1 downto g_width*i);
end if;
end loop;
end if;
end if;
end process;
--storing the input and output valid data in registers
creating_vectors : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_q_valid_o = '1' then
s_cnt <= s_cnt + 1;
if s_cnt = 0 then
s_data_o(g_width-1 downto 0) <= tb_q_o;
s_data_i(g_width-1 downto 0) <= s_regs_i(to_integer(s_cnt));
elsif s_cnt < g_num_inputs then
s_data_o((g_width)*to_integer(s_cnt)+g_width-1 downto g_width*(to_integer(s_cnt))) <= tb_q_o;
s_data_i((g_width)*to_integer(s_cnt)+g_width-1 downto g_width*(to_integer(s_cnt))) <= s_regs_i(to_integer(s_cnt));
else
s_cnt <= (others=>'0');
end if;
else
s_cnt <= (others=>'0');
end if;
end if;
end process;
-- Comparing the input and output
self_check : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if falling_edge(tb_q_valid_o) then
assert (s_data_o = s_data_i)
report "Data mismatch" severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------
-- Sets up coverpoint bins
InitCoverage : process
begin
cp_q_valid_o.AddBins("valid output data", ONE_BIN);
wait;
end process InitCoverage;
-- Count the number of valid output data
sample : process
begin
loop
wait until rising_edge(tb_clk_i);
cp_q_valid_o.ICover(to_integer(tb_q_valid_o = '1'));
end loop;
end process sample;
-- Report of the coverage
CoverReports : process
begin
wait until stop;
report "valid output";
cp_q_valid_o.writebin;
report "PASS";
end process CoverReports;
end tb;
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_async_counter_diff"
files="tb_gc_async_counter_diff.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench for gc_async_counter_diff. Various test cases are tested regarding
the counter width (in bits) and which is the output clock (either increment or decrement).
In the testbench there are two different stimulus, one for INC and one for DEC. We have
two different clocks, so this test can be tested when:
1) clocks are same
2) inc clock > dec clock
3) inc clock < dec clock
The testing process is:
- Assign a constant value of inc and dec clock. Then give random values to inc/dec valid
and check the output counter.
- Some simple coverage metrics for example, to ensure that reset asserted
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_async_counter_diff
echo "Running simulation for $TB"
echo "**************************************************"
echo " TEST CASE 1 "
echo "Number of counter widdth = 1, g_output_clock = inc"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=1 -gg_output_clock="inc"
echo "**************************************************"
echo " TEST CASE 2 "
echo "Number of counter widdth = 4, g_output_clock = inc"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=4 -gg_output_clock="inc"
echo "**************************************************"
echo " TEST CASE 3 "
echo "Number of counter widdth = 8, g_output_clock = inc"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=8 -gg_output_clock="inc"
echo "**************************************************"
echo " TEST CASE 4 "
echo "Number of counter widdth = 15, g_output_clock = inc"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=15 -gg_output_clock="inc"
echo "**************************************************"
echo " TEST CASE 5 "
echo "Number of counter widdth = 1, g_output_clock = dec"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=1 -gg_output_clock="dec"
echo "**************************************************"
echo " TEST CASE 6 "
echo "Number of counter widdth = 4, g_output_clock = dec"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=4 -gg_output_clock="dec"
echo "**************************************************"
echo " TEST CASE 7 "
echo "Number of counter widdth = 8, g_output_clock = dec"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=8 -gg_output_clock="dec"
echo "**************************************************"
echo " TEST CASE 8 "
echo "Number of counter widdth = 15, g_output_clock = dec"
echo "**************************************************"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_bits=15 -gg_output_clock="dec"
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- general-cores
-- https://www.ohwr.org/project/general-cores
--------------------------------------------------------------------------------
--
-- unit name : tb_gc_async_counter_diff.vhd
-- author : Konstantinos Blantos
-- description: Testbench for gc_async_counter_diff
--
-- The module counts pulses on inc_i and dec_i inputs. Each input can be
-- in its own clock domain. The module outputs difference in the number of
-- pulses counted on inc_i and dec_i. The output is in the clock domain
-- selected with the g_output_clock generic (that of inc_i or of dec_i).
--
-- Internally, Grey Codes are used and count encoded with Grey Code is
-- resynchronized to the output clock domain. Therefore, the output
-- is provided few clock cycles after pulse actually occured.
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN BE/CO/HT
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- 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
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_async_counter_diff is
generic (
g_seed : natural;
g_bits : integer;
g_output_clock : string);
end entity;
architecture tb of tb_gc_async_counter_diff is
-- Constants
constant C_INC_CLK_PERIOD : time := 5 ns;
constant C_DEC_CLK_PERIOD : time := 10 ns;
-- Signals
signal tb_rst_n_i : std_logic;
signal tb_clk_inc_i : std_logic;
signal tb_clk_dec_i : std_logic;
signal tb_inc_i : std_logic := '0';
signal tb_dec_i : std_logic := '0';
signal tb_counter_o : std_logic_vector(g_bits downto 0);
signal stop : boolean;
-- Shared variables used in coverage
shared variable cp_rst_n_i : covPType;
shared variable cp_inc_i : covPType;
shared variable cp_dec_i : covPType;
shared variable cp_cnt_eq : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_async_counter_diff
generic map (
g_bits => g_bits,
g_output_clock => g_output_clock)
port map (
rst_n_i => tb_rst_n_i,
clk_inc_i => tb_clk_inc_i,
clk_dec_i => tb_clk_dec_i,
inc_i => tb_inc_i,
dec_i => tb_dec_i,
counter_o => tb_counter_o);
-- Clock inc generation
clk_inc_process : process
begin
while (stop = FALSE) loop
tb_clk_inc_i <= '1';
wait for C_INC_CLK_PERIOD/2;
tb_clk_inc_i <= '0';
wait for C_INC_CLK_PERIOD/2;
end loop;
wait;
end process;
-- Clock dec generation
clk_dec_process : process
begin
while (stop = FALSE) loop
tb_clk_dec_i <= '1';
wait for C_DEC_CLK_PERIOD/2;
tb_clk_dec_i <= '0';
wait for C_DEC_CLK_PERIOD/2;
end loop;
wait;
end process;
-- Reset g_output_clock domain
tb_rst_n_i <= '0', '1' after 4*C_DEC_CLK_PERIOD;
-- Stimulus for increment clock
stim_inc : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 2 ms loop
wait until (rising_edge(tb_clk_inc_i) and tb_rst_n_i = '1');
tb_inc_i <= data.randSlv(1)(1);
wait for 10*C_INC_CLK_PERIOD;
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles (inc) = " & to_string(ncycles);
report "Test PASS!";
stop <= true;
wait;
end process;
-- Stimulus for decrement clock
stim_dec : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
while not stop loop
wait until (rising_edge(tb_clk_dec_i) and tb_rst_n_i = '1');
tb_dec_i <= data.randSlv(1)(1);
wait for 10*C_DEC_CLK_PERIOD;
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles (dec) = " & to_string(ncycles);
wait;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_rst_n_i.AddBins("Reset has asserted" ,ONE_BIN);
cp_inc_i.AddBins ("Inc input has asserted",ONE_BIN);
cp_dec_i.AddBins ("Dec input has asserted",ONE_BIN);
cp_cnt_eq.AddBins ("Counter output is zero",ONE_BIN);
wait;
end process;
-- Sample the coverpoints
sample_rst_cov : process
begin
loop
wait on tb_rst_n_i;
cp_rst_n_i.ICover(to_integer(tb_rst_n_i = '1'));
end loop;
end process;
sample_inc_i : process
begin
loop
wait until rising_edge(tb_clk_inc_i);
cp_inc_i.ICover(to_integer(tb_inc_i = '1'));
end loop;
end process;
sample_dec_i : process
begin
loop
wait until rising_edge(tb_clk_dec_i);
cp_dec_i.ICover(to_integer(tb_dec_i = '1'));
end loop;
end process;
out_clk_is_inc : if (g_output_clock = "inc") generate
sample_cnt_equal : process
begin
loop
wait until rising_edge(tb_clk_inc_i) and tb_rst_n_i = '1';
cp_cnt_eq.ICover(to_integer(unsigned(tb_counter_o) = 0));
end loop;
end process;
end generate;
out_clk_is_dec : if (g_output_clock = "dec") generate
sample_cnt_equal : process
begin
loop
wait until rising_edge(tb_clk_dec_i) and tb_rst_n_i = '1';
cp_cnt_eq.ICover(to_integer(unsigned(tb_counter_o) = 0));
end loop;
end process;
end generate;
-- Report coverage
cover_report : process
begin
wait until stop;
cp_rst_n_i.Writebin;
cp_inc_i.Writebin;
cp_dec_i.Writebin;
cp_cnt_eq.Writebin;
end process;
end tb;
action="simulation"
target="generic"
sim_tool="ghdl"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_async_signals_input_stage"
files="tb_gc_async_signals_input_stage.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
Summary of test cases :
1. One clock and one reset to handle
2. Coming input async signals (can be more than one)
3. config_active_i goes with each input signal. Actually
this is the one that say if the pulses produced on falling edge
** this can be always high, always zero, and random
4. The output (signals_o) is synchronized to our clock
5. Now, depending on config_active_i, we have different values of the output
signals, signals_p1_o, signals_pN_o. The first one is HIGH if config HIGH
and is the "identity" let's say of the output signal.
The latter can be the same if we activate (more than 0) of g_extended_pulse_width.
The testing process is the following: Assign random input data using OSVVM, to verify the functionality
of the RTL core. In addition, a few assertions added in the testbench, for all the signals.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_async_signals_input_stage
echo "******************************************************************************************"
echo "Running simulation for $TB"
echo "******************************************************************************************"
echo ""
echo "**************************TEST CASE 1 *****************************************************"
echo "Number of input signals = 1, extended clock cycles = 0, cycles that filter out glitches = 0"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_signal_num=1 -gg_extended_pulse_width=0 -gg_dglitch_filter_len=0
echo""
echo "**************************TEST CASE 2 *****************************************************"
echo "Number of input signals = 1, extended clock cycles = 0, cycles that filter out glitches = 1"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_signal_num=1 -gg_extended_pulse_width=0 -gg_dglitch_filter_len=1
echo ""
echo "**************************TEST CASE 3 *****************************************************"
echo "Number of input signals = 2, extended clock cycles = 2, cycles that filter out glitches = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_signal_num=2 -gg_extended_pulse_width=2 -gg_dglitch_filter_len=2
echo ""
echo "**************************TEST CASE 4 *****************************************************"
echo "Number of input signals = 2, extended clock cycles = 2, cycles that filter out glitches = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_signal_num=2 -gg_extended_pulse_width=2 -gg_dglitch_filter_len=4
echo ""
echo "**************************TEST CASE 5 *****************************************************"
echo "Number of input signals = 4, extended clock cycles = 4, cycles that filter out glitches = 6"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_signal_num=4 -gg_extended_pulse_width=4 -gg_dglitch_filter_len=6
echo ""
echo "**************************TEST CASE 6 *****************************************************"
echo "Number of input signals = 8, extended clock cycles = 8, cycles that filter out glitches = 10"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_signal_num=8 -gg_extended_pulse_width=8 -gg_dglitch_filter_len=10
-------------------------------------------------------------------------------
-- Title : Testbench for Generic input stage for asynchronous input signals
-------------------------------------------------------------------------------
-- File : tb_gc_async_signals_input_stage.vhd
-- Author : Konstantinos Blantos
-- Company : CERN BE-CEM-EDL
-- Platform : FPGA-generics
-- Standard : VHDL 2008
-------------------------------------------------------------------------------
-- Description: Testbench for gc_async_signals_input_stage
--
-- A generic input stage for digital asynchronous input signals.
-- It implements a number of stages that might be generally useful/needed
-- before using such signals in a synchronous FPGA-base applications.
--
-- It includes the following input stages:
-- 1. synchronisation with clock domain with taking care for metastability
-- 2. choice of HIGH/LOW active
-- 3. degliching with a filter width set through generic
-- 4. single-clock pulse generation on edge detection
-- * rising edge if HIGH active set
-- * falling edge if LOW actvie set
-- 5. extension of pulse with width set through generic
--
-- The output provides three outputs, any of them can be used at will
-- signals_o : synchronised and deglichted signal active LOW or HIGH,
-- depending on conifg
-- signals_p_o : single-clock pulse on rising/faling edge of the synchronised
-- and degliched signal
-- signals_pN_o : the single-clock pulse extended
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2016 CERN/TE-MS-MM
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); 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-0.51.
-- 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.
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2021-11-26 1.0 kblantos created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_async_signals_input_stage is
generic (
g_seed : natural;
g_signal_num : integer;
g_extended_pulse_width : integer;
g_dglitch_filter_len : integer);
end entity;
architecture tb of tb_gc_async_signals_input_stage 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_signals_a_i : std_logic_vector(g_signal_num-1 downto 0) :=(others=>'0');
signal tb_config_active_i : std_logic_vector(g_signal_num-1 downto 0) :=(others=>'0');
signal tb_signals_o : std_logic_vector(g_signal_num-1 downto 0);
signal tb_signals_p1_o : std_logic_vector(g_signal_num-1 downto 0);
signal tb_signals_pN_o : std_logic_vector(g_signal_num-1 downto 0);
signal stop : boolean;
begin
-- Unit Under Test
UUT : entity work.gc_async_signals_input_stage
generic map (
g_signal_num => g_signal_num,
g_extended_pulse_width => g_extended_pulse_width,
g_dglitch_filter_len => g_dglitch_filter_len)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
signals_a_i => tb_signals_a_i,
config_active_i => tb_config_active_i,
signals_o => tb_signals_o,
signals_p1_o => tb_signals_p1_o,
signals_pN_o => tb_signals_pN_o);
-- Clock and reset generation
clk_i_process : process
begin
while (not stop) 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while (NOW < 1 ms) loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
tb_signals_a_i <= data.randSlv(g_signal_num);
tb_config_active_i <= data.randSlv(g_signal_num);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
stop <= true;
report "Test PASS!";
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions
--------------------------------------------------------------------------------
-- At least one signal to be synchronized
assert (g_signal_num > 0)
report "Invalid value of input signals" severity failure;
-- Zero or more than one is the valid value of extended pulse width
-- (due to dependency of gc_extend_pulse)
assert (g_extended_pulse_width = 0 or g_extended_pulse_width > 1)
report "Invalid value of extended pulse width value" severity failure;
-- Checking that signals_p1_o is '1' on rising or falling edge (depending the conf.)
gen_signals : for i in 0 to g_signal_num-1 generate
check_signals_p1 : process
begin
while not stop loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
wait until rising_edge(tb_signals_o(i));
wait for 2*C_CLK_PERIOD;
assert (tb_signals_p1_o(i) = '1')
report "Wrong value for single-clock output" severity failure;
end loop;
end process;
-- Checking that signals_pn is '1' on rising or falling edge (depending the conf.)
gen_with_pulse_extender : if g_extended_pulse_width>1 generate
check_signals_pn : process
begin
while not stop loop
wait until (tb_signals_o(i) = '1');
wait for g_extended_pulse_width*C_CLK_PERIOD;
assert (tb_signals_pn_o(i) = '1')
report "Wrong value for multi-clock output" severity failure;
end loop;
end process;
end generate gen_with_pulse_extender;
-- Value of signals_p1 and signals_pn is the same, except that pn is extended
check_same_value : process
begin
while not stop loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
wait until rising_edge(tb_signals_o(i));
wait for 2*C_CLK_PERIOD;
assert (tb_signals_p1_o(i) = tb_signals_pn_o(i))
report "different output pulses" severity failure;
end loop;
end process;
end generate gen_signals;
end tb;
action = "simulation"
sim_tool = "modelsim"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
target = "xilinx"
syn_device = "xc6slx45t"
......@@ -14,5 +15,6 @@ files = [
modules = {
"local" : [
"../../../",
"../../../modules/common"
],
}
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
#In case we need to see waveforms, type --wave=waveform.ghw
#in the end of each command
TB=gc_bicolor_led_ctrl_tb
echo "Running simulation for $TB"
echo "******************** TEST CASE **********************************"
echo "column=4, line=2, clock frequency in Hz=125000000, refresh rate=250"
ghdl -r --std=08 -frelaxed-rules $TB --stop-time=100ms
echo "*********************************************************************"
action="simulation"
sim_tool="ghdl"
target="xilinx"
syn_device="xc6slx45t"
top_module="tb_gc_big_adder" #hdlmake2
sim_top="tb_gc_big_adder" #hdlmake3
ghdl_opt="--std=08 -frelaxed-rules"
files = ["tb_gc_big_adder.vhd"]
modules= {"local" : ["../../../",
"../../../modules/common"]}
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
#In case we need to see waveforms, type --wave=waveform.ghw
#in the end of each command
TB=tb_gc_big_adder
echo "Running simulation for $TB"
echo "data bits = 64, g_parts = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_data_bits=64 -gg_parts=4
echo "***********************************************************"
echo "data bits = 32, g_parts = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_data_bits=32 -gg_parts=2
echo "***********************************************************"
echo "data bits = 16, g_parts = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_data_bits=16 -gg_parts=4
echo "***********************************************************"
echo "data bits = 8, g_parts = 1"
ghdl -r --std=08 -frelaxed-rules $TB -gg_data_bits=8 -gg_parts=1
echo "***********************************************************"
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity tb_gc_big_adder is
generic (
g_data_bits : natural := 64;
g_parts : natural := 4);
end entity tb_gc_big_adder;
architecture tb of tb_gc_big_adder is
-- Signal declarations
signal tb_clk_i : std_logic;
signal tb_stall_i : std_logic;
signal tb_a_i : std_logic_vector(g_data_bits-1 downto 0);
signal tb_b_i : std_logic_vector(g_data_bits-1 downto 0);
signal tb_c_i : std_logic;
signal tb_c1_o : std_logic;
signal tb_x2_o : std_logic_vector(g_data_bits-1 downto 0);
signal tb_c2_o : std_logic;
signal tb_sim_end : std_logic;
begin
-- Unit Under Test instantiation
UUT : entity work.gc_big_adder
generic map (
g_data_bits => g_data_bits,
g_parts => g_parts)
port map (
clk_i => tb_clk_i,
stall_i => tb_stall_i,
a_i => tb_a_i,
b_i => tb_b_i,
c_i => tb_c_i,
c1_o => tb_c1_o,
x2_o => tb_x2_o,
c2_o => tb_c2_o);
-- Clock process definitions
clk_i_process : process
begin
while tb_sim_end /= '1' loop
tb_clk_i <= '0';
wait for 5 NS;
tb_clk_i <= '1';
wait for 5 NS;
end loop;
wait;
end process;
-- Stimulus process
stim_proc : process
procedure wait_clock_rising(
constant cycles : in integer) is
begin
for i in 1 to cycles loop
wait until rising_edge(tb_clk_i);
end loop;
end procedure wait_clock_rising;
procedure assign_input (
constant value_a : in integer;
constant value_b : in integer;
constant value_c : in std_logic;
constant wait_cycles : in integer) is
begin
wait_clock_rising(wait_cycles);
wait until falling_edge(tb_clk_i);
tb_a_i <= std_logic_vector(to_signed(value_a,g_data_bits));
tb_b_i <= std_logic_vector(to_signed(value_b,g_data_bits));
tb_c_i <= value_c;
end procedure assign_input;
begin
-- initial values
tb_sim_end <= '0';
tb_a_i <= (others=>'0');
tb_b_i <= (others=>'0');
tb_stall_i <= '1';
tb_c_i <= '0';
-- hold stall for 100ns
wait_clock_rising(5);
tb_stall_i <= '0';
assign_input(4,4,'0',2);
wait_clock_rising(20);
assign_input(4,4,'1',2);
wait_clock_rising(20);
assign_input(10,10,'1',2);
wait_clock_rising(20);
assign_input(12,12,'0',2);
wait_clock_rising(20);
tb_sim_end <= '1';
wait;
end process;
end tb;
action = "simulation"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
target = "xilinx"
syn_device = "xc6slx45t"
......
action="simulation"
sim_tool="ghdl"
sim_top="tb_gc_delay_gen"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
files="tb_gc_delay_gen.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench for a simple delay line generator. It uses GHDL as a simulator.
The testing process is the following:
- Assigning random input values (with random seed) using the OSVVM methodology.
- Storing these values in a register and an array.
- Via an assertion, comparing the testbench's output with the core's output,
to verify that the output is delayed as it is supposed to (regarding the `g_delay_cycles` generic value.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_delay_gen
echo "Running simulation for $TB"
echo "************ TEST CASE 1 ***************"
echo "Number of delay cycles = 1, data width = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay_cycles=1 -gg_data_width=8
echo "************ TEST CASE 2 ***************"
echo "Number of delay cycles = 2, data width = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay_cycles=2 -gg_data_width=8
echo "************ TEST CASE 3 ***************"
echo "Number of delay cycles = 4, data width = 16"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay_cycles=4 -gg_data_width=16
echo "************ TEST CASE 4 ***************"
echo "Number of inputs = 12, data width = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay_cycles=12 -gg_data_width=32
-------------------------------------------------------------------------------
-- Title : Testbench for Simple delay line generator
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : tb_gc_delay_gen.vhd
-- Author : Konstantinos Blantos
-- Company : CERN BE-CEM-EDL
-- Created : 2021-11-22
-- Platform : FPGA-generic
-- Standard : VHDL 2008
------------------------------------------------------------------------------
-- Description: Testbench for Simple N-bit delay line with programmable delay.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 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
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2021-11-22 1.0 kblantos Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_delay_gen is
generic (
g_seed : natural;
g_delay_cycles : natural := 2;
g_data_width : natural := 8);
end entity;
architecture tb of tb_gc_delay_gen 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_d_i : std_logic_vector(g_data_width-1 downto 0);
signal tb_q_o : std_logic_vector(g_data_width-1 downto 0);
type t_dly_array is array (0 to g_delay_cycles) of std_logic_vector(g_data_width -1 downto 0);
signal s_dly_arr : t_dly_array;
signal stop : boolean;
begin
-- Unit Under test
UUT : entity work.gc_delay_gen
generic map (
g_delay_cycles => g_delay_cycles,
g_data_width => g_data_width)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
d_i => tb_d_i,
q_o => tb_q_o);
-- Clock and reset generation
clk_i_process : 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while (NOW < 1 ms) loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
tb_d_i <= data.randSlv(g_data_width);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions - Self Checking --
--------------------------------------------------------------------------------
-- Fill the array with input data
delay_array : process (tb_clk_i, tb_rst_n_i)
begin
if tb_rst_n_i = '0' then
for_rst : for i in 1 to g_delay_cycles loop
s_dly_arr(i) <= (others => '0');
end loop;
elsif rising_edge(tb_clk_i) then
s_dly_arr(0) <= tb_d_i;
for_clk : for i in 0 to g_delay_cycles-1 loop
s_dly_arr(i+1) <= s_dly_arr(i);
end loop;
end if;
end process delay_array;
--Depending on the g_delay_cycles, we expect the output equal to input
self_check : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) and tb_rst_n_i = '1' then
assert (s_dly_arr(g_delay_cycles) = tb_q_o)
report "Data mismatch" severity failure;
end if;
end process;
end tb;
action="simulation"
sim_tool="ghdl"
target="xilinx"
syn_device="xc6slx45t" #"5agxmb1g4f"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_delay_line"
files="tb_gc_delay_line.vhd"
modules={"local" : ["../../../",
"../../../modules/common",
"../../../modules/genrams"]}
This is a testbench to verify that gc_delay_line core is working properly.
It uses GHDL as a simulator and OSVVM verification methodology. The testing process is the following:
- Assigning random input values (with random seed) using the OSVVM methodology.
- Storing these values in a register and an array.
- An assertion is used in order to compare the output of the testbench and the output of the
core. In this way, the functionality is being tested.
- In `run.sh`, which is the script to run the simulation, the value of the generics can be
changed and run the test with more test cases.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
#In case we need to see waveforms, type --wave=waveform.ghw
#in the end of each command
TB=tb_gc_delay_line
echo "***********************************************************************"
echo "Running simulation for $TB"
echo "***********************************************************************"
echo "Number of delay cycles = 2, data width = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay=2 -gg_width=8
echo ""
echo "Number of delay cycles = 4, data width = 16"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay=4 -gg_width=16
echo ""
echo "Number of inputs = 12, data width = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_delay=12 -gg_width=32
echo ""
-------------------------------------------------------------------------------
-- Title : Testbench for Parametrized delay block
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : tb_gc_delay_line.vhd
-- Company : CERN (BE-CEM-EDL)
-- Author : Konstantinos Blantos
-- Platform : FPGA-generics
-- Standard : VHDL 2008
-------------------------------------------------------------------------------
-- Copyright (c) 2011-2017 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.genram_pkg.all;
--OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_gc_delay_line --
--=============================================================================
entity tb_gc_delay_line is
generic (
g_seed : natural;
g_delay : natural := 2;
g_width : natural := 8);
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_gc_delay_line 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_d_i : std_logic_vector(g_width-1 downto 0);
signal tb_q_o : std_logic_vector(g_width-1 downto 0);
signal tb_ready_o : std_logic;
signal stop : boolean;
signal s_cnt : unsigned(g_delay-1 downto 0) := (others=>'0');
-- array used for self-checking
type t_dly_array is array (0 to g_delay) of std_logic_vector(g_width-1 downto 0);
signal s_dly_arr : t_dly_array;
begin
-- Unit Under Test
UUT : entity work.gc_delay_line
generic map (
g_delay => g_delay,
g_width => g_width)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
d_i => tb_d_i,
q_o => tb_q_o,
ready_o => tb_ready_o);
-- Clock and reset generation
clk_i_process : 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
--Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 1 ms loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
tb_d_i <= data.randSlv(g_width);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
------------------------------------------------------------------------------
-- Assertions - Self Checking --
------------------------------------------------------------------------------
-- Delay should be higher than 1
assert (g_delay > 1)
report "Wrong value for Delay" severity failure;
-- Fill in the array with random input data
delay_array : process(tb_clk_i)
begin
if (tb_rst_n_i = '0') then
for_rst : for i in 0 to g_delay loop
s_dly_arr(i) <= (others=>'0');
end loop;
elsif (rising_edge(tb_clk_i) and tb_ready_o = '1') then
s_dly_arr(0) <= tb_d_i;
for_clk : for i in 0 to g_delay-1 loop
s_dly_arr(i+1) <= s_dly_arr(i);
end loop;
end if;
end process;
-- Self-checking process
self_check : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) and tb_rst_n_i = '1' then
if tb_ready_o = '1' then
if s_cnt >= 0 and s_cnt < g_delay then
s_cnt <= s_cnt + 1;
elsif (s_cnt = g_delay) then
s_cnt <= (others=>'0');
assert (s_dly_arr(g_delay-1)= tb_q_o)
report "Data mismatch" severity error;
end if;
end if;
end if;
end process;
end tb;
action = "simulation"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
target = "xilinx"
syn_device = "xc6slx45t"
......
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=gc_ds182x_readout_tb
echo "Running simulation for $TB"
echo "********************************************************"
echo " TEST CASE "
echo "Clock frequency (kHz) = 40.000, Use internal pps = false"
echo "********************************************************"
ghdl -r --std=08 -frelaxed-rules $TB --stop-time=600ms
action="simulation"
sim_tool="ghdl"
target="xilinx"
syn_device="generic"
sim_top="tb_gc_dual_pi_controller"
ghdl_opt="--std=08 -frelaxed-rules"
files=["tb_gc_dual_pi_controller.vhd"]
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench to verify the gc_dual_pi_controler core. It uses GHDL simulator and OSVVM as verification methodology. All input signals in the testbench are random, with random seed also.
We can have this testbench running either for frequency mode, either for phase mode.
This can be changed, through a generic value in testbench "g_mode"
There is FSM coverage presented in the end of each run, to ensure that all legal states are covered.
Self - Checking testbench, where RTL module's output is being compared with the one
calculated in the testbench with similar logic.
The other values in the rest of the generics are indicative and can be changed in
the run.sh script.
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_gc_dual_pi_controller
echo "Running simulation for $TB"
echo " TEST CASE 1 : Frequency mode "
echo " Error Bits = 12 "
echo " Dacval_bits = 16 "
echo " Output_bias = 32767"
echo " Integrator_fracbits = 16 "
echo " Integrator_overbits = 6 "
echo " Coef_bits = 16 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_mode=1 -gg_error_bits=12 -gg_dacval_bits=16 -gg_output_bias=32767 -gg_integrator_fracbits=16 -gg_integrator_overbits=6 -gg_coef_bits=16
echo "*******************************************************************************"
echo " TEST CASE 2 : Phase mode "
echo " Error Bits = 12 "
echo " Dacval_bits = 16 "
echo " Output_bias = 32767"
echo " Integrator_fracbits = 16 "
echo " Integrator_overbits = 6 "
echo " Coef_bits = 16 "
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_mode=0 -gg_error_bits=12 -gg_dacval_bits=16 -gg_output_bias=32767 -gg_integrator_fracbits=16 -gg_integrator_overbits=6 -gg_coef_bits=16
echo "*******************************************************************************"
action="simulation"
target="generic"
sim_tool="ghdl"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_dyn_extend_pulse"
files="tb_gc_dyn_extend_pulse.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench to verify the functionality of gc_dyn_extend_pulse. The core, generates a pulse of programmable width upon detection of a rising edge in the input. With this test, we check that this pulse will not be higher than the len_i, which is specified by the generic `g_len_width`.
This testbench is running with GHDL and OSVVM verification methodology is used. Randomized input signals with random seed is used in every run. Currently there are three test cases, where the length is 2, 4 and 6 clock cycles.
Some simple coverage is being achieved for these cases:
- when the reset is asserted (at least once)
- when the input and output pulses are both HIGH
- when input pulse is LOW and output pulse is HIGH
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_gc_dyn_extend_pulse
echo "Running simulation for $TB"
echo " TEST CASE 1"
echo "Length of the pulse = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len_width=2
echo "***************************************************************"
echo " TEST CASE 2"
echo "Length of the pulse = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len_width=4 --wave=waveform.ghw
echo "***************************************************************"
echo " TEST CASE 3"
echo "Length of the pulse = 6"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len_width=6
echo "***************************************************************"
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: tb_gc_dyn_extend_pulse
--
-- author : Konstantinos Blantos <Konstantinos.Blantos@cern.ch>
--
-- description: Synchronous pulse extender. Generates a pulse of programmable
-- width upon detection of a rising edge in the input.
--
--------------------------------------------------------------------------------
-- Copyright CERN 209-2018
--------------------------------------------------------------------------------
-- 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.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_gc_dyn_extend_pulse --
--=============================================================================
entity tb_gc_dyn_extend_pulse is
generic (
g_seed : natural;
g_len_width : natural := 1);
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_gc_dyn_extend_pulse 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_pulse_i : std_logic;
signal tb_len_i : std_logic_vector(g_len_width-1 downto 0) := (others=>'0');
signal tb_extended_o : std_logic := '0';
signal stop : boolean;
signal s_cnt : unsigned(g_len_width-1 downto 0) := (others=>'0');
-- Shared variables, used for coverage
shared variable cp_rst_n_i : covPType;
shared variable cp_pulse_detect : covPType;
shared variable cp_ext_pulse_o : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_dyn_extend_pulse
generic map (
g_len_width => g_len_width)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
pulse_i => tb_pulse_i,
len_i => tb_len_i,
extended_o => tb_extended_o);
-- Clock generation
clk_i_process : 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING Slave] with seed = " & to_string(g_seed);
while (NOW < 2 ms) loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
tb_pulse_i <= data.randSlv(1)(1);
tb_len_i <= data.randSlv(g_len_width) when tb_pulse_i = '1' else (others=>'0');
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
-- The extended output pulse should not be asserted for a period more than
-- len_i between two rising edges of input pulse
-- So, extended_o shouldn't be high for a period longer than
-- this when pulse_i is falling_edge
p_cnt : process(tb_clk_i)
begin
if tb_rst_n_i = '0' then
s_cnt <= (others=>'0');
elsif rising_edge(tb_clk_i) then
if (tb_pulse_i = '0' and tb_extended_o = '1') then
s_cnt <= s_cnt + 1;
else
s_cnt <= (others=>'0');
end if;
end if;
end process;
-- Check the width of the output pulse
-- not to be higher then len_i
check_extended_o : process(tb_clk_i)
begin
if (tb_rst_n_i = '1') then
elsif rising_edge(tb_clk_i) then
assert (s_cnt <= unsigned(tb_len_i))
report "Output pulse high for longer period" severity failure;
end if;
end process;
-- Output extended pulse is rising when input pulse is asserted
both_high : process(tb_clk_i)
begin
if (rising_edge(tb_clk_i) and tb_rst_n_i = '1') then
if (tb_pulse_i = '1') then
assert (tb_extended_o = '1')
report "Output pulse not high when input pulse is high" severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_rst_n_i.AddBins("Reset has asserted", ONE_BIN);
cp_pulse_detect.AddBins("output pulse high when input high", ONE_BIN);
cp_ext_pulse_o.AddBins("output pulse high when input is low", ONE_BIN);
wait;
end process;
sample_rst_cov : process
begin
loop
wait on tb_rst_n_i;
wait for C_CLK_PERIOD;
--sample the coverpoints
cp_rst_n_i.ICover(to_integer(tb_rst_n_i = '1'));
end loop;
end process;
sample_pulse_detect : process
begin
loop
wait until rising_edge(tb_clk_i);
cp_pulse_detect.ICover(to_integer((tb_pulse_i = '1')
and tb_extended_o = '1'));
end loop;
end process;
sample_out_pulse : process
begin
loop
wait until rising_edge(tb_clk_i);
if (s_cnt = g_len_width-1) then
cp_ext_pulse_o.ICover(to_integer(tb_extended_o = '1' and tb_pulse_i = '0'));
end if;
end loop;
end process;
cover_report : process
begin
wait until stop;
cp_rst_n_i.Writebin;
cp_pulse_detect.Writebin;
cp_ext_pulse_o.Writebin;
end process;
end tb;
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_dyn_glitch_filt"
files="tb_gc_dyn_glitch_filt.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
Testbench to verify the functionality of the gc_dyn_glitch_filt general core. It receives randomized input signals with random seed. It consist of 3 test cases (can be extented to more) regarding the length of the latency.
Some assertions are being used for better self-checking purposes. First of all, one of them, is checking that the glitch filter length is more than zero. Another assertion, is for the relation between input and output data. So, if input data, dat_i is HIGH, the output dat_o is HIGH after len_i clk cycles. The same goes in case the input data is LOW.
Simple coverage is being covered too, to better check that the testbench covers everything that needs to be checked. These cases are:
- Reset has beend asserted
- Output pulse is HIGH when input is HIGH
- Output pulse is LOW when input is LOW
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_dyn_glitch_filt
echo "Running simulation for $TB"
echo " TEST CASE 1 "
echo "Length of the pulse = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len_width=2
echo "***************************************************************"
echo " TEST CASE 2 "
echo "Length of the pulse = 32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len_width=8
echo "***************************************************************"
echo " TEST CASE 3 "
echo "Length of the pulse = 64"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len_width=16
echo "****************************************************************"
--==============================================================================
-- CERN (BE-CEM-EDL)
-- Testbench for Glitch filter with dynamically selectable length
--==============================================================================
--
-- author: Konstantinos Blantos (Konstantinos.Blantos@cern.ch)
--
-- date of creation: 2021-11-24
--
-- version: 1.0
--
-- description:
-- Testbench for gc_glitch_filt. Glitch filter consisting of a set of
-- chained flip-flops followed by a comparator. The comparator toggles
-- to '1' when all FFs in the chain are '1' and respectively to '0' when
-- all the FFS in the chain are '0'. Latency = len_i + 1.
--
-- references:
-- Based on gc_glitch_filter.vhd
--
--==============================================================================
-- GNU LESSER GENERAL PUBLIC LICENSE
--==============================================================================
-- 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
--==============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_dyn_glitch_filt is
generic (
g_seed : natural;
g_len_width : natural := 4);
end entity;
architecture tb of tb_gc_dyn_glitch_filt 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_len_i : std_logic_vector(g_len_width-1 downto 0) := (others=>'0');
signal tb_dat_i : std_logic := '0';
-- latecy : g_len+1 clk_i cycles
signal tb_dat_o : std_logic;
signal stop : boolean;
signal s_cnt : unsigned(g_len_width-1 downto 0) := (others=>'0');
-- Shared variables, used for coverage
shared variable cp_rst_n_i : covPType;
shared variable cp_high_pulse_detect : covPType;
shared variable cp_low_pulse_detect : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_dyn_glitch_filt
generic map (
g_len_width => g_len_width)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
len_i => tb_len_i,
dat_i => tb_dat_i,
dat_o => tb_dat_o);
-- Clock generation
clk_i_process : process
begin
while not stop 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 4 ms loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
tb_dat_i <= data.randSlv(1)(1);
tb_len_i <= data.randSlv(g_len_width);
wait for 4*C_CLK_PERIOD;
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
-- Check that the number of bits of the glitch filter length is more than zero
len_filter : assert (g_len_width > 0)
report "Length of glitch filter is invalid" severity failure;
-- If dat_i is HIGH, the output is HIGH after len_i clk cycles
-- Same goes for dat_i is LOW
check_output : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
s_cnt <= unsigned(tb_len_i) srl 1;
else
if rising_edge(tb_dat_i) then
if s_cnt = unsigned(tb_len_i) + 1 then
s_cnt <= (others=>'0');
assert (tb_dat_o = '1')
report "Data not HIGH after specified length of clocks"
severity failure;
else
s_cnt <= s_cnt + 1;
end if;
elsif falling_edge(tb_dat_i) then
if s_cnt = unsigned(tb_len_i) then
assert (tb_dat_o = '0')
report "Data not LOW after specified length of clocks"
severity failure;
else
s_cnt <= s_cnt + 1;
end if;
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_rst_n_i.AddBins("Reset has asserted", ONE_BIN);
cp_high_pulse_detect.AddBins("output pulse high when input high", ONE_BIN);
cp_low_pulse_detect.AddBins("output pulse low when input low", ONE_BIN);
wait;
end process;
sample_rst_cov : process
begin
loop
wait on tb_rst_n_i;
wait for C_CLK_PERIOD;
--sample the coverpoints
cp_rst_n_i.ICover(to_integer(tb_rst_n_i = '1'));
end loop;
end process;
sample_high_pulse_detect : process
begin
loop
wait until rising_edge(tb_clk_i);
cp_high_pulse_detect.ICover(to_integer((tb_dat_i = '1')
and tb_dat_o = '1'));
end loop;
end process;
sample_low_pulse_detect : process
begin
loop
wait until rising_edge(tb_clk_i);
cp_low_pulse_detect.ICover(to_integer((tb_dat_i = '0')
and tb_dat_o = '0'));
end loop;
end process;
cover_report : process
begin
wait until stop;
cp_rst_n_i.Writebin;
cp_high_pulse_detect.Writebin;
cp_low_pulse_detect.Writebin;
end process;
end tb;
action="simulation"
sim_tool="ghdl"
target="xilinx"
syn_device="xc6slx45t"
sim_top="tb_gc_edge_detect"
ghdl_opt="--std=08 -frelaxed-rules"
files=["tb_gc_edge_detect.vhd"]
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a generic testbench which checks the width of the ouput pulse, depending on the given generics in the beginning of the simulation. The output pulse is high in the falling or in the rising edge of the input pulse.
The generics of this core are the following:
- g_async_rst : Synchronous or asynchronous reset
- g_pulse_edge : Detect of positive or negative edges
- g_clock_edge : Clock edge sensitivity of edge detection
Regarding on the values of the above generics, there are the following test cases:
1. TRUE, positive, positive
2. TRUE, positive, negative
3. TRUE, negative, negative
4. TRUE, negative, negative
5. FALSE, positive, positive
6. FALSE, positive, negative
7. FALSE, negative, positive
8. FALSE, negative, negative
The testbench is using OSVVM for randomization of the inputs and for basic coverage. Simple assertions are using, to verify that the output is the same as the input, after one clock.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_edge_detect
echo "Running simulation for $TB"
echo " TEST CASE 1 "
echo "ASYNC_RST=TRUE, PULSE_EDGE=positive, CLOCK_EDGE=positive"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=TRUE -gg_PULSE_EDGE=positive -gg_CLOCK_EDGE=positive
echo "*******************************************************************************************************"
echo " TEST CASE 2 "
echo "ASYNC_RST=TRUE, PULSE_EDGE=positive, CLOCK_EDGE=negative"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=TRUE -gg_PULSE_EDGE=positive -gg_CLOCK_EDGE=negative
echo "*******************************************************************************************************"
echo " TEST CASE 3 "
echo "ASYNC_RST=TRUE, PULSE_EDGE=negative, CLOCK_EDGE=positive"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=TRUE -gg_PULSE_EDGE=negative -gg_CLOCK_EDGE=positive
echo "*******************************************************************************************************"
echo " TEST CASE 4 "
echo "ASYNC_RST=TRUE, PULSE_EDGE=negative, CLOCK_EDGE=negative"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=TRUE -gg_PULSE_EDGE=negative -gg_CLOCK_EDGE=negative
echo "*******************************************************************************************************"
echo " TEST CASE 5 "
echo "ASYNC_RST=FALSE, PULSE_EDGE=positive, CLOCK_EDGE=positive"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=FALSE -gg_PULSE_EDGE=positive -gg_CLOCK_EDGE=positive
echo "*******************************************************************************************************"
echo " TEST CASE 6 "
echo "ASYNC_RST=FALSE, PULSE_EDGE=positive, CLOCK_EDGE=negative"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=FALSE -gg_PULSE_EDGE=positive -gg_CLOCK_EDGE=negative
echo "*******************************************************************************************************"
echo " TEST CASE 7 "
echo "ASYNC_RST=FALSE, PULSE_EDGE=negative, CLOCK_EDGE=positive"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=FALSE -gg_PULSE_EDGE=negative -gg_CLOCK_EDGE=positive
echo "*******************************************************************************************************"
echo " TEST CASE 8 "
echo "ASYNC_RST=FALSE, PULSE_EDGE=negative, CLOCK_EDGE=negative"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_ASYNC_RST=FALSE -gg_PULSE_EDGE=negative -gg_CLOCK_EDGE=negative
echo "*******************************************************************************************************"
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- author : Konstantinos Blantos <Konstantinos.Blantos@cern.ch>
--
-- unit name: tb_gc_edge_detect
--
-- description: testbench for simple edge detector
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-2020
--------------------------------------------------------------------------------
-- 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;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_edge_detect is
generic (
g_seed : natural;
g_ASYNC_RST : boolean := FALSE;
g_PULSE_EDGE : string := "positive";
g_CLOCK_EDGE : string := "positive");
end entity;
architecture tb of tb_gc_edge_detect is
-- Constants
constant C_CLK_PERIOD : time := 10 ns;
-- Signals
signal tb_clk_i : std_logic;
signal tb_rst_i : std_logic;
signal tb_d_i : std_logic := '0';
signal tb_pulse_o : std_logic;
signal stop : boolean;
-- Shared variables, used for coverage
shared variable cp_rst_i : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => g_ASYNC_RST,
g_PULSE_EDGE => g_PULSE_EDGE,
g_CLOCK_EDGE => g_CLOCK_EDGE)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_i,
data_i => tb_d_i,
pulse_o => tb_pulse_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_i <= '0', '1' after 4*C_CLK_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 4 ms loop
wait until (rising_edge(tb_clk_i) and tb_rst_i = '1');
tb_d_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process;
--sets up coverpoint bins
init_coverage : process
begin
cp_rst_i.AddBins("reset has asserted", ONE_BIN);
wait;
end process init_coverage;
--Assertion to check that the width of the output pulse
--is asserted for only one clock cycle
one_clk_width : process
begin
if rising_edge(tb_clk_i) then
if tb_pulse_o = '1' then
wait for C_CLK_PERIOD;
assert (tb_pulse_o = '0')
report "output pulse remains high for more than one clock"
severity failure;
end if;
end if;
wait;
end process;
--Assertion to check that output is the same as input
--after one clock cycle
check_output : process
begin
if rising_edge(tb_clk_i) then
if tb_d_i /= tb_pulse_o then
wait for C_CLK_PERIOD;
assert (tb_d_i = tb_pulse_o)
report "Input and Output signals are different"
severity failure;
else
wait for C_CLK_PERIOD;
assert (tb_d_i /= tb_pulse_o)
report "Input and Output signals still the same"
severity failure;
end if;
end if;
wait;
end process check_output;
sample : process
begin
loop
wait on tb_rst_i;
wait for C_CLK_PERIOD;
--sample the coverpoints
cp_rst_i.ICover(to_integer(tb_rst_i = '1'));
end loop;
end process sample;
cover_report: process
begin
wait until stop;
cp_rst_i.writebin;
end process;
end tb;
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_extend_pulse"
files="tb_gc_extend_pulse.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench to verify the gc_extend_pulse core. It uses GHDL simulator and OSVVM as verification methodology. All input signals in the testbench are random, with random seed also.
There are 4 test cases, depending on the width of the output pulse (2, 8, 12, 24). This can be extended more and have more test cases, but for simulation reasons it is preferred to give to the `g_width` generic, a lower value.
There are the following assertions, to give to the testbench a more self-checking approach:
- Check that the duration of the output pulse (in clock cycles), is not bigger that g_width
- Check that the output extended pulse is rising when input pulse is asserted
Simple coverage is being covered:
- Reset has been asserted
- Output pulse width is HIGH when input is HIGH
- Output pulse de-asserted when reached the maximum width
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_extend_pulse
echo "Running simulation for $TB"
echo "TEST CASE 1 "
echo "Length of the pulse = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_width=2
echo "***********************************************************"
echo "TEST CASE 2 "
echo "Length of the pulse = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_width=8
echo "***********************************************************"
echo "TEST CASE 3 "
echo "Length of the pulse = 12"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_width=12
echo "***********************************************************"
echo "TEST CASE 4 "
echo "Length of the pulse = 16"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_width=16
echo "***********************************************************"
-------------------------------------------------------------------------------
-- Title : Testbench for Pulse width extender
-- Project : General Cores library
-------------------------------------------------------------------------------
-- File : tb_gc_extend_pulse.vhd
-- Author : Konstantinos Blantos
-- Company : CERN
-- Created : 2021-11-25
-- Platform : FPGA-generic
-- Standard : VHDL 2008
-------------------------------------------------------------------------------
-- Description:
-- Testbench for Synchronous pulse extender. Generates a pulse of programmable
-- width upon detection of a rising edge in the input. OSVVM used for coverage
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009-2011 CERN
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); 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-0.51.
-- 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.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_extend_pulse is
generic (
g_seed : natural;
g_width : natural := 1000);
end entity;
architecture tb of tb_gc_extend_pulse 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_pulse_i : std_logic;
signal tb_extended_o : std_logic;
signal stop : boolean;
signal s_cnt : unsigned(f_log2_ceil(g_width)-1 downto 0);
-- Shared variables, used for coverage
shared variable cp_rst_n_i : covPType;
shared variable cp_pulse_detect : covPType;
shared variable cp_ext_pulse_o : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_extend_pulse
generic map (
g_width => g_width)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
pulse_i => tb_pulse_i,
extended_o => tb_extended_o);
-- Clock generation
clk_i_process : process
begin
while not stop 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 2.5 ms loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
tb_pulse_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
-- Checks that the length of the output pulse is not bigger than
-- the specified length
check_extended_o : process(tb_clk_i)
begin
if tb_rst_n_i = '0' then
s_cnt <= (others=>'0');
elsif (rising_edge(tb_clk_i)) then
if (tb_pulse_i = '0' and tb_extended_o = '1') then
s_cnt <= s_cnt + 1;
assert (s_cnt <= g_width)
report "Output pulse high for longer period" severity failure;
if s_cnt > g_width then
s_cnt <= (others=>'0');
end if;
else
s_cnt <= (others=>'0');
end if;
end if;
end process;
-- Output extended pulse is rising when input pulse is asserted
both_high : process(tb_clk_i)
begin
if (rising_edge(tb_clk_i) and tb_rst_n_i = '1') then
if (tb_pulse_i = '1') then
assert (tb_extended_o = '1')
report "Output pulse not high when input pulse is high" severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_rst_n_i.AddBins("Reset has asserted", ONE_BIN);
cp_pulse_detect.AddBins("output pulse high when input high", ONE_BIN);
cp_ext_pulse_o.AddBins("output pulse de-asserted when max width",ONE_BIN);
wait;
end process;
-- Sample the coverpoints
sample_rst_cov : process
begin
loop
wait on tb_rst_n_i;
cp_rst_n_i.ICover(to_integer(tb_rst_n_i = '1'));
end loop;
end process;
sample_pulse_detect : process
begin
loop
wait until rising_edge(tb_clk_i);
cp_pulse_detect.ICover(to_integer((tb_pulse_i = '1')
and tb_extended_o = '1'));
end loop;
end process;
sample_out_pulse : process
begin
loop
wait until rising_edge(tb_clk_i);
if s_cnt = g_width-1 then
cp_ext_pulse_o.ICover(to_integer(tb_extended_o = '0'));
end if;
end loop;
end process;
-- Coverage report
cover_report : process
begin
wait until stop;
cp_rst_n_i.Writebin;
cp_pulse_detect.Writebin;
cp_ext_pulse_o.Writebin;
end process;
end tb;
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_frequency_meter"
files="tb_gc_frequency_meter.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench to verify the gc_frequency_meter core. It uses GHDL simulator and OSVVM as verification methodology. All input signals in the testbench are random, with random seed also.
The generics of the core are:
- g_with_internal_timebase : Specifies from where the period is defined
- g_clk_sys_freq : Frequency of system clock
- g_sync_out : If true, the output freq_o, belongs to the clk_sys clock domain
- g_counter_bits : Bit length of the counter
And the test cases that are created, depending on the values of these generics are:
- Two bigger category, if g_with_internal_timebase is either true or false, where there are the following:
- Different values of system clock frequency (up to 10000Hz) and g_sync_out true or false
There are the following assertions, to give to the testbench a more self-checking approach:
- Check for data mismatch between the testbench's output and RTL output for both choices of g_sync_out
Note: It is better to give lower values to CLK_SYS_FREQ in order for the simulation to not take loong time to finish
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_frequency_meter
echo "Running simulation for $TB"
echo "======================================"
echo "*When g_WITH_INTERNAL_TIMEBASE = TRUE*"
echo "======================================"
echo "clk_sys_freq = 50, sync_out = FALSE, counter_bits=32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=TRUE -gg_CLK_SYS_FREQ=50 -gg_SYNC_OUT=FALSE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 500, sync_out = TRUE, counter_bits=32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=TRUE -gg_CLK_SYS_FREQ=500 -gg_SYNC_OUT=TRUE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 1000, sync_out = FALSE, counter_bits=32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=TRUE -gg_CLK_SYS_FREQ=1000 -gg_SYNC_OUT=FALSE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 5000, sync_out = TRUE, counter_bits=64"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=TRUE -gg_CLK_SYS_FREQ=5000 -gg_SYNC_OUT=TRUE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 10000, sync_out = FALSE, counter_bits=8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=TRUE -gg_CLK_SYS_FREQ=10000 -gg_SYNC_OUT=FALSE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "======================================="
echo "*When g_WITH_INTERNAL_TIMEBASE = FALSE*"
echo "======================================="
echo "clk_sys_freq = 50, sync_out = FALSE, counter_bits=32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=FALSE -gg_CLK_SYS_FREQ=50 -gg_SYNC_OUT=FALSE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 500, sync_out = TRUE, counter_bits=32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=FALSE -gg_CLK_SYS_FREQ=500 -gg_SYNC_OUT=TRUE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 1000, sync_out = FALSE, counter_bits=32"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=FALSE -gg_CLK_SYS_FREQ=1000 -gg_SYNC_OUT=FALSE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 5000, sync_out = TRUE, counter_bits=64"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=FALSE -gg_CLK_SYS_FREQ=5000 -gg_SYNC_OUT=TRUE -gg_COUNTER_BITS=32
echo "******************************************************************************"
echo "clk_sys_freq = 10000, sync_out = FALSE, counter_bits=8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_WITH_INTERNAL_TIMEBASE=FALSE -gg_CLK_SYS_FREQ=10000 -gg_SYNC_OUT=FALSE -gg_COUNTER_BITS=32
echo "******************************************************************************"
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: tb_gc_frequency_meter
--
-- description: Testbench for Frequency meter with internal or external timebase
--
--------------------------------------------------------------------------------
-- Copyright CERN 2012-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.
--------------------------------------------------------------------------------
-- Principle of operation:
--
-- This block counts the number of pulses on CLK_IN_I during a period.
-- At the end of the period, the value is saved and the counter reset.
-- The saved value is available on FREQ_O, which is synchronized with
-- CLK_SYS_I if G_SYNC_OUT is True.
-- The width of the counter is defined by G_COUNTER_BITS.
--
-- - If g_WITH_INTERNAL_TIMEBASE is True:
-- The period is defined by an internal counter that generates a pulse
-- every G_CLK_SYS_FREQ CLK_SYS_I ticks.
--
-- - If g_WITH_INTERNAL_TIMEBASE is False:
-- The period is defined by PPS_P1_I
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_frequency_meter is
generic (
g_seed : natural;
g_WITH_INTERNAL_TIMEBASE : boolean := FALSE;
g_CLK_SYS_FREQ : integer := 10;
g_SYNC_OUT : boolean := FALSE;
g_COUNTER_BITS : integer := 8);
end entity;
architecture tb of tb_gc_frequency_meter is
-- Constants
constant C_CLK_SYS_PERIOD : time := 8 ns;
constant C_CLK_IN_PERIOD : time := 10 ns;
-- Signals
signal tb_clk_sys_i : std_logic;
signal tb_clk_in_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_pps_p1_i : std_logic;
signal tb_freq_o : std_logic_vector(g_COUNTER_BITS-1 downto 0);
signal tb_freq_valid_o : std_logic;
signal stop : boolean := FALSE;
signal s_cnt_gate : unsigned(g_COUNTER_BITS-1 downto 0) := (others=>'0');
signal s_gate_pulse : std_logic := '0';
signal s_cnt_freq : unsigned(g_COUNTER_BITS-1 downto 0) := (others=>'0');
signal s_data_o : std_logic_vector(g_COUNTER_BITS-1 downto 0) := (others=>'0');
signal s_freq : std_logic_vector(g_COUNTER_BITS-1 downto 0) := (others=>'0');
signal s_gate_pulse_synced : std_logic := '0';
begin
-- Unit Under Test
UUT : entity work.gc_frequency_meter
generic map (
g_WITH_INTERNAL_TIMEBASE => g_WITH_INTERNAL_TIMEBASE,
g_CLK_SYS_FREQ => g_CLK_SYS_FREQ,
g_SYNC_OUT => g_SYNC_OUT,
g_COUNTER_BITS => g_COUNTER_BITS)
port map (
clk_sys_i => tb_clk_sys_i,
clk_in_i => tb_clk_in_i,
rst_n_i => tb_rst_n_i,
pps_p1_i => tb_pps_p1_i,
freq_o => tb_freq_o,
freq_valid_o => tb_freq_valid_o);
-- Clocks 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;
clk_in_proc : process
begin
while not stop loop
tb_clk_in_i <= '1';
wait for C_CLK_IN_PERIOD/2;
tb_clk_in_i <= '0';
wait for C_CLK_IN_PERIOD/2;
end loop;
wait;
end process clk_in_proc;
-- Reset generation
tb_rst_n_i <= '0', '1' after 4*C_CLK_SYS_PERIOD;
-- Stimulus if g_with_internal_timebase = TRUE
stim_with_internal_timebase : if (g_with_internal_timebase = TRUE) generate
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 2 ms loop
wait until rising_edge(tb_clk_sys_i);
tb_pps_p1_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process;
end generate;
-- Stimulus if g_with_internal_timebase = TRUE
stim_without_internal_timebase : if (g_with_internal_timebase = FALSE) generate
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 2 ms loop
wait until (rising_edge(tb_clk_sys_i) and tb_freq_valid_o = '1');
tb_pps_p1_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process;
end generate;
--------------------------------------------------------------------------------
-- Self-Checking and Assertions
--------------------------------------------------------------------------------
-- Reproduce the behavior of the internal counter
with_internal_timebase : if (g_WITH_INTERNAL_TIMEBASE = TRUE) generate
internal_counter : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if s_cnt_gate = g_CLK_SYS_FREQ-1 then
s_cnt_gate <= (others=>'0');
s_gate_pulse <= '1';
else
s_cnt_gate <= s_cnt_gate + 1;
s_gate_pulse <= '0';
end if;
end if;
end process;
-- generate s_gate_pulse_synced
gate_pulse_sync : process
begin
while not stop loop
wait until falling_edge(s_gate_pulse);
wait until rising_edge(tb_clk_in_i);
wait for C_CLK_IN_PERIOD;
s_gate_pulse_synced <= '1';
wait for C_CLK_IN_PERIOD;
s_gate_pulse_synced <= '0';
end loop;
end process;
end generate with_internal_timebase;
-- Reproduce the behavior when no internal timebase activated
no_internal_timebase : if (g_WITH_INTERNAL_TIMEBASE = FALSE) generate
no_internal_counter : process
begin
while not stop loop
wait until falling_edge(tb_freq_valid_o);
wait until rising_edge(tb_clk_in_i);
wait for C_CLK_IN_PERIOD;
s_gate_pulse_synced <= '1';
wait for C_CLK_IN_PERIOD;
s_gate_pulse_synced <= '0';
end loop;
wait;
end process;
end generate;
-- Reproduce the output and store it in a register
output_data : process(tb_clk_in_i)
begin
if rising_edge(tb_clk_in_i) then
if falling_edge(s_gate_pulse_synced) then
s_data_o <= std_logic_vector(s_cnt_freq);
s_cnt_freq <= (others=>'0');
else
s_cnt_freq <= s_cnt_freq + 1;
end if;
end if;
end process;
sync_out : if (g_SYNC_OUT = FALSE) generate
check_unsync_out_data : process
begin
while not stop loop
wait until tb_freq_valid_o = '1';
wait until rising_edge(tb_clk_in_i);
assert (s_data_o = tb_freq_o)
report "Data mismatch" severity failure;
end loop;
end process;
end generate;
-- output synced with clk_sys_i. Put in s_freq register the value
-- that will be presented in the output and compare it with s_data_o
no_sync_out : if (g_SYNC_OUT = TRUE) generate
check_sync_out_data : process
begin
while not stop loop
wait until falling_edge(s_gate_pulse_synced);
s_freq <= std_logic_vector(s_cnt_freq);
wait until rising_edge(tb_clk_sys_i);
assert (s_data_o = s_freq)
report "Data mismatch" severity failure;
end loop;
end process;
end generate;
end tb;
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_fsm_watchdog"
files="tb_gc_fsm_watchdog.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench to verify the gc_fsm_watchdog core. It uses GHDL simulator and OSVVM as verification methodology. All input signals in the testbench are random, with random seed also.
There are 4 test cases, depending on the value of the watchdog timer (1, 2, 4, 8). This can be extended more and have more test cases, but for simulation reasons it is preferred to give to this generic, a lower value. In case of an increase in this value, please increase also the simulation time (ex. NOW)
There is also one assertion, to give to the testbench a more self-checking approach:
- Check that output signal (fsm_rst_o) is HIGH when the internal counter reaches the maximum value of the watchdog timer
Simple coverage is being covered:
- Reset has been asserted
- Output fsm reset asserted
#!/bin/bash -e
#This is a simple script to run simulations
#in GHDL
TB=tb_gc_fsm_watchdog
echo "Running simulation for $TB"
echo " TEST CASE 1 "
echo "Value of watchdog timer = 1"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_wdt_max=1
echo "*************************************************************"
echo " TEST CASE 2 "
echo "Value of watchdog timer = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_wdt_max=2
echo "*************************************************************"
echo " TEST CASE 3 "
echo "Value of watchdog timer = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_wdt_max=4
echo "*************************************************************"
echo " TEST CASE 4 "
echo "Value of watchdog timer = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_wdt_max=8
echo "*************************************************************"
--==============================================================================
-- CERN (BE-CEM-EDL)
-- Testbench for Finite State Machine Watchdog Timer
--==============================================================================
--
-- author: Konstantinos Blantos
--
-- date of creation: 2021-11-225
--
-- version: 1.0
--
-- description:
--
-- references: from the file gc_fsm_watchdog
--
--==============================================================================
-- GNU LESSER GENERAL PUBLIC LICENSE
--==============================================================================
-- 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
--==============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_fsm_watchdog is
generic (
g_seed : natural;
g_wdt_max : positive := 65535);
end entity;
architecture tb of tb_gc_fsm_watchdog 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_wdt_rst_i : std_logic := '0';
signal tb_fsm_rst_o : std_logic;
signal stop : boolean;
signal s_wdt_cnt : unsigned(f_log2_ceil(g_wdt_max)-1 downto 0) := (others=>'0');
-- Shared variables, used for coverage
shared variable cp_rst_n_i : covPType;
shared variable cp_fsm_rst_o : covPType;
begin
--Unit Under Test
UUT : entity work.gc_fsm_watchdog
generic map(
g_wdt_max => g_wdt_max)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
wdt_rst_i => tb_wdt_rst_i,
fsm_rst_o => tb_fsm_rst_o);
-- Clock generation
clk_i_process : process
begin
while not stop 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING Slave] with seed = " & to_string(g_seed);
while NOW < 4 ms loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
tb_wdt_rst_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
-- Check that the output becomes one when the counter reaches the higher value
check_output : process
begin
wait until rising_edge(tb_clk_i);
if (tb_rst_n_i = '0' or tb_wdt_rst_i = '1') then
s_wdt_cnt <= (others=>'0');
else
s_wdt_cnt <= s_wdt_cnt + 1;
if (s_wdt_cnt = g_wdt_max-1) then
wait for C_CLK_PERIOD;
assert (tb_fsm_rst_o = '1')
report "fsm reset is not HIGH" severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_rst_n_i.AddBins("Reset has asserted", ONE_BIN);
cp_fsm_rst_o.AddBins("Output fsm reset asserted",ONE_BIN);
wait;
end process;
-- Sample the coverpoints
sample_rst_cov : process
begin
loop
wait on tb_rst_n_i;
cp_rst_n_i.ICover(to_integer(tb_rst_n_i = '1'));
end loop;
end process;
sample_out_pulse : process
begin
loop
wait until rising_edge(tb_clk_i);
if s_wdt_cnt = g_wdt_max-1 then
cp_fsm_rst_o.ICover(to_integer(tb_fsm_rst_o = '1'));
end if;
end loop;
end process;
-- Coverage report
cover_report : process
begin
wait until stop;
cp_rst_n_i.Writebin;
cp_fsm_rst_o.Writebin;
end process;
end tb;
action="simulation"
target="generic"
sim_tool="ghdl"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_glitch_filt"
files="tb_gc_glitch_filt.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbench to verify the functionality of gc_glitch_filt. The core can operate differently, regarding the `g_len` generic:
- when g_len = 0 => Output is the same as the input AFTER one clock.
- when g_len > 0 => output becomes '1' when all the FF's are '1' and ONLY when all FF's are '0' it becomes '0' again.
This test is running with GHDL and OSVVM is used. There are 4 test cases so far with different length each time. Randomized inputs are producing with random seed.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_glitch_filt
echo "Running simulation for $TB"
echo "TEST CASE 1 "
echo "Length of the glitch filter = 1"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len=1
echo "*********************************************************"
echo "TEST CASE 2 "
echo "Length of the glitch filter = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len=2
echo "*********************************************************"
echo "TEST CASE 3 "
echo "Length of the glitch filter = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len=8
echo "*********************************************************"
echo "TEST CASE 4 "
echo "Length of the glitch filter = 12"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_len=12
echo "*********************************************************"
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: tb_gc_glitch_filt
--
-- author : Konstantinos Blantos
--
-- description: Testbench for: Glitch filter with selectable length, consisting
-- of a set of chained flip-flops followed by a comparator. The comparator
-- toggles to '1' when all FFs in the chain are '1' and respectively to '0'
-- when all the FFS in the chain are '0'.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2013-2018
--------------------------------------------------------------------------------
-- 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.gencores_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_gc_glitch_filt --
--=============================================================================
entity tb_gc_glitch_filt is
generic (
g_seed : natural;
g_len : natural := 0);
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_gc_glitch_filt 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_dat_i : std_logic := '0';
signal tb_dat_o : std_logic;
signal stop : boolean := FALSE;
signal s_glitch_filt : std_logic_vector(g_len downto 0) := (others=>'0');
-- Shared variables, used for coverage
shared variable cp_rst_n_i : covPType;
shared variable cp_dat_o_high : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_glitch_filt
generic map (
g_len => g_len)
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
dat_i => tb_dat_i,
dat_o => tb_dat_o);
-- Clock generation
clk_i_process : 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;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING Slave] with seed = " & to_string(g_seed);
while NOW < 2 ms loop
wait until (rising_edge(tb_clk_i) and tb_rst_n_i = '1');
tb_dat_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process;
--------------------------------------------------------------------------------
-- Assertions - Self Checking --
--------------------------------------------------------------------------------
-- Output should be like input after one clock delay
-- when length is zero
g_len_zero : if (g_len = 0) generate
process(tb_clk_i)
begin
if (rising_edge(tb_clk_i) and tb_rst_n_i = '1') then
if falling_edge(tb_dat_i) then
assert (tb_dat_i = tb_dat_o)
report "Data mismatch" severity failure;
end if;
end if;
end process;
end generate;
-- Generate glitch filter FF's when length of filter is > 0
g_len_non_zero : if (g_len > 0) generate
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
s_glitch_filt <= (others=>'0');
else
s_glitch_filt(0) <= tb_dat_i;
s_glitch_filt(g_len downto 1) <= s_glitch_filt(g_len-1 downto 0);
end if;
end if;
end process;
end generate;
-- Output data asserted when all FF's are '1' and de-asserted when all FF's
-- are zero
self_check : process(tb_clk_i)
begin
if (rising_edge(tb_clk_i) and tb_rst_n_i = '1') then
if (unsigned(s_glitch_filt) = (s_glitch_filt'range => '1')) then
assert (tb_dat_o = '1')
report "Output not HIGH when FF's are all HIGH" severity failure;
elsif (unsigned(s_glitch_filt) = (s_glitch_filt'range => '0')) then
assert (tb_dat_o = '0')
report "Output not LOW when FF's are all LOW" severity failure;
end if;
end if;
end process;
-- When output data is HIGH, we want the glitch filter to be anything but 0
check_output : process(tb_clk_i)
begin
if (rising_edge(tb_clk_i) and tb_rst_n_i = '1') then
if tb_dat_o = '1' then
assert (unsigned(s_glitch_filt) /= (s_glitch_filt'range => '0'))
report "FF's are all LOW when output is HIGH" severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_rst_n_i.AddBins("Reset has asserted", ONE_BIN);
cp_dat_o_high.AddBins("output pulse HIGH when FF's HIGH", ONE_BIN);
wait;
end process;
sample_rst_cov : process
begin
loop
wait on tb_rst_n_i;
wait for C_CLK_PERIOD;
--sample the coverpoints
cp_rst_n_i.ICover(to_integer(tb_rst_n_i = '1'));
end loop;
end process;
sample_dat_o_high : process
begin
loop
wait until rising_edge(tb_clk_i);
cp_dat_o_high.ICover(to_integer((tb_dat_o = '1')
and (unsigned(s_glitch_filt) = (s_glitch_filt'range => '1'))));
end loop;
end process;
cover_report : process
begin
wait until stop;
cp_rst_n_i.Writebin;
cp_dat_o_high.Writebin;
end process;
end tb;
action="simulation"
sim_tool="ghdl"
target="xilinx"
syn_device="xc6slx45t"
sim_top="tb_gc_i2c_slave"
ghdl_opt="--std=08 -frelaxed-rules"
files=["tb_gc_i2c_slave.vhd"]
modules={"local" : ["../../../",
"../../../modules/common"]}
This is a testbech to test the gc_i2c_slave general core. The specification that the core is based on
is: https://www.csd.uoc.gr/~hy428/reading/i2c_spec.pdf
The testing process is the following:
- Assigning a standard i2c address and scl, sda input signals in order to verify the functionality
of the core, as it is described in the specification.
- FSM coverage can be shown in the end of the simulation, using the OSVVM methodology and GHDL as simulator
(due to that we are giving standard input values through procedures and not random values, the coverage
results are expected to be the same in every run).
- Assertions are used to verify the write and read process.
#!/bin/bash -e
#This is a simple script to run simulations in GHDL
TB=tb_gc_i2c_slave
echo "Running simulation for $TB"
echo "******************************** TEST CASE 1 **************************************"
echo "Length of glitch filter = 0, automatically ACK reception upon address match = FALSE"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$(($RANDOM%(2**31))) -gg_gf_len=0 -gg_auto_addr_ack=false
echo "******************************** TEST CASE 2 **************************************"
echo "Length of glitch filter = 1, automatically ACK reception upon address match = TRUE"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$(($RANDOM%(2**31))) -gg_gf_len=1 -gg_auto_addr_ack=true
This diff is collapsed.
action = "simulation"
sim_tool = "ghdl"
ghdl_opt = "--std=08 -frelaxed-rules"
target = "xilinx"
syn_device = "xc6slx45t"
......
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules"
sim_top="tb_gc_multichannel_frequency_meter"
files="tb_gc_multichannel_frequency_meter.vhd"
modules={"local" : ["../../../",
"../../../modules/common"]}
This diff is collapsed.
This diff is collapsed.
action="simulation"
sim_tool="ghdl"
target="xilinx"
syn_device="xc6slx45t"
sim_top="tb_gc_negedge"
ghdl_opt="--std=08 -frelaxed-rules"
files=["tb_gc_negedge.vhd"]
modules={"local" : ["../../../",
"../../../modules/common"]}
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.
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.
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.
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