Sunteți pe pagina 1din 50

ModelSim

Technote Library
Published: 5/Nov/02

ModelSim /VHDL, ModelSim /VLOG, ModelSim /LNL, and ModelSim /PLUS are
produced by Model Technology, a Mentor Graphics Corporation company.
Copying, duplication, or other reproduction is prohibited without the written consent
of Model Technology.
The information in this manual is subject to change without notice and does not
represent a commitment on the part of Model Technology. The program described
in this manual is furnished under a license agreement and may not be used or
copied except in accordance with the terms of the agreement. The online
documentation provided with this product may be printed by the end-user. The
number of copies that may be printed is limited to the number of licenses
purchased.
ModelSim is a registered trademark and Signal Spy, TraceX, ChaseX and Model
Technology are trademarks of Mentor Graphics Corporation. PostScript is a
registered trademark of Adobe Systems Incorporated. UNIX is a registered
trademark of AT&T in the USA and other countries. FLEXlm is a trademark of
Globetrotter Software, Inc. IBM, AT, and PC are registered trademarks, AIX and
RISC System/6000 are trademarks of International Business Machines
Corporation. Windows, Microsoft, and MS-DOS are registered trademarks of
Microsoft Corporation. OSF/Motif is a trademark of the Open Software Foundation,
Inc. in the USA and other countries. SPARC is a registered trademark and
SPARCstation is a trademark of SPARC International, Inc. Sun Microsystems is a
registered trademark, and Sun, SunOS and OpenWindows are trademarks of Sun
Microsystems, Inc. All other trademarks and registered trademarks are the
properties of their respective holders.
Copyright (c) 1990 -2002, Model Technology, a Mentor Graphics Corporation
company. All rights reserved. Confidential. Online documentation may be printed
by licensed customers of Model Technology and Mentor Graphics for internal
business purposes only.
Model Technology
10450 SW Nimbus Avenue / Bldg. R-B
Portland OR 97223-4347 USA
phone: 503-641-1340
fax: 503-526-5410
e-mail: sales@model.com
home page: http://www.model.com

ModelSim Technote Library

Table of contents
Tool usage
Sampling signals at a clock change . . . . . .
Converting signal values to strings . . . . . .
Hiding library cell signals when saving a waveform file .
Examining constants in a package . . . . . .
Performance affected by scheduled events being cancelled
Rounding of delay values when backannotating SDF .
Inlining modules and the -forcecode option . . . .
Issue with +nocheckALL and certain optimized cells .
$sdf_done system task . . . . . . . . .
`uselib and the -compile_uselib argument . . . .
Using the -g argument to modify a generic of type string
Using virtual regions to reconstruct bit-blasted busses .
Run-time error when using time'POS(x) . . . . .
Out-of-range error message . . . . . . . .
Case choice error: "must be a locally static expression" .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

5
5
6
6
7
7
8
9
11
12
13
14
15
16
17

Language
Delta delays . . . . . . . . . .
Event ordering in Verilog designs
. . . .
Verilog simulator resolution . . . . . .
Hierarchical references in a mixed-language design
Incorrect use of VHDL bidirectional ports . .
WAIT statementsVHDL vs. Verilog
. . .
Verilog tran gate in mixed-language designs . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

18
20
24
27
28
31
33

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

34
37
39
42
44
46
47

Platform
NFS problems with Red Hat 7.0, 7.1, and 7.2 . . .
Window manager bug with early versions of KDE . .
Memory addressing above 2GB on an HP platform . .
Problems loading an FLI/PLI compiled on HP-UX 11.0 .
Problems when linking a PLI application on Windows .
RPC_Init error on HPUX . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

48
48
49
49
50
50

.
.
.
.
.
.
.

Timing and SDF


Negative timing check limits . . . . . . .
Backannotation of interconnect delays . . . .
Combining distributed delays and path delays . .
Glitch filtering. . . . . . . . . . .
IOPATH delayVITAL vs. Verilog . . . . .
Interconnect delay on X transitionsVITAL vs. Verilog
Using the RECREM timing check with VITAL cells.

ModelSim Technote Library

Introduction

Introduction
This document discusses various issues related to running simulations in ModelSim.

ModelSim Technote Library

Sampling signals at a clock change

Tool usage
Sampling signals at a clock change
You can do this easily using the add list command with the -notrigger argument.
-notrigger disables triggering the display on the specified signals. For example:
add list clk -notrigger a b c

When you run the simulation, List window entries for clk, a, b, and c appear only when clk
changes.
If you want to display on rising edges only, you have two options:
1 Turn off the List window triggering on the clock signal, and then define a repeating
strobe for the list window
2 Define a "gating expression" for the List window that requires the clock to be in a
specified state

Converting signal values to strings


You may want to display certain signal values as strings. For example, rather than
displaying the value 0, you may want to display the string "idle." The virtual type
command allows you to do this.
The virtual type command creates a new enumerated type, known only by the GUI. The
steps for using the command are as follows:
1 Define a virtual type that contains the states:
virtual type { state0 state1 state2 state3} myState

2 Define a virtual function for translating the signal values to strings


virtual function {(mystate)mysignal} myConvertedSignal

3 Display the translated value


add wave myConvertedSignal

When myConvertedSignal is displayed in the Wave, List or Signals window, the string
"state0" appears when mysignal == 0, "state1" when mysignal == 1, "state2" when
mysignal == 2, and so on.
See the virtual type command in the ModelSim Command Reference for further details.

ModelSim Technote Library

Tool usage

Hiding library cell signals when saving a waveform file


Gate-level simulations may result in large waveform files because the internal signals of
your library cells are saved. Use the following method to prevent ModelSim from saving
these signals in a Verilog design.
If your cells are enclosed in Verilog `celldefine and `endcelldefine preprocessor directives,
you can specify -fast on the vlog command line when compiling the cell library. This
basically hides the internal signals so they are not saved. A further benefit of this
methodology is that cells compiled with -fast consume less memory.
See "Compiling with -fast" in the Verilog chapter of the ModelSim Users Manual for
further details on using -fast.

Examining constants in a package


To examine a constant in a package, first define a process with a variable that references
the constant and then examine that process variable. The code below demonstrates.
Say you have the following package:
package bpack is
constant a1 : integer := 4;
end bpack;

To examine constant a1, first define a process with a variable that references the constant.
For example:
use work.bpack.all;
entity x is
port (a : in bit; b : out bit);
end x;
architecture simple of x is
begin
dummy : process
variable x1 : integer := 0;
begin
x1 := a1;
wait;
end process;
end simple;

Now when you load entity x, you can examine variable x1 to get the value of constant a1.
vsim x
view source
examine x1
# 4

ModelSim Technote Library

Performance affected by scheduled events being cancelled

Performance affected by scheduled events being cancelled


Performance suffers if events are scheduled far into the future but then cancelled before
they take effect. This situation acts like a memory leak and slows down simulation.
In VHDL this situation can occur several ways. The most common are waits with time-out
clauses and projected waveforms in signal assignments.
The following code shows a wait with a time-out:
signals synch : bit := '0';
...
p: process
begin
wait for 10 ms until synch = 1;
end process;
synch <= not synch after 10 ns;

At time 0 process p makes an event for time 10 ms. When synch goes to 1 at 10 ns, the event
at 10 ms is marked as cancelled but not deleted, and a new event is scheduled at 10 ms +
10 ns. The cancelled events are not reclaimed until time 10 ms is reached, and the cancelled
event is processed. As a result there will be 500000 (10 ms/20 ns) cancelled but undeleted
events. Once 10 ms is reached, memory no longer increases because the simulator is
reclaiming events as fast as they are added.
For projected waveforms, the following behaves the same way:
signals synch : bit := '0';
...
p: process(synch)
begin
output <= '0', '1' after 10ms;
end process;
synch <= not synch after 10 ns;

Rounding of delay values when backannotating SDF


ModelSim rounds delays when they are less than the simulator's resolution. This may cause
SDF delay values to be truncated unexpectedly. For example, an SDF file has a timescale
of 1 ns and has the following delay values:
IOPATH a z (0.014:0.015:0.016) (0.014:0.015:0.016)

If the simulator's resolution is set to 10 ps, then the delays that get annotated are rounded
as follows:
MINIMUM delays
TYPICAL delays
MAXIMUM delays

14 ps -> gets rounded to 10 ps


15 ps -> gets rounded to 20 ps
16 ps -> gets rounded to 20 ps

In order to get the exact delay value as it is specified in the SDF file, the simulator's
resolution must be set to 1 ps.

ModelSim Technote Library

Tool usage

Inlining modules and the -forcecode option


ModelSim attempts to inline (combine) modules when you compile a design using -fast
(see the Verilog chapter of the ModelSim Users Manual for more details on -fast). When
this inlining occurs, no fast.asm file is created in the inlined modules library directory.
Without a *.asm file, the simulator cannot directly instantiate the module. The -forcecode
argument ensures that code is generated for inlined modules so they can be directly
instantiated.
Suppose you have the following library
cells: inv_a, inv_b, inv_c, and inverter. The
cell inverter is instantiated in each of the
other cells. If you compile these cells with
-fast and without -forcecode, ModelSim
generates a fast.asm file only for the cells
inv_a, inv_b, and inv_c. The cell inverter
will not have a fast.asm file in its library
directory. But if you compile the design
with -forcecode, ModelSim creates this file
for every cell regardless if it has been
inlined.

inv_a

inv_b

inv_c

inverter

We recommend using -forcecode when compiling all gate-level libraries.


Here are a few other things to keep in mind about inlining:
Inlining occurs only if the lower-level module is not defined as a cell. A module is
considered a cell if the module contains a non-empty specify block.
ModelSim never inlines UDPs

Auto-refreshing of inlined modules


Even if you dont use the -forcecode option, and a design contains instances of cells that
have been inlined (i.e. no fast.asm files in that instances library), the simulator
"auto-refreshes" those cells and create a verilog.asm file. ModelSim can use that file to
instantiate the module.
The main drawback to this approach concerns libraries that have been made write-only.
ModelSim cannot refresh write-only libraries. So, if you dont use the -forcecode option
during the original compile, the design will not load because ModelSim cant find the
necessary files to instantiate the cell.

ModelSim Technote Library

Issue with +nocheckALL and certain optimized cells

Issue with +nocheckALL and certain optimized cells


The +nocheckALL argument to vlog overrides checks that prevent cells from optimizing
under various conditions. One such condition is when a cell has an output that is used
internally to drive other logic.
buf (Z, A);
nand (PO, Z, PI);
A

PO

PI

If the +nocheck argument is not used, the compiler issues the following warning:
WARNING[10]: cell.v(xx): [OPRD] - Not optimizing library module because
output port is read internally by module

Overriding this condition with the +nocheckALL argument and causing the cell to
optimize is not normally an issue, but in some cases it can cause problems. For instance,
assume this cell has the following iopaths specified:
A => Z
A => PO
PI => PO

ModelSim Technote Library

10

Tool usage

The optimized cell cannot recognize the A => PO path. In the optimized cell, the inputs to
the NAND gate are seen as Z and PI. Since there is not an iopath declared from Z => PO,
no delay is annotated. Only the A => Z delay that has already been annotated to the output
Z is seen:

A
Z
PO

A => Z

However, if you prevent the cell from optimizing, the correct delay values are seen:

A
Z
PO

A => Z

A => PO

There is a compiler directive in ModelSim to selectively disable the +nocheckALL switch.


This directive is used so that most cells are optimized, and only the cells that have problems
such as the one above are exempted from the optimization process. ModelSim also has a
built-in variable in the compiler that can be placed in a `ifdef block to make the code
portable to other simulators:
`ifdef MODEL_TECH
`mti_disable_nocheck
`endif

ModelSim Technote Library

$sdf_done system task

11

$sdf_done system task


$sdf_done is a ModelSim-specific system task that is not part of the IEEE Std 1364. It is a
"cleanup" function that removes internal buffers, called MIPDs, that have a delay value of
zero. These MIPDs are inserted in response to the -v2k_int_delay argument to vsim.
In general ModelSim automaticallys remove all zero delay MIPDs. However, in one case
ModelSim cannot determine if the MIPDs should be removed. The following code shows
this problem:
module amod;
integer a = 0;
initial
begin
$sdf_annotate("a.sdf");
if ( a )
$sdf_annotate("b.sdf");
end
endmodule

ModelSim waits for the second $sdf_annotate() call before removing zero-delay MIPDs.
However, variable a is always 0, so the second $sdf_annotate() call never executes.
Because the second call never happens, the zero-delay MIPDs are not removed.
Extraneous MIPDs reduce simulator performance. The solution is to "manually" remove
the MIPDs by calling $sdf_done.
Note: $sdf_annotate() cannot be called after $sdf_done has been called.

Since $sdf_done is a ModelSim-specific task, your design will not be portable if the task is
present in the code. To prevent errors if you run your design in other simulators, you can
qualify $sdf_done with the MODEL_TECH environment variable. MODEL_TECH is set
automatically by ModelSim upon invocation. The following code shows you how to use it
with $sdf_done:
module amod;
integer a = 0;
initial
begin
$sdf_annotate("a.sdf");
if ( a )
begin
$sdf_annotate("b.sdf");
`ifdef MODEL_TECH
$sdf_done;
`endif
end
end
endmodule

ModelSim Technote Library

12

Tool usage

`uselib and the -compile_uselib argument


