Multiple VVCs question (1 testbench, 1 test harness, 1 test sequencer process?)

Hi Kevin,
For a setup with 1 testbench, multiple test harnesses, I guess you can create a test_lib and compile both adc_vvc_th.vhd and i2c_vvc_th.vhd to this library, along with testbench.vhd. From the testbench perspective you will reference the test-harnesses by work.<interface_name>_vvc_th

Br,
Marius

Hi Marius,

Thanks for your reply to the 4 extra td_ files matter. I compiled this earlier for the ClockCycleCounter one wrt 4 td_ files so all 10 files were compiled to the bitvis_vip_clockcyclecounter library and simulation results were still successful. This was my testcase with just 1 DUT and 1 Test Harness.

You can see the compile order in e.g. bitvis_vip_sbi/doc/sbi_vvc_qr.pdf - final page.

I can see from that final .pdf page that the vvc_context.vhd was missing from the list (only 9 files are listed there. They should be 10). I included that in my compilation list as the last one to be compiled.

Kind regards,
Kevin

Hi Marius,

Another thing I noticed. One of the files VVC generator generated automatically was the vvc_context.vhd file. Recall that I had to replace within it:

–use bitvis_vip_clockcyclecounter.clockcyclecounter_bfm_pkg.t_clockcyclecounter_if;
–use bitvis_vip_clockcyclecounter.clockcyclecounter_bfm_pkg.t_clockcyclecounter_bfm_config;
–use bitvis_vip_clockcyclecounter.clockcyclecounter_bfm_pkg.C_CLOCKCYCLECOUNTER_BFM_CONFIG_DEFAULT;

with:

use bitvis_vip_clockcyclecounter.clockcyclecounter_bfm_pkg.all;

otherwise had a compilation error:

** Error: …/vvc_vhdl/vvc_tb.vhd(187): (vcom-1136) Unknown identifier “counter_check” when compiling my testbench.

counter_check is a procedure I created within the clockcyclecounter_bfm_pkg.vhd

Why did it list individually the 3 above separate ones (the ones I commented out above)? These could be all replaced by:

 use bitvis_vip_clockcyclecounter.clockcyclecounter_bfm_pkg.all;

Any other suggestions or do you agree with my change?
Please comment here.

Regards,
Kevin

Hi Marius,

Wrt my setup with 1 testbench, multiple test harnesses (eg 2 test harnesses so far), I created test_lib and tried to compile both test harnesses (adc_vvc_th.vhd and i2c_vvc_th.vhd) to this library.

It started now reporting many compilation errors eg

** Error: (vcom-11) Could not find work.common.

** Error (suppressible): …/vvc_vhdl/adc/adc_vvc_th.vhd(22): (vcom-1195) Cannot find expanded name “work.Common”.

** Error: …/vvc_vhdl/adc/adc_vvc_th.vhd(22): Unknown expanded name.

I compiled this within my .do file script already before hand as follows:
vcom -2008 -work work {…/…/vhdl_code/Common.vhd}

but it flagged it again as an Error (see above).


The common.vhd is a package vhd file we use which declares all the types, subtypes, constants etc for our main FPGA. The DUTs were using eg the type ‘Words’ declaration and they were picking this up from this package. Used this type within my test harness port map declaration and defined this at the top as:
use work.Common.all;

The ClockCycleCounter DUT was also using it and declared it also at the top as: use work.Common.all;
(DUT should remain as it is without any changes)

I tried to compile the Common.vhd within the work library just before compiling the test harness but it flagged the same error as above again.

I then added the following in bold within my .do file just before compiling the test harness:
vcom -2008 -work test_lib {…/…/vhdl_code/Common.vhd}

vcom -2008 -work test_lib {…/vvc_vhdl/adc/adc_vvc_th.vhd}

it started then flagging Errors with the rest of the hierarchy:

** Error: (vcom-11) Could not find work.clockcyclecounter.

** Error (suppressible): …/vvc_vhdl/adc/adc_vvc_th.vhd(66): (vcom-1195) Cannot find expanded name “work.ClockCycleCounter”.

** Error: …/vvc_vhdl/adc/adc_vvc_th.vhd(66): Unknown expanded name.

After I added the following in bold too ie

vcom -2008 -work test_lib {…/…/vhdl_code/Common.vhd}
vcom -2008 -work test_lib {…/…/vhdl_code/timer/ClockCycleCounter.vhd}

vcom -2008 -work test_lib {…/vvc_vhdl/adc/adc_vvc_th.vhd}

it flagged the following error:

** Error: (vcom-11) Could not find work.clockcyclecounter_vvc.

