Reply To: Problems with OSVVM Functional Coverage
Why OSVVM™? › Forums › OSVVM › Problems with OSVVM Functional Coverage › Reply To: Problems with OSVVM Functional Coverage
April 15, 2025 at 15:45
#2674

Member
Hi ALex,
I added the two suggestions I made previously to the code. Choose one of them.
I also changed the WaitForClock(clk, 2) to WaitForClock(InterruptRec, 2).
Usually I do not put clock in TestCtrl. The reason being is if you have lots of
different clocks in your system, it is easy to use the wrong one.
rx_process : process is
variable cnt : integer := 0; -- this value is applied at time 0 ns
variable rd_data : std_logic_vector(31 downto 0) := (others => '0');
begin
rx_cnt_s <= 0;
RxCov <= NewID("RxCov") ; -- Get a Coverage ID
wait for 0 ns ;
-- This puts all counts in a single bin with range 1 to 20
osvvm.CoveragePkg.AddBins(RxCov, "count", GenBin(1,20,1) ) ;
-- This puts all counts in a separate bins range 1 to 1, 2 to 2, ...
osvvm.CoveragePkg.AddBins(RxCov, "count", GenBin(1,20) ) ;
loop
WaitForClock(InterruptRec, 1) ;
report "Interrupt Handler Started" ;
Read(InterruptRec, X"A80", rd_data);
if (rd_data(10) = '1') then
Read(InterruptRec, x"920", rd_data);
if (rd_data(30 downto 26) = rd_data(20 downto 16)) then
report "RX FIFO EMPTY";
else
-- The following is a problem if you do not have clk here - I generally recommend against clock here
-- osvvm.TbUtilPkg.WaitForClock(clk, 2);
-- Instead let the VC do the waiting
WaitForClock(InterruptRec, 2); -- wait for VC number of clocks
-- Note the previous waits are not needed by OSVVM.
cnt := rx_cnt_s;
cnt := cnt + 1;
-- Either Check cnt in ICover because rx_cnt_s does not update until a delta cycle later
osvvm.CoveragePkg.ICover(RxCov, cnt) ; -- Collect functional coverage
log("cnt value: " & to_string(cnt)) ; -- log values of cnt to correlate with functional coverage
rx_cnt_s <= cnt;
-- Or add a delta cycle by doing wait for 0 ns here:
rx_cnt_s <= cnt;
wait for 0 ns ;
osvvm.CoveragePkg.ICover(RxCov, rx_cnt_s ) ; -- Collect functional coverage
log("cnt value: " & to_string(rx_cnt_s)) ; -- log values of cnt to correlate with functional coverage
end if;
end if;
report "Interrupt Handler Done" ;
InterruptReturn(InterruptRec) ;
wait for 1 ns ;
end loop;
-- The loop is never exited so this code never runs.
osvvm.CoveragePkg.WriteBin(RxCov); -- generates a test report
wait;
end process;
Your control process cannot iterate, so change it as follows:
ControlProc : process
begin
-- Initialization of test
SetTestName("test") ;
SetLogEnable(PASSED, TRUE) ; -- Enable PASSED logs
SetLogEnable(INFO, TRUE) ; -- Enable INFO logs
-- SetLogEnable(DEBUG, TRUE) ; -- Enable INFO logs
-- Wait for testbench initialization
wait for 0 ns ; wait for 0 ns ;
TranscriptOpen(OSVVM_RESULTS_DIR & "test.txt") ;
SetTranscriptMirror(TRUE) ;
SetAlertLogOptions(WriteTimeLast => FALSE) ;
SetAlertLogOptions(TimeJustifyAmount => 15) ;
SetAlertLogJustify ;
-- Wait for Design Reset
wait until nreset = '1' ;
ClearAlerts ;
-- Wait for test to finish
-- If you have a process that uses WaitForBarrier(TestDone) somewhere else the following is ok
WaitForBarrier(TestDone, 20 ms) ; -- note I change the wait time to match the timeout period
AlertIf(now >= 20 ms, "Test finished due to timeout") ;
-- If not, replace the WaitForBarrier with
wait for 20 ms ;
AlertIf(GetAffirmCount < 1, "Test is not Self-Checking");
TranscriptClose ;
EndOfTestReports ;
-- add stop, remove wait for 7 ms
std.env.stop ;
-- wait for 7ms ;
wait ;
end process ControlProc ;