We added the -compile_uselibs argument to vlog to ease the use of `uselib directives. The
argument finds the source files referenced in the directive, compiles them into
automatically created object libraries, and updates the modelsim.ini file with the logical
mappings to the libraries.
The `uselib compiler directive can be used in three ways.
1 It can reference a library. In this case, ModelSim looks in the referenced library for
instantiated objects. For example:
`uselib lib=components

This behaves similarly to a LIBRARY/USE clause in VHDL. As with VHDL, the correct
mappings must be setup if the library does not exist in the current working directory. The
-compile_uselibs argument does not affect this usage of `uselib.
2 It can reference a directory or directories containing source code. The "libext" argument
is used to identify the type of files to search. For example:
`uselib dir=./src1 libext=.v

This compiler directive is equivalent to the following command line:


vlog -y ./src1 +libext+.v mux81.v

However, using the -y switch causes needed objects to be compiled into the same library
with the rest of the design. Using -compile_uselibs with a `uselib statement causes the
referenced objects to be compiled into a different library (as described below).
3 It can reference a file(s). For example:
`uselib file=./src1/mux21.v file=./src2/mux41.v

This compiler directive is equivalent to the following command line:


vlog -v ./src1/mux21.v -v ./src2/mux41.v

Like -y, the -v switch causes needed objects to be compiled into the same library with the
rest of the design. Using -compile_uselibs with a `uselib statement causes the referenced
objects to be compiled into a different library.
When using -compile_uselibs, ModelSim determines where to compile the source files
based on the following:
Explicit directory name given to the argument (e.g., -compile_uselibs=./components).
The MTI_USELIBS_DIR environment variable.
If no explicit name is given to the argument, and the environment variable is not set,
ModelSim creates a directory called mti_uselibs.

ModelSim Technote Library

Using the -g argument to modify a generic of type string

13

Using the -g argument to modify a generic of type string


You may observe inconsistent behavior when using the -g argument to vsim to modify a
generic of type string. Lets say you declare the following generic in a component:
GENERIC( message : string := "The signal has changed" );

Using this generic with configurations and generic maps works correctly. However,
ModelSim cannot modify this generic from the command line. For example, invoking the
following command from csh returns a warning, and the value of the generic is not
changed:
vsim -gmessage="The signal has changed" gen_test
** Warning: "The signal has changed" is not a valid value for generic message

Additionally, if you use this syntax at the ModelSim command line or in a DO file,
ModelSim reports that it cannot find work.signal.
What is going on?
The trick with modifying generics/parameters of type string is that the double quotes ("")
MUST make it into ModelSim. Shells often strip away the double quotes and parse the text
on the whitespace. To prevent this from happening, you must vary the syntax depending on
how/where you invoke vsim:
csh (UNIX/Linux)
vsim -gmessage='"The signal has changed"' gen_test

ModelSim command line or a DO file (Tcl/Tk):


vsim {-gmessage="The signal has changed"} gen_test