** Error (suppressible): …/vvc_vhdl/adc/adc_vvc_th.vhd(91): (vcom-1195) Cannot find expanded name “work.clockcyclecounter_vvc”.

** Error: …/vvc_vhdl/adc/adc_vvc_th.vhd(91): Unknown expanded name.

etc…

Do I have to re-compile all the submodules into test_lib including the VVCs etc? I was not expecting this here. I must be doing something wrong…


Before I had the test harness and testbench compiled within work library but had issues when it was compiling the testbench. Changed the ‘work’ library to ‘test_lib’ as you suggested but it started flagging the above errors when it was trying to compile the 1st test harness.

Within my test harness eg adc_vvc_th.vhd, I currently declare in the instantiation part of the DUT and VVC as follows:

i_ClockCycleCounter: entity work.ClockCycleCounter
::

i_clockcyclecounter_vvc: entity work.clockcyclecounter_vvc
::

I also tried to change within the adc_vvc_th.vhd to the following for the VVC instance:

i_clockcyclecounter_vvc: entity bitvis_vip_clockcyclecounter.clockcyclecounter_vvc
::

but had other compilation errors such as:

** Error: …/vvc_vhdl/adc/adc_vvc_th.vhd(103): Signal [mode OUT port] “out_counter” is type work.Common.Words; expecting type bitvis_vip_clockcyclecounter.Common.Words.

Will appreciate your comments to this matter.

Regards,
Kevin

Hi Marius,

Wrt above email I reported earlier “setup with 1 testbench, multiple test harnesses (eg 2 test harnesses so far)” wrt errors seen, I think I resolved all of them.

I compiled the clockcyclecounter DUT into a separate library adc_lib
and the bfm, vvc packages and adc_vvc_th.vhd added:

library adc_lib;
use adc_lib.Common.all;

The compilation flow went through ok.

The other test harness DUT was compiled within i2c_lib and referenced within the test harness instantiation part as
i_checkStable: entity i2c_lib.checkStable
:::

I created also a test_lib and compiled both adc_vvc_th.vhd and i2c_vvc_th.vhd to this library, along with testbench.vhd (as you suggested).

Test harness instances within the testbench I referenced both test harnesses with ‘work.<interface_name>_vvc_th’ as you suggested in your previous email.

Testbench compiled ok too.

Declared at the top of the testbench also:
library adc_lib;
use adc_lib.Common.all;

because it was using within it in the 1st test harness instance one of the Common package declarations.

I had an error kickstarting simulation but this is something else which I will rectify too shortly.

Hope the simulation with 1 testbench and 2 test harnesses runs ok. Will report results soon.

Best regards,
Kevin

1 Like

Hi Marius,

Managed to get the combined 1 testbench, 2 test harnesses to simulate ok :slight_smile:

Moved the ti_uvvm_engine instance to the testbench level and removed it from the test harnesses because had the following warning:
“ti_uvvm_engine seems to have been instantiated more than once in this testbench system”

Best regards,
Kevin

Hi Kevin,
Great! Yes, the ti_uvvm_engine should only be instantiated once, and putting it in the testbench is a good approach.

Br,
Marius

Hi Marius,

Since we have now 1 testbench (includes within it 1 test sequencer process) and eg 2 test harnesses that the testbench instantiates, if I execute within the test sequencer process separate VVC commands of the 2 different eg DUTs, it all works in a sequential fashion ie

eg reseting the ClockCycleCounter followed by reseting the checkStable
resetting the ClockCycleCounter DUT happens first (ClockCycleCounter belongs to the 1st test harness) and resetting of the CheckStable DUT happens next (checkStable belongs to the 2nd test harness).

So both resets could not happen concurrently in this example and thus in the simulation window I see the checkStable block having undefined reset output value at the start until the ClockCycleCounter reset completes and the CheckStable reset command kickstarts.

The only way I think to run separate concurrent DUT/VVC interfaces commands, if we only want to still have 1 testbench, is to have within it multiple test sequencer processes (ie all can then run in parallel - in this example 2 test sequencer processes within 1 testbench that instantiates 2 test harnesses). Is this the case? Please comment here.

Kind regards,
Kevin

Hi,
I think you are overcomplicating the test by having 1 testbench and multiple test harness. Can you clarify how you intend to test:

  • one DUT at a time
  • both DUTs at the same time

I guess you have each DUT instantiated in their own test harness?

The VVC commands are distributed from the test sequencer at no time, i.e. you can distribute many VVC commands to various VVCs at the same time, and the commands distributed to each VVC will be executed in the same order as they were written in the test sequencer. When the VVC command(s) have been sent from the sequencer, you will typically wait for the VVC to finish executing the command (await_comlpetion() - see Common VVC Methods PDF in uvvm_vvc_framework/doc) before you send new commands or check the response from the DUT etc.

