Scripting dual-language testbench (VHDL / Verilog)

Why OSVVM™? Forums OSVVM Scripting dual-language testbench (VHDL / Verilog)

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
  • #2292
    Brad Adam


    I’m wondering if there has been any documentation made for using some script functions with a dual-language testbench. Looking through past articles I’ve found discussion of topics that come close to what I am trying to do but none of which speak to .pro (or since I’m simulating in Riviera .do) considerations.

    The core of what I am trying to do is use ‘SetExtendedSimulateOptions’ to set some top level testbench generics from my .do script. I’ve done this plenty of times with VHDL only DUTs and it works great but I’ve found that if the DUT uses both VHDL and Verilog I am unable to set those generics.

    I believe the main issue is that I needed to use commands like vsim instead of ‘simulate’ or ‘RunTest’ for the testbench to run but these commands don’t have the necessary hooks to read in the values being passed by ‘SetExtendedSimulateOptions’.

    As an example a the .do script would look something like this:

    source ../dir/hdl/OsvvmLibraries/Scripts/StartUp.tcl
    SetExtendedSimulateOptions "-gC_EXAMPLE_PARAM=1"
    build ../dir/OsvvmLibraries/
    build  ../dir/
    analyze ../dir/test_cases/DUT_test.vhd
    vsim work.DUT_test work.glbl -L unisim
    run -all

    Is there some consideration I am missing in OSVVM that would allow me to change the vsim command to an equivalent osvvm command and still run both the VHDL DUT_test file and the Verilog glbl file?

    Jim Lewis

    Have you tried:

    simulate DUT_test glbl -L unisim [generic C_EXAMPLE_PARAM 1]

    What library is glbl in? If it were VHDL and glbl is in the unisim library, the glbl would be referenced as unisim.glbl.

    If all of your simulations use glbl and unisim library, you can do:

    SetExtendedSimulateOptions "-L unisim"
    SetSecondSimulationTopLevel glbl
    simulate DUT_test [generic C_EXAMPLE_PARAM 1]
    simulate ... 
    Brad Adam


    glbl is a verilog file referenced by an IP from a third party vendor.

    Is it possible to set a generic for a file that is analyzed before simulation? Looking at the script users guide I would think that SetExtendedAnalyzeOptions is meant to accomplish this but I could be using the command incorrectly. Is it possible to use SetExtendedAnalyzeOptions to set the value of a generic in a specific analyzed file?

    In this case DUT_test would be a configuration of the main DUT_TB entity defined in a separate file, so I’m trying to set a generic set in DUT_TB which is analyzed before simulating DUT_test.


    Jim Lewis

    In OsvvmLibraries/Ethernet/TestStandAlone/, I set the generics for the top level test by doing:

    simulate Tb_xMii1 [generic MII_INTERFACE RGMII] [generic MII_BPS BPS_1G]

    Here Tb_xMii1 is the name of the configuration for the testharness (named TbStandAlone).

    So if you have not already, add top level generics to the testharness that are then mapped to lower level blocks. Looking at the example above may help some.

    From the RiveraPRO command reference on asim/vsim,

    Assigns values to VHDL generics, Verilog and SystemVerilog parameters, and SystemC generics that are not assigned values in VHDL generic maps or through the Verilog/SystemVerilog defparam statement. Has no effect on SystemVerilog parameterized classes.
    The name part of the argument can include a relative or hierarchical path (without the dataset logical name, i.e. without string sim: at the beginning). For example:

    So if you have mapped a lower level generic, it does not look like you can override it with this. So instead, have a top level generic that is not mapped, and connect it to the lower level examples – just like done in the Ethernet testharness.

    Brad Adam

    Okay, this is very helpful information and from this I believe the answer to what I am trying to do is probably no.

    Looking at TestStandAlone.vhd assume there is a generate statement that decides if xMiiPhy gets created or not.

    phy_gen : if C_PHY_GEN_TRUE = 1 generate
      xMiiPhy_1 : xMiiPhy 
        generic map (
          MII_BPS        => MII_BPS, 
          DEFAULT_DELAY  => tpd
        port map (
          -- xMii Transmitter Functional Interface
          GTx_Clk       => GTx_Clk      ,
          Tx_Clk        => Tx_Clk       ,
          TxD           => TxD          ,
          Tx_En         => Tx_En        ,
          Tx_Er         => Tx_Er        ,
          Tx_Ctl        => Tx_Ctl       ,
          -- xMii Receiver Interface
          Rx_Clk        => Rx_Clk       ,
          RxD           => RxD          ,
          Rx_Dv         => Rx_Dv        ,
          Rx_Er         => Rx_Er        ,
          Rx_Ctl        => Rx_Ctl       ,
          Crs           => Crs          ,
          Col           => Col          ,
          -- Testbench Transaction Interface
          PhyTxRec     => PhyTxRec    ,
          PhyRxRec     => PhyRxRec
        ) ;
    end generate phy_gen;

    In the above code passing something like MII_INTERFACE into the xMiiPhy using the simulate commands makes total sense, those generics will not be needed before simulation begins. However, C_PHY_GEN_TRUE is needed before simulation of a testcase occurs.

    Does OSVVM assume that generics will not be used in this way? If this is not recommended for OSVVM I will restructure my testbenches going forward but I wanted to be sure I wasn’t missing something simple that would allow me to control a generate statement in the TB before running a dependent testcase.

    Jim Lewis

    Hi Adam,
    If C_PHY_GEN_TRUE is a top level generic, OSVVM will allow you to specify it for either simulate or RunTest. As long as your simulator supports that, it should work just fine. Generate is resolved at elaboration time – which is the first step of simulation.

    Have you tried something like this and it failed to work?


    Brad Adam

    Yes, this fails before the simulation phase is ever reached because I have two testbenches that are testing two versions of a DUT which has a different port list in each testbench but use the same TB file. These two testbenches have separate .pro files and test cases but they share the TB file. When analyzing that TB file, since the generic has not been set to control the generate statement yet the simulation fails as it sees signals from the other DUT which is meant NOT to be generated and throws “unknown identifier” errors.

    I’m fairly certain that in the OSVVM Ethernet example, if for whatever reason two versions of ethernet were using TestStandAlone.vhd with generate statements to create one version of the DUT or the other, it would encounter the same issue.
    “analyze TestStandAlone.vhd” would fail because the generic that controls which version of the DUT is created would not be set until the next line, “RunTest Tb_xMii1.vhd”.

    Luckily its pretty easy to just split the TB file into two, one for each version of the DUT. I just thought I must be missing something because during initial testing I was using a constant variable to generate the correct DUT during analyze just fine but when I pulled that constant to the top level as a generic it broke the testbench.


    Brad Adam

    Jim Lewis

    Hi Brad,
    I have had on my todo list to come back to look at this example in further detail – I have just had a very busy year end for 2023.

    Since I don’t have a copy of your testbench, we have only been able to talk in generalities. However, I think I see the issue in your statement here:

    > When analyzing that TB file, since the generic has not been set to control the generate statement yet the simulation fails as it sees signals from the other DUT which is meant NOT to be generated and throws “unknown identifier” errors.

    Generate statements differ from VHDL-2019’s conditional analysis in that everything in a generate statement must analyze – whether you intend to enable it or not. Hence, if that part of the testbench had pieces that will not analyze, then you will get analysis errors.

    Now though, you probably have two separate working testbenches – you could merge them back together. However, I probably would not. I consider the cost of having two separate test harness very low.

    OSVVM has a situation like this when testing the Axi4Manager.vhd and Axi4ManagerVti.vhd. The Axi4ManagerVti is a special version of the Axi4Manager that is used internal to a DUT where we have no ports that can be routed to the outside. Internally these two VC are identical (done by copying). Externally, Axi4Manager uses a port for the transaction interface and Axi4ManagerVti uses an internal signal for the transaction interface. The testbench/test harness connects to the Axi4Manager using port maps. The test bench connects to the Axi4ManagerVti using external names.

    Even though I could handle these by a simple generic specified to the test harness when the test loads, I decided to do it by two separate test harnesses that are mirror images of each other (all signal names and instance names are the same) – the external name on the Vti component uses an identical name to the signal name for the port of the regular component.

    Both VC will run the same test cases. Since the test harness and test ctrl from both versions use identical names, the same test case will run in either environment.

    To run the tests, I created a RunAllTests that runs the regular component that does:

    include testbench
    include TestCases

    And I created a RunAllTestsVti that runs the internal signal + external name based component that does:

    include testbenchVti
    include TestCases

    Had I used generics, then I would have needed to have a setting that passes the generic value down to the TestCases script. This is worth doing when necessary, but otherwise, I try to avoid it.

    Best Regards,

Viewing 9 posts - 1 through 9 (of 9 total)
  • You must be logged in to reply to this topic.