DOS batch file (Window's):


vsim -gmessage=\"The signal has changed\" gen_test

ModelSim Technote Library

14

Tool usage

Using virtual regions to reconstruct bit-blasted busses


One use for virtual regions is reconstructing busses so that an RTL design can be compared
to the synthesized version.
During synthesis the design hierarchy is typically flattened and busses are bit-blasted. If
you wanted to do a comparison using the Waveform Compare tool, you would need to do
it bit-by-bit. For example:
compare add rtl:/top/count/q[15] gate:/synthesized_name_15
compare add rtl:/top/count/q[14] gate:/synthesized_name_14
.
.
.
compare add rtl:/top/count/q[0] gate:/synthesized_name_0

Alternatively, you can create a virtual region and signal to use for the comparison:
virtual region gate:/ top
virtual region gate:/top count
virtual signal -install gate:/top/core {(concat_range 31:0) &
"gate:/synthesized_name_*"} q
.
.
.
compare add /top/count/q

The first command creates a virtual region named "top" and sets its parent to the root of the
flattened gate-level design. The second command creates a virtual region named "count"
and sets its parent to gate:/top. The third command creates a virtual bus, with range 31
downto 0, that is the concatenation of the synthesized_name_* signals .

ModelSim Technote Library

Run-time error when using time'POS(x)

15

Run-time error when using time'POS(x)


You may encounter a run-time error with VHDL code like the following:
real_time := (real(time'POS(NOW)) / (real(time'POS(time_units))));

The error message youd receive looks like this:


# ** Fatal: time'pos(9100 ns) cannot be represented as an integer.

The error may be doubly confusing because the code runs without error in Cadence. What
is going on?
The difference lies in how the two simulators handle the scaling of the base units for the
physical data type "time". The base units for "time" are femtoseconds. When we set the
simulator resolution, we do not change the base units of that physical data type. The
Cadence simulator must change these base units. This is just a difference in
implementation, not a violation of the IEEE standard.
In the current example, the user is passing 9100 nanoseconds to the attribute:
time'POS(9100 ns)

This attribute returns the position number as an integer. For physical data types, the position
number is the integer value of the base units. Since the base units of the physical data type
"time" are femtoseconds, regardless of the resolution set in ModelSim, the attribute is
returning 9100 nanoseconds converted to femtoseconds:
9,100 ns => 9,100,000,000 fs

An integer is guaranteed only to have a range of -2,147,483,647 to +2,147,483,647, so the


above converted time value is out of range. With this range restriction, the largest number
we can pass to the attribute is 2147 nanoseconds.
To make the code run, you need to either limit the size of the value passed to the function
or scale that value. For example, you can divide the input to the attribute by 1000, thereby
allowing you to pass larger numbers. Then just multiply the returned value from the
attribute by a 1000 before using it.

ModelSim Technote Library

16

Tool usage

Out-of-range error message


You may encounter unexpected "out of range" error messages from code that runs through
synthesis or other simulators without any problems. Consider the following signal
declaration and a process that references the signal:
SIGNAL cnt : integer RANGE 0 TO 7;

PROCESS (clk)
BEGIN
IF (rst = '1') THEN
cnt <= 0;
ELSIF clk'EVENT AND clk = '1' THEN
cnt <= cnt + 1;
IF (cnt = 7) THEN
cnt <= 0;
END IF;
END IF;
END PROCESS;

When running the design, the following error message is reported:


# ** Fatal: Value 8 is out of range 0 to 7

Though the error is valid, you may not want to see it. To turn off run-time range checking,
use the following argument during compilation:
vcom -nocheck range_check.vhd

ModelSim Technote Library

Case choice error: "must be a locally static expression"

17

Case choice error: "must be a locally static expression"


You may encounter this error message from code that compiles fine in other simulators.
Consider this code snippet:
ARCHITECTURE behavioral OF test IS
CONSTANT label1 : std_logic_vector(3 DOWNTO 0) := "11" & "11";
CONSTANT label2 : std_logic_vector(3 DOWNTO 0) := "0011";
BEGIN
reg : PROCESS (clk,a,b)
BEGIN
IF clk'EVENT AND clk = '1' THEN
CASE a IS
WHEN label1 => c <= b;
WHEN label2 => c <= '0';
WHEN OTHERS => NULL;
END case;
END IF;
END PROCESS reg;
END behavioral;

ModelSim produces the following error when compiling the code:


ERROR: test.vhd(21): Case choice must be a locally static expression.

Why does this code compile error free in other simulators?


Some simulators allow the use of certain constants that we feel are not really locally static
according to the LRM. Using the following constant as a case choice results in an ERROR
in the ModelSim compiler:
CONSTANT label1 : std_logic_vector(3 DOWNTO 0) := "11" & "11";

However, since using these constants does not adversely affect the simulation, we have
implemented the -nocasestaticerror argument to vcom to disable this checking and make
code using these constants compatible between simulators.

ModelSim Technote Library

18

Language

Language
Delta delays
Event-based simulators such as ModelSim may process many events at a given simulation
time. Multiple signals may need updating, statements that are sensitive to these signals
must be executed, and any new events that result from these statements must then be
queued and executed as well. The steps taken to evaluate the design without advancing
simulation time are referred to as "delta times" or just "deltas."
The exact event queuing process varies for Verilog and VHDL. See "Event ordering in
Verilog designs" (20) for details on Verilog. The diagram below represents the process for
VHDL. This process continues until the end of simulation time.

Execute
concurrent
statements at
current time

Advance
simulation
time

Advance
delta time

No

Any transactions
to process?
Yes
Any events to
process?

No

Yes
Execute concurrent
statements that are
sensitive to events

This mechanism in event-based simulators may cause unexpected results. Consider the
following code snippet:
.
.
.
clk2 <= clk;
process (rst, clk)
begin
if(rst = '0')then
s0 <= '0';
elsif(clk'event and clk='1') then
s0 <= inp;

ModelSim Technote Library

Delta delays

19

end if;
end process;

process (rst, clk2)


begin
if(rst = '0')then
s1 <= '0';
elsif(clk2'event and clk2='1') then
s1 <= s0;
end if;
end process;
.
.
.

In this example you have two synchronous processes, one triggered with clk and the other
with clk2. To your surprise, the signals change in the clk2 process on the same edge as they
are set in the clk process. As a result, the value of inp appears at s1 rather than s0. What is
going on?
Here is whats happing. During simulation an event on clk occurs (from the testbench).
From this event ModelSim performs the "clk2 <= clk" assignment and the process which
is sensitive to clk. Before advancing the simulation time, ModelSim finds that the process
sensitive to clk2 can also be run. Since there are no delays present, the effect is that the
value of inp appears at s1 in the same simulation cycle.
In order to get the expected results, you must do one of the following:
1 insert delay at every output
2 make certain to use the same clock
3 insert a delta delay
To insert a delta delay, modify the code like this:
process (rst, clk)
begin
if(rst = '0')then
s0 <= '0';
elsif(clk'event and clk='1') then
s0 <= inp;
s0_delayed <= s0;
end if;
end process;
process (rst, clk2)
begin
if(rst = '0')then
s1 <= '0';
elsif(clk2'event and clk2='1') then
s1 <= s0_delayed;
end if;
end process;

The best way to debug delta delay problems is observe your signals in the List window.
There you can see how values change at each delta time.

ModelSim Technote Library

20

Language

Event ordering in Verilog designs


Event-based simulators such as ModelSim may process multiple events at a given
simulation time. The Verilog language is defined such that you cannot explicitly control the
order in which simultaneous events are processed. Unfortunately, some designs rely on a
particular event order, and these designs may behave differently than you expect.

Event queues
Section 5 of the IEEE Std 1364-1995 LRM defines several event queues that determine the
order in which events are evaluated. At the current simulation time, the simulator has the
following pending events:
active events
inactive events
non-blocking assignment update events
monitor events
future events
- inactive events
- non-blocking assignment update events
The LRM dictates that events are processed as follows 1) all active events are processed;
2) the inactive events are moved to the active event queue and then processed; 3) the
non-blocking events are moved to the active event queue and then processed; 4) the monitor
events are moved to the active queue and then processed; 5) simulation advances to the next
time where there is an inactive event or a non-blocking assignment update event.
Within the active event queue, the events can be processed in any order, and new active
events can be added to the queue in any order. In other words, you cannot control event
order within the active queue. The example below illustrates potential ramifications of this
situation.
Say you have these four statements:
1 always@(q) p = q;
2 always @(q) p2 = not q;
3 always @(p or p2) clk = p and p2;
4 always @(posedge clk)
and current values as follows: q = 0, p = 0, p2=1

