Skip to content

Instantly share code, notes, and snippets.

@tmeissner
Created August 14, 2014 15:43
Show Gist options
  • Save tmeissner/1ca16372e247098d9462 to your computer and use it in GitHub Desktop.
Save tmeissner/1ca16372e247098d9462 to your computer and use it in GitHub Desktop.
Simple example of functional coverage using CoveragePkg of OSVVM
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.env.all;
library OSVVM;
use OSVVM.RandomPkg.all;
use OSVVM.CoveragePkg.all;
entity OSVVM_tb is
end entity OSVVM_tb;
architecture sim of OSVVM_tb is
constant C_ADDER_WIDTH : positive := 16;
constant C_CLK_PERIOD : time := 20 ns;
constant C_MAX_BINS : natural := 64;
shared variable sv_coverage : CovPType;
signal s_adder1_in : unsigned(C_ADDER_WIDTH - 1 downto 0);
signal s_adder2_in : unsigned(C_ADDER_WIDTH - 1 downto 0);
signal s_adder0_out : unsigned(C_ADDER_WIDTH downto 0) := (others => '0');
signal s_adder1_out : unsigned(C_ADDER_WIDTH downto 0) := (others => '0');
signal s_clk : std_logic := '0';
begin
s_clk <= not(s_clk) after C_CLK_PERIOD / 2;
-- behaviour model of adder
Adder0P : process is
begin
wait until rising_edge(s_clk);
s_adder0_out <= ('0' & s_adder1_in) + ('0' & s_adder2_in);
end process Adder0P;
-- "rtl" model of adder
Adder1P : process is
variable v_carry : std_logic;
begin
wait until rising_edge(s_clk);
v_carry := '0';
for index in 0 to C_ADDER_WIDTH - 1 loop
if(index = 0) then
s_adder1_out(index) <= s_adder1_in(index) xor s_adder2_in(index);
else
s_adder1_out(index) <= s_adder1_in(index) xor s_adder2_in(index) xor v_carry;
end if;
v_carry := (s_adder1_in(index) and s_adder2_in(index)) or (s_adder1_in(index) and v_carry) or (s_adder2_in(index) and v_carry);
end loop;
s_adder1_out(C_ADDER_WIDTH) <= v_carry;
end process Adder1P;
-- stimulus & coverage of adder inputs
StimCoverageP : process is
variable v_adder_in : integer_vector(0 to 1);
begin
s_adder1_in <= (others => '0');
s_adder2_in <= (others => '0');
-- cross bins for all possible combinations (very slow on large vector widths):
--sv_coverage.AddCross(GenBin(0, 2 ** C_ADDER_WIDTH - 1), GenBin(0, 2 ** C_ADDER_WIDTH - 1));
-- cross bins for maximum of 64 slices with same width:
sv_coverage.AddCross(GenBin(0, 2 ** C_ADDER_WIDTH - 1, C_MAX_BINS), GenBin(0, 2 ** C_ADDER_WIDTH - 1, C_MAX_BINS));
-- cross bins for corner cases:
sv_coverage.AddCross(GenBin(0), GenBin(2 ** C_ADDER_WIDTH - 1));
sv_coverage.AddCross(GenBin(2 ** C_ADDER_WIDTH - 1), GenBin(0));
wait for 1 ns;
-- loop until reach coverage goal
while not sv_coverage.IsCovered loop
wait until rising_edge(s_clk);
v_adder_in := sv_coverage.RandCovPoint;
s_adder1_in <= to_unsigned(v_adder_in(0), C_ADDER_WIDTH);
s_adder2_in <= to_unsigned(v_adder_in(1), C_ADDER_WIDTH);
sv_coverage.ICover(v_adder_in);
end loop;
wait for 2 * C_CLK_PERIOD;
report("CovBin Coverage details");
sv_coverage.WriteBin;
stop;
end process StimCoverageP;
-- check if outputs of both adders are equal
CheckerP : process is
begin
wait until rising_edge(s_clk);
assert s_adder0_out = s_adder1_out
report "FAILURE: s_adder0_out (0x" & to_hstring(s_adder0_out) & ") & s_adder1_out (0x" & to_hstring(s_adder1_out) & ") are not equal!"
severity failure;
end process CheckerP;
end architecture sim;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment