Generating HDL Code Coverage Using Simulink and Cadence Incisive

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

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:

copyCosimDemoFiles('cruise_control');

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. Open the test bench model by executing:

open_system('cruise_control_incisive');

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 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 Incisive for Cosimulation

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

tclCmds = {
    'exec ncvhdl -64bit -v93 PI_Controller.vhd',...      % Compile VHDL code
    'exec ncvhdl -64bit -v93 Controller.vhd',...         % Compile VHDL code
    'exec ncelab -64bit -coverage all -vhdl_time_precision 1ns -access +wc Controller',...    % Elaborate design with coverage enabled
    'hdlsimulink -covoverwrite Controller',...   % Load simulation
    'puts "Ready for cosimulation..."',...
};

% Now we launch HDL simulator and wait for it to ready.
nclaunch('tclstart',tclCmds,'runmode','CLI','libfile','liblfihdls_gcc44.so');
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. The 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.

for k = 1 : 9
    % Select a testcase
    signalbuilder('cruise_control_incisive/Inputs', 'activegroup', k)
    % Run simulation
    sim('cruise_control_incisive');
end

Observe Code Coverage Result

When the simulation is finished, run the following commands to generate code coverage result in ncsim and view the result in iccr GUI.

% Generate code coverage result in ncsim
tclHdlSim('coverage -dump test');
% View code coverage result in iccr GUI
system('iccr -gui -test test &');