A well-known issue in hardware simulation is the potential for different results on different runs when race conditions are present. Because the HDL simulator is a highly parallel execution environment, you must write the HDL such that the results do not depend on the ordering of process execution.
Although there are well-known coding idioms for achieving a realistic simulation of a design under test, you must always take special care at the test bench/DUT interfaces for applying stimulus and reading results, even in pure HDL environments. For an HDL/foreign language interface, such as with a Simulink® or MATLAB® cosimulation session, the problem is compounded if you do not have a common synchronization signal, such as a clock, coordinating the flow of data.
All the signals on the interface of an HDL Cosimulation block in the Simulink library have an intrinsic sample rate associated with them. This sample rate can be thought of as an implicit clock that controls the simulation time at which a value change can occur. Because this implicit clock is completely unknown to the HDL engine (that is, it is not an HDL signal), the times at which input values are driven into the HDL or output values are sampled from the HDL are asynchronous to any clocks coded in HDL directly, even if they are nominally at the same frequency.
For Simulink value changes scheduled to occur at a specific simulation time, the HDL simulator does not make any guarantees as to the order that value change occurs versus some other blocking signal assignment. Thus, if the Simulink values are driven/sampled at the same time as an active clock edge in the HDL, there is a race condition.
For cases where your active HDL clock edge and your intrinsic Simulink active clock edges are at the same frequency, you can promote desired data propagation by offsetting one of those edges. Because the Simulink sample rates are always aligned with time 0, you can accomplish this offset by shifting the active clock edge in the HDL off of time 0. If you are coding the clock stimulus in HDL, use a delay operator ("after" or "#") to accomplish this offset.
When using a Tcl "force" command to describe the clock waveform, you can simply put the first active edge at some nonzero time. Using a nonzero value allows a Simulink sample rate that is the same as the fundamental clock rate in your HDL. This example shows a 20 ns clock (so the Simulink sample rates will also be every 20 ns) with an active positive edge that is offset from time 0 by 2 ns (example shown for use with Incisive®):
> force top.clk = 1'b0 -after 0 ns 1'b1 -after 2 ns 1'b0 -after 12 ns -repeat 20 ns
For HDL Cosimulation blocks with Clock panes, you can define the clock period and active edge in that pane. The waveform definition places the non-active edge at time 0 and the active edge at time T/2. This placement sets the maximum setup and hold times for a clock with a 50% duty cycle.
If the Simulink sample rates are at a different frequency than the HDL clocks, then you must synchronize the signals between the HDL and Simulink as you would do with any multiple time-domain design, even one in pure HDL. For example, you can place two synchronizing flip-flops at the interface.
If your cosimulation does not include clocks, then you must also treat the interfacing of Simulink and the HDL code as being between asynchronous time domains. You may need to over-sample outputs to see that all data transitions are captured.
When you use the
-falling_edge scheduling options to
matlabcp to trigger MATLAB function calls, the propagation of values follow the same semantics as
a pure HDL design; the triggers must occur before the results can be calculated. You
still can have race conditions, but they can be analyzed within the HDL
However, when you use the
-time scheduling option to
matlabcp, or use
tnext within the MATLAB function itself, the driving of signal values or sampling of signal
values cannot be guaranteed in relation to any HDL signal
changes. It is as if the potential race conditions in that time-based scheduling are
like an implicit clock that is unknown to the HDL engine and not visible by just
looking at the HDL code.
The remedies are the same as for the Simulink signal interfacing: make sure that the sampling and driving of signals does not occur at the same simulation times as the MATLAB function calls.
Problems interfacing designs from test benches and foreign languages, including race conditions in pure HDL environments, are well-known and extensively documented. Some texts that describe these issues include:
The documentation for each vendor’s HDL simulator product
The HDL standards specifications
Writing Testbenches: Functional Verification of HDL Models, Janick Bergeron, 2nd edition, © 2003
Verilog and SystemVerilog Gotchas, Stuart Sutherland and Don Mills, © 2007
SystemVerilog for Verification: A Guide to Learning the Testbench Language Features, Chris Spear, © 2007
Principles of Verifiable RTL Design, Lionel Bening and Harry D. Foster, © 2001