ModelSim Technote Library

Event ordering in Verilog designs

21

The tables below show two of the many valid evaluations of these statements. Evaluation
events are denoted #, where # is the statement to be evaluated. Update events are denoted
<name>(old->new) where <name> indicates the reg being updated and new is the updated
value.

Table 1: Evaluation 1
Event being processed

Active event queue


q(0 1)

q(0 1)

1, 2

p(0 1), 2

p(0 1)

3, 2

clk(0 1), 2

clk(0 1)

4, 2

p2(1 0)

p2(1 0)

clk(1 0)

clk(1 0)

<empty>

Table 2: Evaluation 2
Event being processed

Active event queue


q(0 1)

q(0 1)

1, 2

p(0 1), 2

p2(1 0), p(0 1)

p(0 1)

3, p2(1 0)

p2(1 0)

<empty> (clk doesnt change)

Again, both evaluations are valid. However, in Evaluation 1, clk has a glitch on it; in
Evaluation 2, clk doesnt. This indicates that the design has a zero-delay race condition on
clk.

ModelSim Technote Library

22

Language

Controlling event queues with blocking/non-blocking assignments


The only control you have over event order is to assign an event to a particular queue. You
do this via blocking or non-blocking assignments.
Blocking assignments
Blocking assignments place an event in the active, inactive, or future queues depending on
what type of delay they have:
a blocking assignment without a delay goes in the active queue
a blocking assignment with an explicit delay of 0 goes in the inactive queue
a blocking assignment with a non-zero delay goes in the future queue
Non-blocking assignments
A non-blocking assignment goes into either the non-blocking assignment update event
queue or the future non-blocking assignment update event queue. (Non-blocking
assignments with no delays and those with explicit zero delays are treated the same.)
Non-blocking assignments should be used only for outputs of flip-flops. This insures that
all outputs of flip-flops do not change until after all flip-flops have been evaluated.
Attempting to use non-blocking assignments in combinational logic paths to remove race
conditions may only cause more problems. (In the preceding example, changing all
statements to non-blocking assignments would not remove the race condition.) This
includes using non-blocking assignments in the generation of gated clocks.
The following is an example of how to properly use non-blocking assignments.
gen1: always @(master)
clk1 = master;
gen2: always @(clk1)
clk2 = clk1;
f1 : always @(posedge clk1)
begin
q1 <= d1;
end
f2:
always @(posedge clk2)
begin
q2 <= q1;
end

If written this way, a value on d1 always takes two clock cycles to get from d1 to q2.
If you change clk1 = master and clk2 = clk1 to non-blocking assignments or q2 <= q1 and
q1 <= d1 to blocking assignments, then d1 may get to q2 is less than two clock cycles.

Debugging event order issues


Since many models have been developed on Verilog-XL, ModelSim tries to duplicate
Verilog-XL event ordering to ease the porting of those models to ModelSim. However,
ModelSim does not match Verilog-XL event ordering in all cases, and if a model ported to
ModelSim does not behave as expected, then you should suspect that there are event order
dependencies.

ModelSim Technote Library

Event ordering in Verilog designs

23

ModelSim helps you track down event order dependencies with the following compiler
arguments: -compat, -hazards, and -keep_delta.
See the vlog command for descriptions of -compat and -keep_delta.
Hazard detection
The -hazard argument to vsim detects event order hazards involving simultaneous reading
and writing of the same register in concurrently executing processes. vsim detects the
following kinds of hazards:
WRITE/WRITE:
Two processes writing to the same variable at the same time.
READ/WRITE:
One process reading a variable at the same time it is being written to by another process.
ModelSim calls this a READ/WRITE hazard if it executed the read first.
WRITE/READ:
Same as a READ/WRITE hazard except that ModelSim executed the write first.
vsim issues an error message when it detects a hazard. The message pinpoints the variable
and the two processes involved. You can have the simulator break on the statement where
the hazard is detected by setting the break on assertion level to error.
To enable hazard detection you must invoke vlog command with the -hazards argument
when you compile your source code and you must also invoke vsim with the -hazards
argument when you simulate.
Limitations of hazard detection
Reads and writes involving bit and part selects of vectors are not considered for hazard
detection. The overhead of tracking the overlap between the bit and part selects is too
high.
A WRITE/WRITE hazard is flagged even if the same value is written by both processes.
A WRITE/READ or READ/WRITE hazard is flagged even if the write does not modify
the variable's value.
Glitches on nets caused by non-guaranteed event ordering are not detected.

ModelSim Technote Library

24

Language

Verilog simulator resolution


Simulator resolution in Verilog is set using the `timescale compiler directive:
`timescale time_unit / time_precision

The Verilog LRM 1364-2001 defines the arguments of the directive as follows:
"The time_unit argument specifies the unit of measurement for times and delays."
"The time_precision argument specifies how delay values are rounded before being used
in simulation. The values used are accurate to within the unit of time specified here, even
if there is a smaller time_precision argument elsewhere in the design. The smallest
time_precision argument of all the `timescale compiler directives in the design
determines the precision of the time unit of the simulation."
Here is an example of a `timescale directive:
`timescale 1 ns / 100 ps

This directive causes time values to be read as ns and to be rounded to the nearest 100 ps.

Problems with timescale directives


Problems may arise if a timescale is absent or its behavior is misunderstood. Furthermore,
different simulators may have different implementations thereby causing further confusion.
To avoid problems, all files should include timescale directives with the correct values.
The examples below demonstrate two common problems that arise from missing or
incorrect timescale directives. Note that this behavior may not be the same in all simulators.
Example 1
In ModelSim, files without timescales inherit the simulator resolution for both time_unit
and time_precision. Consider a design with the following structure:
missing_tb
dut_1 (mod1)
dut_2 (mod2)
Instance dut1 does not have a timescale. Instance dut2 and the testbench missing_tb have
the following timescale directive:
`timescale 1 ns / 10 ps

The smallest time precision in all timescale directives is 10 ps, so in accordance with the
LRM, the simulator uses that value for its resolution. Since instance dut1 does not have a
timescale directive, it inherits the simulator resolution of 10 ps for time_unit and
time_precision. This equates to dut1 having the following timescale directive:
`timescale 10 ps / 10 ps

ModelSim Technote Library

Verilog simulator resolution

25

Now assume that instance mod1 contains the following code fragment:
parameter d = 1.55;
initial
begin
set = 1'bz;
#d set = 1'b0;
#d set = 1'b1;
end

Parameter d has a time value of 1.55. Due to the inheritance, 1.55 is seen as a delay of 15.5
ps rounded to 20 ps. Consequently, signal set toggles from '0' to 'z' after 20 ps and then to
'1' after 20 ps more.
This is most likely not the intended behavior. You probably assumed the time would be
seen as a 1.55 ns delay, and, with a 10 ps resolution, would be rounded to 1550 ps.
To highlight this potential error, ModelSim reports the following warning during
elaboration of the example design:
# WARNING: [TSCALE] - Module 'mod1' has a `timescale directive in effect, but
previous modules do not

This message is often ignored or disabled during simulation. However, the warning points
out a situation like that in the example above and should ALWAYS be checked.
Example 2
Per the LRM, ModelSim uses the time_precision argument to round delay values in the file
in which it is specified. This is true even if that number is not used in setting simulator
resolution.
Consider a design with a testbench mem_tb containing the following timescale directive:
`timescale 1 ns / 1 ps

Module sp_syn_ram instantiated in the testbench contains this timescale directive:


`timescale 1 ns / 10 ps

