Generating HDL Code Coverage Using Simulink and Mentor Graphics ModelSim

This example shows how to achieve complete code coverage of an HDL cruise controller design using Simulink® and ModelSim®.

Set Up Example Files

Create a folder outside the scope of your MATLAB® installation folder into which you can copy the example files. The folder must be writable.

Set the folder you created as your current folder in MATLAB.

Copy all the files located in matlabroot\toolbox\edalink\foundation\hdllink\demo_src\cruise_control to the folder you created by executing the following command in MATLAB:


Open Model

The HDL code associated with this model is generated via HDL Coder™ from a Simulink behavioral model of the cruise controller. A test bench model is provided to verify the correctness of the HDL code by comparing the output of the HDL cosimulation block with that of the original behavioral block. The testcases in the test bench model are generated through Simulink Design Verifier™ from the original behavioral model for achieving complete model coverage. This example shows that those automatically generated testcases also achieve complete HDL code coverage. You do not need Simulink Design Verifier installed to run this example. Note that the code coverage function is an optional feature in ModelSim PE. Make sure that your version of ModelSim has the proper code coverage license to run this example. Open the test bench model by executing:


Observe Cosimulation Block Settings

Open the mask of the cosimulation block "hdl_cruise_control" and select the "Simulation" tab. The settings on this tab are shown in the following picture:

Note that in the "Pre-simulation Tcl commands" field, the Tcl force command is used to generate waveforms for the control signals:

  1. The clock period is 10 ns

  2. The clock enable signal is active at 37 ns.

  3. The reset signal is asserted from 0 to 27 ns.

The purpose of the option "Time to run HDL simulator before cosimulation starts" is to properly align the signal of behavioral block "cruise_control" and the HDL signal so that they can be compared and verified directly without additional delays. This example show how to set this option in the next section.

The cosimulation starting time should be aligned with the falling edge of the HDL clock to avoid a race condition since the HDL signals change their values at the rising edge of the HDL clock. Therefore, the value of this parameter should be an integer multiple of the 10 ns clock period.

We also want to run the HDL design past reset, but stop before the first active clock edge enabled by clk_enable. This is to match the behavioral block, which updates its internal states right after the simulation starts.

Based on the above considerations, the option "Time to run HDL simulator before cosimulation starts" is set to 40 ns. When running each testcase, the "Pre-simulation Tcl commands" are applied in the HDL simulator first. Then the HDL simulator advances its time by 40 ns to apply the reset, clock, and clk_enable signals before the cosimulation starts.

Launch ModelSim for Cosimulation

The following ModelSim Tcl commands compile the HDL code and load the simulation with code coverage enabled.

tclCmds = {
    'vlib work',...                          % Create ModelSim library
    'vcom +cover PI_Controller.vhd',...      % Compile VHDL code with code coverage enabled
    'vcom +cover Controller.vhd',...         % Compile VHDL code with code coverage enabled
    'vsimulink  -coverage work.Controller',...% Load simulation
    'puts "Ready for cosimulation..."',...

% Now we launch HDL simulator and wait for it to ready.
disp('Waiting for HDL simulator to start ...');
processid = pingHdlSim(240);
disp('HDL simulator is ready to cosimulate.');

Run Simulation

There are nine testcases in the test bench model. This example runs this model with all testcases to produce the code coverage result. After finishing each cosimulation session, there is no need to restart the HDL simulator since the HDL signal is reset properly at the beginning of each simulation. After each simulation, it takes ModelSim time to update the coverage result. To prevent the potential conflict between this process and the next cosimulation session, a short pause is added between two successive simulations.

for k = 1 : 9
    % Select a testcase
    signalbuilder('cruise_control_modelsim/Inputs', 'activegroup', k)
    % Run simulation
    % Make sure ModelSim has finished previous simulation

Observe Code Coverage Result

During simulation, look at the results in the code coverage window in ModelSim. Note that the code coverage percentage increases as this example iterates through all testcases. When the simulation is finished, 100% code coverage is achieved.