Br,
Marius

Hi Marius,

I agree with you wrt your statement of ‘overcompicating the test by having 1 testbench and multiple test harnesses’…

However, this is what my team asked me to do after a review meeting ie use 1 testbench and multiple test harnesses to verify the whole FPGA. So related DUT interfaces will be instantiated within one test harness together with their VVCs. My choice was to use multiple testbenches but this method was not agreed to use.

The Test sequencer I use is a process within the testbench and VVC commands are issued as follows eg

:::
log(ID_SEQUENCER, “Pulse the ClockCycleCounter in_reset for 10 clock periods”, C_SCOPE)

counter_reset(CLOCKCYCLECOUNTER_VVCT, 1, 10, “Reset counter value”);
await_completion(CLOCKCYCLECOUNTER_VVCT, 1, 11*C_CLK_PERIOD, “Await completion”);

counter_check(1, “1st counter check”, x"0000", out_counter(0), in_clock, ErrCnt, TotalPass, TotalCnt, C_SCOPE);

::

log(ID_SEQUENCER, “Pulse the checkStable in_reset for 10 clock periods”, C_SCOPE);

checkStable_reset(CHECKSTABLE_VVCT, 1, 10, “Reset checkStable module”);

await_completion(CHECKSTABLE_VVCT, 1, 11*C_CLK_PERIOD, “Await completion”);

log(ID_SEQUENCER, “Check the checkStable out_bus value right after reset”, C_SCOPE);

checkStable_check(1, “1st checkStable check - Check out_bus right after reset”, ‘0’, out_bus, in_clk, ErrCnt, TotalPass, TotalCnt, C_SCOPE);

:::

– Other VVC commands follow in a similar way as above
:::


So from the above each VVC command is wait to be completed before a new command is send or check the response from the DUT.

So they are executed in the same order as they were written in the test sequencer and not concurrently. Isn’t this the case here?

& if we like then for the separate test harnesses the VVC commands to be concurrent, 2 separate Test Sequential processes must be included within the 1 testbench (executing separately their VVC commands) wrt this example. Do you agree here?

Kind regards,
Kevin

Hi Kevin,
Yes, the commands are executed in the same order as written in the sequencer.
You can call both counter_reset() and check_stable_reset() before the await_completion() if you want the two VVC commands to be executed at the same time. E.g.

log(ID_SEQUENCER, "Pulsing ClockCycleCounter and checkStable resets for 10 clk periods", C_SCOPE);
counter_reset(CLOCKCYCLECOUNTER_VVCT, 1, 10, “Reset counter value”); 
checkStable_reset(CHECKSTABLE_VVCT, 1, 10, “Reset checkStable module”);

await_completion(CHECKSTABLE_VVCT, 1, 11*C_CLK_PERIOD, “Await completion”);

log(ID_SEQUENCER, “Checking reset values”, C_SCOPE);
counter_check(1, “1st counter check”, x"0000", out_counter(0), in_clock, ErrCnt, TotalPass, TotalCnt, C_SCOPE);
checkStable_check(1, “1st checkStable check - Check out_bus right after reset”, ‘0’, out_bus, in_clk, ErrCnt, TotalPass, TotalCnt, C_SCOPE);

Can both DUTs use the same reset, or are there a reason you need two reset VVCs?

Just as a note; for the reset checking I would probably have created a reset_checker process inside the test harness, that monitors the DUT reset signal and triggers the checker methods every time the reset signal is released, simplifying your sequencer and ensures that the reset values are checked for every testcase. E.g

p_reset_checker: process
begin
  while true loop
    wait until reset'event and reset='1'; -- active low reset
    checkStable_check(1, “1st checkStable check - Check out_bus right after reset”, ‘0’, out_bus, in_clk, ErrCnt, TotalPass, TotalCnt, C_SCOPE);
    counter_check(1, “1st counter check”, x"0000", out_counter(0), in_clock, ErrCnt, TotalPass, TotalCnt, C_SCOPE);
  end loop;
  wait;
end process;

Br,
Marius

Hi Marius,

Thanks for your reply wrt calling both counter_reset() and check_stable_reset() before the await_completion(). The 2 VVC commands are now executed at the same time :slight_smile:

Is there a reason why you have suggested creating a reset_checker process inside the test harness and not within the testbench?

Kind regards,
Kevin

Hi,
If you have more than one testcase you will reuse the test harness with all testcases (i.e. sequencers). Putting the reset checking in the harness will ensure that reset values are always checked (i.e. you actually don’t need a testcase for reset checking because it is always checked).

Br,
Marius