Since 1 ps is the smaller of the two time precision values, 1 ps is used for the simulator
resolution. However, module sp_syn_ram has the following code fragment initializing a
memory:
repeat (`MEMDEPTH)
begin
#0.001 mem[init] = 8'h00;
init = init + 1;
end

The time_unit for this module is 1 ns, so ModelSim reads the delay in the repeat statement
as 1 ps. Using the 10 ps time_precision for rounding, ModelSim rounds the 1 ps delay to
zero. Once the delay is rounded to zero, all iterations of the repeat statement occur in one
time step. If the value of MEMDEPTH is greater than the value set for iteration loop limits,
the following message is issued during a simulation run:
# Iteration limit reached. Possible zero delay oscillation. See the manual.

Increasing the iteration loop limit to a number greater than MEMDEPTH allows simulation
to proceed, but that ignores the real issue and still does not produce the intended results.

ModelSim Technote Library

26

Language

The real solution is to use the correct timescale directive (`timescale 1 ns / 1 ps) for module
sp_syn_ram. The delay is then read as 1 ps, and ModelSim iterates over the repeat
statement in real time instead of many delta steps.

ModelSim Technote Library

Hierarchical references in a mixed-language design

27

Hierarchical references in a mixed-language design


This example shows how hierarchical references can work in a mixed-language design.
VHDL does not allow hierarchical references, but they can work in a mixed environment
provided the following conditions are met:
The referenced net and the hierarchical reference are both located in Verilog modules.
The module containing the referenced net is elaborated before the module containing the
hierarchical reference.
For example, consider the following design hierarchy:
tb (VHDL)
dut1 (Verilog)
mod_a (Verilog)

dut2 (VHDL)
mod_b (Verilog)
tb.dut1.mod_a.im0

The hierarchical reference (tb.dut1.mod_a.im0) in mod_b works provided that dut1 is


elaborated first. To ensure this happens, place the instance of dut1 first in the testbench
source code. If it is placed second in the file, ModelSim reports the following error:
Unresolved reference to 'dut1' in tb.dut1.mod_a.im0

ModelSim Technote Library

28

Language

Incorrect use of VHDL bidirectional ports


An error is often made when dealing with logic like that depicted below:

a
out_1

AND
b

OR

out_2

Consider the associated VHDL code. In this case the compiler reports an error due to a bad
assignment.
--------------------------------------- source: bad_init.vhd
-------------------------------------LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
ENTITY bad_init IS
PORT (
a
: IN std_logic;
b
: IN std_logic;
c
: IN std_logic;
out_1 : OUT std_logic;
out_2 : OUT std_logic
);
END bad_init ;
ARCHITECTURE behavioral OF bad_init IS
BEGIN
out_1 <= a AND b;
-- This is a bad assignment.
out_2 <= out_1 OR c;

The compiler errors on this line.

END behavioral;

The compiler displays the following error:


ERROR: bad_init.vhd(21): Cannot read output: out_1.

ModelSim Technote Library

Incorrect use of VHDL bidirectional ports

29

Addressing the error


People commonly change out_1 to a bidirectional in order to fix the error. However, this
may only exacerbate the problem. Consider the following code:
--------------------------------------- source: bad_change.vhd
-------------------------------------LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
-- out_1 is now a bi-directional port. This fixes the compile
-- error, but creates a bad design with potentially difficult
-- debug problems.
ENTITY bad_change IS
PORT (
a
: IN
std_logic;
b
: IN
std_logic;
c
: IN
std_logic;
out_1 : INOUT std_logic;
out_2 : OUT
std_logic
);
END bad_change ;
ARCHITECTURE behavioral OF bad_change IS
BEGIN
out_1 <= a AND b;
out_2 <= out_1 OR c;
END behavioral;

The code compiles and simulates fine provided no external drivers are applied to the port.
If that happens, though, there is the possibility of bus contention, and debugging can be
difficult.
The correct way to write this piece of code is to assign the first logical operation to a
temporary signal and then use that temporary signal in other operations.
--------------------------------------- source: good_change.vhd
-------------------------------------LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
ENTITY good_change IS
PORT (
a
: IN std_logic;
b
: IN std_logic;
c
: IN std_logic;
out_1 : OUT std_logic;
out_2 : OUT std_logic
);
END good_change ;
ARCHITECTURE behavioral OF good_change IS
SIGNAL temp : std_logic;

ModelSim Technote Library

30

Language

BEGIN
temp

<= a AND b;

-- Using an intermediate temporary signal is the preferred


-- method to fix this problem
out_1 <= temp;
out_2 <= temp OR c;
END behavioral;

Note: The assignment operator ( <= ) is not a "netcon", or simple wire connection as it
appears in the schematic. The VHDL code actually generates a buffered connection.

ModelSim Technote Library

WAIT statementsVHDL vs. Verilog

31

WAIT statementsVHDL vs. Verilog


WAIT statements behave differently in VHDL and Verilog per their definitions in the
respective LRMs. This difference may cause unexpected behavior when switching between
the languages. In particular, confusion may arise when a process in a VHDL design has a
"WAIT UNTIL <expression>;" statement. The simulator seems to execute the wait
statement and then never come back to the process even though the expression is TRUE.
What is happening?

WAIT statements in VHDL


The problem described above typically results from a misinterpretation of how the WAIT
statement behaves in VHDL. The VHDL WAIT statement behaves as follows (VHDL
1076-1993 LRM section 8.1 p.113 line 90):
"The WAIT statement WAIT UNTIL clk ='1'; has semantics identical to:
LOOP
WAIT ON clk;
EXIT WHEN clk = '1';
END LOOP;

because of the rules for the construction of the default sensitivity clause."
In VHDL the expression is checked only after the WAIT statement is executed and there is
an event on any signals in the expression. If the expression is already TRUE upon entering
the WAIT, the semantics are identical to just using WAIT; (LRM sec 8.1 line 95). This
form causes the process to suspend for the remainder of the simulation.

WAIT statements in Verilog


The behavior in VHDL is the opposite of what you expect in Verilog. The Verilog WAIT
statement behaves as follows (Verilog 1364-1995 LRM section 9.7.4 p.117):
begin
wait (!enable) #10 a = b;
end

"If the value of enable is 1 when the block is entered, the wait statement delays the
evaluation of the next statement (#10 a = b;) until the value of enable changes to 0. If
enable is already 0 when the begin-end block is entered, then the assignment "a = b" is
evaluated after a delay of 10 and no additional delay occurs."
In Verilog the expression is checked before the WAIT statement is executed and if TRUE
the wait never occurs.

ModelSim Technote Library

32

Language

Example
Here is an example of a Verilog and a VHDL AND gate. Both of these AND gates have an
enable signal en with a WAIT statement:
// Verilog
always
begin
wait (en) #10 z_v = a & b;
end

-- VHDL
PROCESS
BEGIN
z_vhd <= a AND b AFTER 10 ns;
WAIT UNTIL en = '1';
END PROCESS;

When simulated the Verilog output z_v changes 10 ns after the input a toggles. However,
there is no corresponding toggle on the VHDL output z_vhd. This signal does not toggle
until 10 ns after the enable signal en toggles.
a

b
en
z_vl

z_vhd

ModelSim Technote Library

Verilog tran gate in mixed-language designs

33

Verilog tran gate in mixed-language designs


VHDL does not have an equivalent construct to the Verilog tran gate. When ModelSim
detects a Verilog tran gate in a mixed simulation, it issues the following warning:
# WARNING: tran_gate.v(13): [TRAN] - Verilog net 'a' with bidirectional tran
primitives may not function correctly when connected to a VHDL signal.

This problem occurs in the VHDL language because of the resolution function. You must
model the tran gate behavior in VHDL so the resolution function has time to determine
drivers on the two ports.
Modeling tran gate behavior relies on a concept called "break before make." The code
"breaks" the connection upon sensing a transaction on either port by driving a 'Z' onto both
ports. This break gives the resolution function time to determine the drivers for each port.
A "WAIT FOR 0 ns" statement helps to insure driver resolution. Finally, the swap signal
assignment performs the "make" operation. The following code demonstrates this
modeling:
tran_gate: PROCESS
VARIABLE last_time : time;
BEGIN
WAIT ON a'TRANSACTION, b'TRANSACTION UNTIL last_time /= NOW;
-- Break
last_time := NOW;
a <= 'Z';
b <= 'Z';
WAIT FOR 0 ns;
-- Make
a <= b;
b <= a;
END PROCESS tran_gate;

There are two restrictions on this model:


1 The input signals to this process (a, b) cannot have multiple transitions during a single
time step. A process is entered only at the start of the time step, and any transactions that
occur on a delta will not be detected. Multiple transitions most likely occur during
gate-level simulation when delays in the gates are present.
2 The value of the data on the ports cannot be a don't care '-'. The model asserts the value
'Z' on the ports to determine the driving values, and the 1164 standard resolves a don't
care with anything but a 'U' to an 'X'.

ModelSim Technote Library

34

Timing and SDF

Timing and SDF


Negative timing check limits
Verilog supports negative limit values in the $setuphold and $recrem system tasks. These
tasks have optional delayed versions of input signals to ensure proper evaluation of models
with negative timing check limits. Delay values for these delayed nets are determined by
the simulator so that valid data is available for evaluation before a clocking signal.

Example
$setuphold(posedge clk, negedge d, 5, -3, Notifier,,, clk_dly, d_dly);;

d violation
region

3
0

clk

ModelSim calculates the delay for signal d_dly as 4 time units instead of 3. It does this to
prevent d_dly and clk_dly from occurring simultaneously when a violation isnt reported.
Note: ModelSim accepts negative limit checks by default, unlike current versions of
Verilog-XL. To match Verilog-XL default behavior (i.e., zeroing all negative timing
check limits), use the +no_neg_tcheck argument to vsim.

Negative timing constraint algorithm


The algorithm ModelSim uses to calculate delays for delayed nets isnt described in IEEE
Std 1364. Rather, ModelSim matches Verilog-XL behavior. The algorithm attempts to find
a set of delays so the data net is valid when the clock net transitions and the timing checks
are satisfied. The algorithm is iterative because a set of delays can be selected that satisfies
all timing checks for a pair of inputs but then causes mis-ordering of another pair (where
both pairs of inputs share a common input). When a set of delays that satisfies all timing
checks is found, the delays are said to converge.
When none of the delay sets cause convergence, the algorithm pessimistically changes the
timing check limits to force convergence. Basically the algorithm zeroes the smallest
negative $setup/$recovery limit. If a negative $setup/$recovery doesn't exist, then the
algorithm zeros the smallest negative $hold/$removal limit. After zeroing a negative limit,
the delay calculation procedure is repeated. If the delays dont converge, the algorithm
zeros another negative limit, repeating the process until convergence is found.

ModelSim Technote Library

Negative timing check limits

35

A simple example helps clarify the algorithm. Assume you have the following timing
checks:
$setuphold(posedge
$setuphold(posedge
$setuphold(posedge
$setuphold(posedge

clk,
clk,
clk,
clk,

posedge
negedge
posedge
negedge

d,
d,
t,
t,

3, -2 ,
6, -5 ,
20, -12
18, -11

NOTIFIER,,, clk_dly, d_dly);


NOTIFIER,,, clk_dly, d_dly);
, NOTIFIER,,, clk_dly, t_dly);
, NOTIFIER,,, clk_dly, t_dly);

The violation regions for t and d in this example are:


t violation
region

d violation
regions

20
18

12
11

3
6

5
0

clk

Note that the delays between clk/clk_dly, t/t_dly, and d/d_dly are not edge sensitive, and
they must be the same for both rising and falling transitions of clk, t, and d. A d => d_dly
delay of 5 satisfies the negedge case (transitions of d from 5 to 0 before clk won't be
latched), but valid transitions of posedge d, in the region of 5 to 3 before clk, won't latch
correctly. Therefore, to find convergence, the algorithm starts zeroing negative $hold
limits (-12, then -11, and then -5). The check limits on t are zeroed first because of their
magnitude.
ModelSim displays messages when limits are zeroed if you use the +ntc_warn argument.
The messages look similar to the following:
# WARNING: ./src/SDFFX.v(36): No solution possible for delayed timing check
nets. Setting negative limit to zero.

Extending check limits without zeroing


If zeroing limits is too pessimistic for your design, you can use the vsim command
arguments -extend_tcheck_data_limit and -extend_tcheck_ref_limit instead. These
arguments cause a one-time extension of qualifying data or reference limits in an attempt
to provide a solution prior to any limit zeroing. A limit qualifies if it bounds a violation
region which does not overlap a related violation region.
An example helps illustrate. Assume you have the following timing checks:
$setuphold( posedge clk, posedge d,
$setuphold( posedge clk, negedge d,

45, 70, notifier,,,dclk,dd);


216, -68, notifier,,,dclk,dd);

The violation regions for d in this example are:

d violation
regions

45
216

70

-68
0

clk

ModelSim Technote Library

36

Timing and SDF

The delay net delay analysis in this case does not provide a solution. The required negative
hold delay of 68 between d and dd could cause a non-violating posedge d transition to be
delayed on dd so that it arrive after dclk for functional evaluation. By default the -68 hold
limit is set pessimistically to 0 to insure the correct functional evaluation.
Alternatively, you can use -extend_tcheck_data_limit to overlap the regions. In this
example we must specify the percentage by which to "decrease" the negative hold limit in
order to overlap the positive setup limit. In other words, you must extend the 216, -68
region to 216, -44. You calculate the percentage as follows:
1 Calculate the size of the negative edge violation region:
216 - 68 = 148
2 Calculate the gap between the negative hold limit and the positive setup limit and add
one timing unit to allow for overlap:
68 - 45 = 23 + 1 = 24
3 Divide the gap size by the violation region size:
24 / 148 = .16
Hence, you set -extend_tcheck_data_limit to 16.
Note: ModelSim extends the limit only as far as is needed to derive a solution. So if you
used 100 in the previous example, it still only extends the limit 16 percent. Indeed, in
some cases it may be easiest to select a large percentage number and not worry about an
exact calculation.

ModelSim Technote Library

Backannotation of interconnect delays

37

Backannotation of interconnect delays


This example shows both path delays and interconnect delays annotated through an SDF
file. The design is an 8-to-1 multiplexer with a testbench. IO path delays are defined for
both the 4-to-1 and 2-to-1 multiplexers. Interconnect delays are defined between the
instantiated multiplexers and from the output of the 2-to-1 MUX to the top-level port z on
the 8-to-1 MUX. The design's structure is as follows:
MUX81
d0
d1

d0
d1

d2
d3

d2
d3

MUX41
z
MUX21
d0
z

MUX41
d4
d5

d4
d5

d6
d7

d6
d7

d1
z

When this design is simulated with the SDF file applied, the simulator reports the following
runtime warning:
# WARNING: mux81.sdf(54): Annotating cell drivers of INTERCONNECT source port

This warning indicates that an interconnect delay from z on MUX21 to the top-level port z
on MUX81 exists and is being annotated. This interconnect delay is a special case and has
to be treated differently from regular interconnect delays in the design. Cadence tools
handle this exactly the same way and produce a very similar warning message.

Explanation
The SDF standard specifies only that interconnect delays can go from a module
output/inout port to a module input/inout port. It does not address the case where
interconnect delays go from a module output port to the top-level output port.
Almost all tools that write SDF files specify delays as ABSOLUTE delays. This means that
when a delay is annotated, it overwrites any existing value. This is to ensure that any default
values defined in the actual cells are replaced with the correct values from the SDF file.
Delays can also be INCREMENT delays, but these are almost never used. These are added
to any existing delay information instead of overwriting them.
As the simulator reads through the SDF file from top to bottom, it finds each instance and
annotates the specified delay to that instance. Since the interconnect delay from the output
of the MUX21 to the output port of the MUX81 is a special case, it does not have a defined

ModelSim Technote Library

38

Timing and SDF

location to put the delay information as do the interconnect delays between the modules and
the path delays through the modules.
Since there is no defined location to store the delay information for this special case, the
delay information is added to any existing path delay information on the MUX21, in effect
ignoring whether or not the delay is INCREMENT or ABSOLUTE for this interconnect
delay. This is how both MTI and Cadence handle this special case.
Because this interconnect delay is being added to the path delay from the MUX21, the
INTERCONNECT line in the SDF file must be AFTER any lines that specify IO path
delays for the MUX21. If it occurs before the IO path lines, the IO path delay overwrites
the interconnect delay. The designer thinks things are being annotated, but he/she is really
losing the final interconnect delay.
Most tools that write SDF files write these special case interconnect delays at the end of the
SDF file since this is how Cadence requires them. However, when this warning is issued,
check that the delay is not lost due to improper placement of the delay in the SDF file.

ModelSim Technote Library

Combining distributed delays and path delays

39

Combining distributed delays and path delays


The following combinatorial cell is created from two Verilog primitives and has distributed
delays on the primitives as noted:

a0
NOR

#3ns

a1

OR

a2

#2ns

z0

There is also a 4 ns path delay in a specify block from a1 to z0. The SDF file contains an 8
ns path delay from a1 to z0. Thus the cell is driven as follows:

a0

a1
a2

z0

XX
A

The delays being observed at the various points on the outputs don't seem to be correct
under various cases:
using +delay_mode_distributed during compile
using +delay_mode_path during compile
using +delay_mode_zero during compile
applying SDF with and without a specify block in the module
Which delay is used?

ModelSim Technote Library

40

Timing and SDF

The distributed delays and the path delays are independent of each other. Distributed delays
are placed on the output driver for each primitive. Path delays are placed on a special driver
created during the compile when a specify block is present.
For distributed delays, the delays are assigned as signals propagate through the primitives.
This means that the logic of the circuit affects the delay value seen on the output. For
example consider the diagrams on the previous page:
The change in the output occurring at point B could be caused by the change on the a1
input or the a2 input. Before the toggle, the values seen on the OR gates inputs are (1,1).
Both a1 and a2 inputs change at the same time. The change from a2 is seen immediately
on the input to the OR gate. However, the value of (1,0) into the OR gate does not cause
the output to change. The change in a1 causes the output of the NOR gate to change, but
only after the 3 ns delay. Therefore, the 0 from the NOR gate arrives at the input to the
OR gate after 3 ns. This makes the value on the inputs to the OR gate (0,0), causing a
change on its output after another 2 ns delay. This creates the observed delay of 5 ns (3
+ 2) at point B on the output.
The change in the output at point F looks similar to the change at point B (both a1 and
a2 inputs change together). However, the delay seen here is only 2 ns. The difference
exists because the a0 input is now 1 and any change in the a1 input has no affect on the
NOR gates output.
When a specify block is present in the module, a special driver is created for the delay.
Essentially a break is created between the output of the primitive and the output of the
module:

OR

z0
A

The primitive retains its drivers so any distributed delays are still seen at point A of the
break. If a change occurs at point A, the following steps are used to determine when to
schedule the assignment of the value at point A to point B:
1 Only ENABLED paths to the output are considered. This means a conditional path delay
is considered only if the condition is true.
2 The input change time for each of these paths is examined, and the delay for the input
with the latest time is used.
3 If multiple paths have the same input change time, the one with the shortest delay path
is used.
The delay is determined by computing the difference between the time the input changed
and the time the output at point A changed. If only path delays are used, that difference is
zero. The value at point A is then scheduled for assignment to point B after the computed
delay value has elapsed.
However, when distributed delays are present with path delays, the difference is not
necessarily zero. If the difference is 2 ns and the path delay is determined to be 4 ns, then
the scheduled assignment of point A to point B will be 2 ns in the future. It is also possible
for the calculated difference to be negative. In this case the scheduled assignment will be
immediate, essentially setting the path delay to zero.

ModelSim Technote Library

Combining distributed delays and path delays

41

This situation is caused by the distributed delays being larger than the path delays. As a
general rule, distributed delays should always be smaller than any path delays.
When trying to determine the delay when both path and distributed delays are present, the
rule to apply is described in the Verilog LRM (Section 13.5):
"If a module contains path delays and distributed delays, the larger of the two delays for
each path shall be used."
ModelSim provides various compiler arguments to turn delays on and off. The
+delay_mode_distributed basically removes the specify block so any path delays are no
longer present. The +delay_mode_path sets all distributed delays to zero. The
+delay_mode_zero does both.
The application of an SDF file modifies the values of path delays and the calculation done
to this point still apply. However, if an SDF file is applied to a cell that contains primitives
and no specify block (or one that has been compiled with the +delay_mode_distributed
macro), a delay is still annotated to the output driver of the last primitive.
This delay is now seen as a distributed delay since it is being annotated to the same location
as the distributed delay. Whether or not it overwrites any values already there depends on
whether the delay type in the SDF file is ABSOLUTE or INCREMENT. Most path delays
in SDF files are ABSOLUTE. ABSOLUTE delay types overwrite any existing values.
In this example, if the SDF file with an 8 ns delay is annotated to the module, and that
module does not have a specify block, the result is a 3 ns delay through the NOR gate and
an 8 ns delay through the OR gate (overwriting the original 2ns delay). The delay at point
B on the timing diagram is 11 ns (3 + 8), just as it was 5 ns (3 + 2) in the above example
without the SDF file.
An SDF file may describe multiple delay paths through a module. If this SDF file is applied
to a module with no specify block, a choice must be made about which path gets annotated
to the one available location. The path that is selected is the last path listed in the SDF file,
because the annotation occurs line-by-line. If the module in the above example had path
delays for inputs A, B, and C defined in that order in the SDF file, each is annotated in turn
to the one available location. If these are ABSOLUTE delays, each overwrites the previous
value, and the delay value from a2 to z0 will be the remaining value.

ModelSim Technote Library

42

Timing and SDF

Glitch filtering
This tech note discusses On-Detect and On-Event glitch filtering. On-Detect filtering is not
supported before the IEEE 1364-2001 standard. On-Event filtering is the default for
Verilog.
The following timing diagram shows an input (a) and output (z) to a buffer that has a 4 ns
delay.

a
6

z (On-Event)

10

12

z (On-Detect)
8

12

There are three methods for setting pulse filtering:


in a specify block specparam PATHPULSE$a$z = (0,6);
on the simulator command line +pulse_r/0 +pulse_e/100
from an SDF file
If you specify both PATHPULSE$ and a command line argument, the PATHPULSE$
values take precedence. The values specified from the command line are treated as a
percentage of the path delay. The above plusargs for the command line catch all pulses less
than the path delay and cause Xs on the output.
The modes On-Event (default) and On-Detect can be set in the specify block or from the
command line:
pulsestyle_ondetect z;
pulsestyle_onevent z;
+pulse_e_style_ondetect
+pulse_e_style_onevent
The pulse style invocation options take precedence over the pulse style specify block
declarations.
When the rise/fall delays in a path delay are unequal, it is possible for the trailing edge of
a pulse to be scheduled for a time earlier than the schedule time of the leading edge. This
causes a pulse with a negative width. Normally this transition is never seen. However, it is
possible to represent these negative width pulses with Xs using the "showcancelled" option.
This can also be defined in a specify block or from the command line:
showcancelled z;
+show_cancelled_e

ModelSim Technote Library

Glitch filtering

43

For example, if the above buffer had a rise/fall delay specified as 4/7, the trailing edge (B)
is scheduled for an earlier time than the leading edge (A):

No showcancelled:
12 13

z (default)

Showcancelled:
z (On-Event)

z (On-Detect)
8

13

ModelSim Technote Library

44

Timing and SDF

IOPATH delayVITAL vs. Verilog


IOPATH delays may be handled different in VITAL than in Verilog. The reason stems
from the different algorithms used to select delay.
VITAL uses the soonest path delay. If a particular value is already scheduled on the output
and a change on an input causes the same value to be scheduled sooner, then VITAL causes
the output to change sooner.
Verilog uses a more simplistic algorithm. If a particular value is already scheduled on the
output and a change on an input causes the same value to be scheduled, Verilog simply
checks that the new value is the same as the previously scheduled value and then throws
away the new event.
Though simulation results may be the same in many cases, there are some cases where the
results differ. The following example illustrates such a case.
Assume you have the following two-input AND gate:
---- entity declaration
entity and_gate is
generic( :
:
:
);

-----

port (
O : out STD_ULOGIC;
I1: in STD_ULOGIC;
I0: in STD_ULOGIC);
attribute VITAL_LEVEL0 of and_gate : entity is TRUE;
end and_gate;

and the following SDF:


(TIMESCALE 1ps)
:
(IOPATH I1 O (100)
(IOPATH I0 O (200)
:

ModelSim Technote Library

(100))
(200))

IOPATH delayVITAL vs. Verilog

45

Looking at the waveforms after simulation, you see the following:


0ps

300ps

350ps

I0

I1

450ps

500ps

O (VITAL)

O (Verilog)

As you can see from this result, VITAL used the I1=>O path delay, and Verilog used the
I0=>O path delay.

ModelSim Technote Library

46

Timing and SDF

Interconnect delay on X transitionsVITAL vs. Verilog


Delay selection for transitions involving X can be different for VITAL and Verilog. For
VITAL, section 9.2 in IEEE Std 1076.4-1995 states that a 0-X transition selects the rising
delay. For Verilog, the LRM does not cover SDF annotation. However, when you annotate
an interconnect delay in Verilog, ModelSim creates a primitive on the input that behaves
just like a regular Verilog primitive. In this case, Section 7.15 in IEEE Std 1364-1995 states
that a 0-X transition selects the minimum of the rising and falling delays.
This difference may produce unexpected results. Consider a design like the following:
TOP (VHDL) test
H01

c_2
Buffer
(VITAL)

N01

tbi0

c_1
(VHDL)

TBI0

c_1_V
(Verilog)

with INTERCONNECT delay as follows.


(INTERCONNECT C_2/N01 C_1/TBI0 (32:57:113)(29:56:107))
(INTERCONNECT C_2/N01 C_1_V/TBI0 (32:57:113)(29:56:107))

Looking at the waveforms after simulation, youd see something like the following:
617ps
/test/c2/N01
730ps
/test/c1/tbi0_dly
724ps
/test/c1_V/TBI0_dly

The delay from N01 to c_1/tbi0 is 113 ps, but for N01 to c_1_V/TBI0 it is only 107 ps. This
is expected behavior.
Note that if you use the +transport_int_delays argument to vsim, then interconnect delays
will behave more like path delays, and the delay selection will behave the same for VITAL
and Verilog. Refer to 13.4.2 in IEEE Std 1364-1995 for details.

ModelSim Technote Library

Using the RECREM timing check with VITAL cells

47

Using the RECREM timing check with VITAL cells


In ModelSim versions prior to 5.6, the simulator may report timing violations related to
RECREM checks that appear to be incorrect. Say a cell has the following timing:

CLK

PB
98ps
Recovery
97ps
Removal
121ps
and the following timing check is in the SDF file:
(RECREM (posedge PB) (posedge CLK) (0.097) (0.121))

ModelSim would return the warning:


Warning: dut RECOVERY High VIOLATION ON PB WITH RESPECT TO CLK;
Expected := 1 ns; Observed := 0.098 ns; At : 8800.005 ns

The 98 ps transition is outside the timing window, so a violation message should not be
reported. And, the warning does not occur if the timing check is split into two separate
entries:
(RECOVERY (posedge PB) (posedge CLK) (0.097))
(REMOVAL (posedge PB) (posedge CLK) (0.121))

Why then is an error reported for the RECREM entry?


Though the RECREM check is part of the SDF 3.0 standard (a standard ModelSim
supports), the combination RECREM check is not a part of the 1995 VITAL spec, and the
version of SDF that VITAL 1995 is based on does not support it either. Therefore, it is not
supported in 5.5 and earlier versions of ModelSim VITAL.
The VITAL 2000 spec specifies SDF 4.0 and explicitly calls out mappings for RECREM.
VITAL 2000 and the RECREM timing check is supported beginning with ModelSim 5.6.

ModelSim Technote Library

48

Platform

Platform
NFS problems with Red Hat 7.0, 7.1, and 7.2
Red Hat releases 7.0, 7.1, and 7.2 cause an error when running a Verilog design across a
network. This error occurs only when the library is located on an NFS remote mounted file
system. ModelSim reports the following error at elaboration:
.
.
Loading work.mem_comp
** Fatal: ERROR: Bad library format
Time: 0 ns Iteration: 0 Region: FATAL ERROR while loading design

This error is related to an NFS problem with these releases that corrupts the *.asm files in
the libraries. The work-around for this problem is to disable NFS caching. This should be
done in the invocation shell by setting the NOMMAP environment variable:
setenv NOMMAP 1

This solution may impact compile times for designs that have large *.asm files.

Window manager bug with early versions of KDE


Early versions of KDE cause the top and left-side ModelSim GUI frames to "disappear."
This is an X-server problem where the (0,0) position for the window is actually up and to
the left of the physical screen. This causes ModelSim to be shifted up and left to the point
that the frame is no longer visible.
There a couple of fixes/work-arounds:
Set the following variable in the .modelsim file located at $HOME:
wnBug = 3

Move the window and then save a preference file


Every ModelSim window has a square box in the lower right corner. Position the cursor
over this box so it changes to a "cross-hair", then click-and-drag the window down and
to the right.
Once you move the window, save a preference file so that ModelSim comes up in that
position at every invocation. To create the preferences file:
1 Move the window to the desired spot
2 Select the pulldown menu Tools > Save Preferences...
3 Save the preferences
This creates a modelsim.tcl file that ModelSim loads upon invocation. You need to place
this file in each directory from which ModelSim will be invoked.

ModelSim Technote Library

Memory addressing above 2GB on an HP platform

49

Memory addressing above 2GB on an HP platform


By default only ~1.5 GB memory is available for processes on 32-bit HP platforms. You
must change the default attributes in order to access addressing space up to the 4GB limit.
You can do this with the following change attribute command:
chatr +q4p enable +q3p enable ./vsim

The 4p command provides addressing into the 3-4GB block, and the 3p provides addressing
into the 2-3GB block. The 4p command is supported by 11.11 and 11.i.

Problems loading an FLI/PLI compiled on HP-UX 11.0


When trying to load a design with an FLI on an HP-UX 11.0 machine, ModelSim reports
the following error, and the shared library for the FLI fails to load:
# Load ./and.sl unsuccessful: Exec format error
# ERROR: Failed to load FLI object file "./and.sl"

The following message is also being printed in the shell window:


/usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage:
/usr/lib/libc.2

This design runs fine on HP-UX 10.20 as well as other platforms. What is wrong?
This problem occurs during the linking of the FLI/PLI. The older HP-UX platforms require
the -lc switch during the linking:
ld -b -o app.sl app.o -lc

On HP-UX 11.0, this switch causes the incorrect version of the standard C library to be
loaded with the design. The "Exec format error" message is the most obvious clue that this
is the problem. Use the following command line instead on HP-UX 11.0:
ld -b -o app.sl app.o

ModelSim Technote Library

50

Platform

Problems when linking a PLI application on Windows


When trying to link a PLI application with the following command:
link -dll -export:init_usertfs hello.obj C:\modeltech\win32\mtipli.lib

ModelSim reports the following link error:


LINK : fatal error LNK1104: cannot open file "LIBC.lib"

The library LIBC.lib is a general purpose library that contains many common C functions
(printf, etc.). This error most likely occured because the directory containing this library is
not mapped correctly.
When Visual C is setup, an environment variable called "lib" is created. This variable
should point at the directory that contains the LIBC.lib library file. For example:
lib = "C:\Program Files\Microsoft Visual Studio\VC98\lib"

Another common problem on Windows machines is when users try to use GNU compilers.
These compilers do not create Windows DLLs correctly. Any applications compiled and
linked with these compilers do not work correctly in ModelSim.

RPC_Init error on HPUX


When trying to invoke the ModelSim GUI on HP-UX, you see the following error:
RPC_Init: TCL_ERROR: couldn't open socket: host is unreachable
Trouble making server
vsim: No IPC channel!
Error in startup script: Initialization problem, exiting.
while executing "ncFyP12 "
(file "/apps/sims/modeltech/bin/../hp700/../tcl/vsim/vsim.op_" line 1)
Trouble with U/I. vsim is exiting with code 18

When ModelSim starts up, it tries to open a socket on the host machine. As stated in the
first line of the message, ModelSim couldnt open a socket.
This error most likely results from not having a "localhost" defined on your system.
Systems must have a localhost setup in their /etc/hosts file (or equivalent) to run the
ModelSim GUI. The first line in this file should be:
127.0.0.1

localhost loopback

Without this line you should not be able to ping localhost. The following command should
return the localhost and the correct address, 127.0.0.1:
/usr/sbin/ping localhost

Even though ping works, the host may still be unreachable. A second thing to try is to run
ifconfig lo and verify that this also contains the correct address for localhost. The key is to
make certain that the localhost is reachable, or ModelSim will never start.

ModelSim Technote Library

S-ar putea să vă placă și