Вы находитесь на странице: 1из 29

TIME SCALE AND PRECISION

Delay unit is specified using 'timescale, which is declared as `timescale time_unit


base / precision base
--time_unit is the amount of time a delay of #1 represents. The time unit must be 1
10 or 100
--base is the time base for each unit, ranging from seconds to femtoseconds, and
must be: s ms us ns ps or fs
--precision and base represent how many decimal points of precision to use relative
to the time units.
For example : `timescale 1 ns / 100 ps means
time values to be read as ns and to be rounded to the nearest 100 ps.
If timescale is omitted, there is a default time scale.
The following examples demonstrate how the time scale and time precision effect
$stime, #delay and toggling in waveform.
EXAMPLE:
`timescale 10ns/10ns
module tim();
reg i;
initial
begin
i=0;
#7.7212;
i=1;
$display("STATEMENT 1 :: time is ",$stime);
#7.123;
$finish;
end
endmodule
module try;
time delay_time = 7.721;
initial begin
$display("STATEMENT 2 :: delay for %0t",delay_time );
end
endmodule
RESULTS: STATEMENT 1 :: time is 8
STATEMENT 2 :: delay for 8

reg i toggled at 80 in waveform debugger


EXAMPLE:
`timescale 10ns/1ns
module tim();
reg i;
initial
begin
i=0;
#7.7212;
i=1;
$display("STATEMENT 1 :: time is ",$stime);
#7.123;
$finish;
end
endmodule
module try;
time delay_time = 7.721;
initial begin
$display("STATEMENT 2 :: delay for %0t",delay_time );
end
endmodule
RESULTS:
STATEMENT 1 :: time is 8
STATEMENT 2 :: delay for 80
reg i toggled at 77 waveform debugger
EXAMPLE:
`timescale 10ns/1ps
module tim();
reg i;
initial
begin
i=0;
#7.7212;
i=1;
$display("STATEMENT 1 :: time is ",$stime);
#7.123;
$finish;
end

endmodule
module try;
time delay_time = 7.721;
initial begin
$display("STATEMENT 2 :: delay for %0t",delay_time );
end
endmodule
RESULTS:
STATEMENT 1 :: time is 8
STATEMENT 2 :: delay for 80000
reg i toggled at 77.212 in waveform debugger
In the timescale statement, the first value is the time unit and the second is the
precision for the simulation. So with the time unit, when the simulator displays a
value, you just have to multiply the value by this time unit to get the real time. With
a 10ns time unit, when a delay of #7.7212, that means that it is 77.212ns delay.
Now the second one (time precision) specify with which precision time values are
rounded. Asking for a 77.212ns delay is possible only with a 1ps precision. That's
what you can see with reg i. It toggles at 77ns with a 1ns precision and 77.212 with
a 1ps precision.
For the STATEMENT 1, $stime returns an integer scaled to timesale unit, that's why
results are always 8 which is 7.7212 rounded up to 8.
Now for STATEMENT 2, the way %t is printed depends on $timeformat. It seems that
in this case, 7.7212 is first rounded to an integer => 8 and then printed according
to your time precision.
Each module can have separate time scale. The smallest time_precision argument
of all the timescale compiler directives in the design determines the precision of the
time unit of the simulation.
Lets take an example. There are two modules. Module_1 is instance od Module_2.
Module_1 has timescale of 1 ns/1ps. Module_2 has time scale of 1ns / 10ps. The
smallest resolution is 1ps. This is taken as simulator resolution but each module
evaluates according to its precision mentioned.
Lets take another example. There are two modules. Module_1 is instance of
Module_2. Module_1 does not have any time scale. Module_2 is having time scale of
1ns/100 ps. As there is no time scale for Module_1 ,the simulator takes precision

and time unit of 100 ps i.e `timescale 100 ps/100 ps.


$Time Vs $Realtime
$time round offs the time to nearby integer where as $realtime does not. So when
you are using real valued delays, then use $realtime instead of $time , else there
may be a misunderstanding during debugging.
System Task Printtimescale
The $printtimescale system task displays the time unit and precision for a particular
module. When no argument is specified, $printtimescale displays the time unit and
precision of the module that is the current scope. When an argument is specified,
$printtimescale displays the time unit and precision of the module passed to it.
EXAMPLE:
`timescale 1 ms / 1 us
module a_dat;
initial
$printtimescale(b_dat.c1);
endmodule
`timescale 10 fs / 1 fs
module b_dat;
c_dat c1 ();
endmodule
`timescale 1 ns / 1 ns
module c_dat;
endmodule
RESULTS: Time scale of (b_dat.c1) is 1ns / 1ns
System Task Timeformat
The $timeformat system task performs the following two functions:
1)It specifies how the %t format specification reports time information for the
$write, $display,$strobe, $monitor, $fwrite, $fdisplay, $fstrobe, and $fmonitor group
of system tasks.
2)It specifies the time unit for delays entered interactively.
The units number argument shall be an integer in the range from 0 to -15. This
argument represents the time
unit as shown in table
Unit number Time unit Unit number Time unit
0
1 s
-8
10 ns

-1
-2
-3
-4
-5
-6
-7

100 ms
10 ms
1 ms
100 us
10 us
1 us
100 ns

-9
-10
-11
-12
-13
-14
-15

1 ns
100 ps
10 ps
1 ps
100 fs
10 fs
1 fs

Syntax : $timeformat(time unit, precision number, suffix string, and minimum field
width);
EXAMPLE:
`timescale 1 ms / 1 ns
module cntrl;
initial
$timeformat(-9, 5, " ns", 10);
endmodule
`timescale 1 fs / 1 fs
module a1_dat;
reg in1;
integer file;
buf #10000000 (o1,in1);
initial begin
file = $fopen("a1.dat");
#00000000 $fmonitor(file,"%m: %t in1=%d o1=%h", $realtime,in1,o1);
#10000000 in1 = 0;
#10000000 in1 = 1;
end
endmodule
RESULTS:
a1_dat: 0.00000 ns in1= x o1=x
a1_dat: 10.00000 ns in1= 0 o1=x
a1_dat: 20.00000 ns in1= 1 o1=0
a1_dat: 30.00000 ns in1= 1 o1=1
EXAMPLE:
`timescale 1 ms / 1 ns
module cntrl;
initial
$timeformat(-9, 5, " ns", 10);
endmodule

`timescale 1 ps / 1 ps
module a2_dat;
reg in2;
integer file2;
buf #10000 (o2,in2);
initial begin
file2=$fopen("a2.dat");
#00000 $fmonitor(file2,"%m: %t in2=%d o2=%h",$realtime,in2,o2);
#10000 in2 = 0;
#10000 in2 = 1;
end
endmodule
RESULTS:
a2_dat:
a2_dat:
a2_dat:
a2_dat:

0.00000 ns in2=x o2=x


10.00000 ns in2=0 o2=x
20.00000 ns in2=1 o2=0
30.00000 ns in2=1 o2=1

RACE CONDITION

Verilog is easy to learn because its gives quick results. Although many users are
telling that their work is free from race condition. But the fact is race condition is
easy to create, to understand, to document but difficult to find. Here we will discuss
regarding events which creates the race condition & solution for that.
What Is Race Condition?

When two expressions are scheduled to execute at same time, and if the order of
the execution is not determined, then race condition occurs.

EXAMPLE
module race();
wire p;
reg q;
assign p = q;
initial begin

q = 1;
#1 q = 0;
$display(p);
end
endmodule

The simulator is correct in displaying either a 1 or a 0. The assignment of 0 to q


enables an update event for p. The simulator may either continue or execute the
$display system task or execute the update for p, followed by the $display task.
Then guess what can the value of p ?
Simulate the above code in your simulator. Then simulate the following code .
Statement "assign p = q;" is changed to end of the module.

EXAMPLE
module race();
wire p;
reg q;
assign p = q;
initial begin
q = 1;
#1 q = 0;
$display(p);
end
endmodule

Analyze the effect if I change the order of the assign statement.

Why Race Condition?

To describe the behavior of electronics hardware at varying levels of abstraction,


Verilog HDL has to be a parallel programming language and Verilog simulator and
language itself are standard of IEEE, even though there are some nondeterministic
events which is not mentioned in IEEE LRM and left it to the simulator algorithm,

which causes the race condition. So it is impossible to avoid the race conditions
from the language but we can avoid from coding styles.
Look at following code. Is there any race condition?

EXAMPLE:
initial
begin
in = 1;
out <= in;
end

Now if you swap these two lines:

EXAMPLE
initial
begin
out <= in;
in = 1;
end

Think, is there any race condition created?


Here first statement will schedule a non-blocking update for "out" to whatever "in"
was set to previously, and then "in" will be set to 1 by the blocking assignment. Any
statement whether it is blocking or nonblocking statements in a sequential block
(i.e. begin-end block) are guaranteed to execute in the order they appear. So there
is no race condition in the above code also. Since it is easy to make the "ordering
mistake", one of Verilog coding guidelines is: "Do not mix blocking and nonblocking
assignments in the same always block". This creates unnecessary doubt of race
condition.

When Race Is Visible?

Sometimes unexpected output gives clue to search for race. Even if race condition
is existing in code, and if the output is correct, then one may not realize that there

exists race condition in their code. This type of hidden race conditions may come
out during the following situation.
When different simulators are used to run the same code.
Some times when the new release of the simulator is used.
Adding more code to previous code might pop out the previously hidden race.
If the order of the files is changed.
When using some tool specific options.
If the order of the concurrent blocks or concurrent statements is changed.(One
example is already discussed in the previous topics)
Some simulators have special options which reports where exactly the race
condition is exists. Linting tools can also catch race condition.

How To Prevent Race Condition?

There are many details which is unspecified between simulators. The problem will
be realized when you are using different simulators. If you are limited to design
guidelines then there is less chance for race condition but if you are using Verilog
with all features for Testbench, then it is impossible to avoid. Moreover the language
which you are using is parallel but the processor is sequential. So you cant prevent
race condition.

Types Of Race Condition

Here we will see race condition closely.


Types of race condition

Write-Write Race:

it occurs when same register is written in both the blocks.

EXAMPLE:
always @(posedge clk)
a = 1;
always @(posedge clk)
a = 5;

Here you are seeing that one block is updating value of a while another also. Now
which always block should go first. This is nondeterministic in IEEE standard and left
that work to the simulator algorithm.

Read-Write Race:

it occurs when same register is read in one block and writes in another.

EXAMPLE:
always @(posedge clk)
a = 1;
always @(posedge clk)
b = a;

Here you are seeing that in one always block value is assign to a while
simultaneously its value is assign to b means a is writing and read parallel. This
type of race condition can easily solved by using nonblocking assignment.

EXAMPLE
always @(posedge clk)
a <= 1;
always @(posedge clk)
b <= a;
More Race Example:

1) Function calls

EXAMPLE:
function incri();
begin
pkt_num = pkt_num + 1;
end
endfunction
always @(...)
sent_pkt_num = incri();
always @(...)
sent_pkt_num_onemore = incri();

2) Fork join

EXAMPLE:
fork
a =0;
b = a;
join

3) $random

EXAMPLE:
always @(...)
$display("first Random number is %d",$random());
always @(...)
$display("second Random number is %d",$random());

4) Clock race

EXAMPLE
initial

clk = 0;
always
clk = #5 ~clk;

If your clock generator is always showing "X" then there is a race condition. There is
one more point to be noted in above example. Initial and always starts executes at
time zero.
5) Declaration and initial

EXAMPLE:
reg a = 0;
initial
a = 1;

6)Testbench DUT race condition.


In test bench , if driving is done at posedge and reading in DUT is done at the same
time , then there is race. To avoid this, write from the Testbench at negedge or
before the posedge of clock. This makes sure that the DUT samples the signal
without any race.

EXAMPLE:
module DUT();
input d;
input clock;
output q;
always @(posedge clock)
q = d;
endmodule
module testbench();
DUT dut_i(d,clk,q);
initial
begin

@(posedge clk)
d = 1;
@(posedge clock)
d = 0;
end
endmodule
The above example has write read race condition.
Event Terminology:

Every change in value of a net or variable in the circuit being simulated, as well as
the named event, is considered an update event. Processes are sensitive to update
events. When an update event is executed, all the processes that are sensitive to
that event are evaluated in an arbitrary order. The evaluation of a process is also an
event, known as an evaluation event.
In addition to events, another key aspect of a simulator is time. The term simulation
time is used to refer to the time value maintained by the simulator to model the
actual time it would take for the circuit being simulated. The term time is used
interchangeably with simulation time in this section. Events can occur at different
times. In order to keep track of the events and to make sure they are processed in
the correct order, the events are kept on an event queue, ordered by simulation
time. Putting an event on the queue is called scheduling an event.

The Stratified Event Queue

The Verilog event queue is logically segmented into five different regions. Events
are added to any of the five regions but are only removed from the active region.
1) Events that occur at the current simulation time and can be processed in any
order. These are the
active events.
1.1 evaluation of blocking assignment.
1.2 evaluation of RHS of nonblocking assignment.
1.3 evaluation of continuous assignment.
1.4 evaluation of primitives I/Os
1.5 evaluation of $display or $write

2) Events that occur at the current simulation time, but that shall be processed after
all the active events are processed. These are the inactive events.
#0 delay statement.
3) Events that have been evaluated during some previous simulation time, but that
shall be assigned at this simulation time after all the active and inactive events are
processed. These are the nonblocking assign update events.
4) Events that shall be processed after all the active, inactive, and non blocking
assign update events are processed. These are the monitor events.
$strobe and $monitor
5) Events that occur at some future simulation time. These are the future events.
Future events are divided into future inactive events, and future non blocking
assignment update events.
Example : PLI tasks
The processing of all the active events is called a simulation cycle.

Determinism

This standard guarantees a certain scheduling order.


1) Statements within a begin-end block shall be executed in the order in which they
appear in that begin-end block. Execution of statements in a particular begin-end
block can be suspended in favor of other processes in the model; however, in no
case shall the statements in a begin-end block be executed in any order other than
that in which they appear in the source.
2) Non blocking assignments shall be performed in the order the statements were
executed.
Consider the following example:

initial begin
a <= 0;
a <= 1;
end

When this block is executed, there will be two events added to the non blocking
assign update queue. The previous rule requires that they be entered on the queue
in source order; this rule requires that they be taken from the queue and performed
in source order as well. Hence, at the end of time step 1, the variable a will be
assigned 0 and then 1.

Nondeterminism

One source of nondeterminism is the fact that active events can be taken off the
queue and processed in any order. Another source of nondeterminism is that
statements without time-control constructs in behavioral blocks do not have to be
executed as one event. Time control statements are the # expression and @
expression constructs. At any time while evaluating a behavioral statement, the
simulator may suspend execution and place the partially completed event as a
pending active event on the event queue. The effect of this is to allow the
interleaving of process execution. Note that the order of interleaved execution is
nondeterministic and not under control of the user.

Guideline To Avoid Race Condition

(A). Do not mix blocking and nonblocking statements in same block.


(B). Do not read and write using blocking statement on same variable.( avoids read
write race)
(C). Do not initialize at time zero.
(D). Do not assign a variable in more than one block.( avoids write-write race)
(E). Use assign statement for inout types of ports & do not mix blocking and
nonblocking styles of declaration in same block. It is disallow variables assigned in a
blocking assignment of a clocked always block being used outside that block and
disallow cyclical references that don't go through a non-blocking assignment. It is
require all non-blocking assignments to be in a clocked always block.
(F). Use blocking statements for combinational design and nonblocking for
sequential design. If you want gated outputs from the flops, you put them in
continuous assignments or an always block with no clock.

Avoid Race Between Testbench And Dut

Race condition may occurs between DUT and testbench. Sometimes verification
engineers are not allowed to see the DUT, Sometimes they don't even have DUT to
verify. Consider the following example. Suppose a testbench is required to wait for a
specific response from its DUT. Once it receives the response, at the same
simulation time it needs to send a set of stimuli back to the DUT.
Most Synchronous DUT works on the posedge of clock. If the Testbench is also
taking the same reference, then we may unconditionally end in race condition. So
it~Rs better to choose some other event than exactly posedge of cock. Signals are
stable after the some delay of posedge of clock. Sampling race condition would be
proper if it is done after some delay of posedge of clock. Driving race condition can
be avoided if the signal is driven before the posedge of clock, so at posedge of clock
,the DUT samples the stable signal. So engineers prefer to sample and drive on
negedge of clock, this is simple and easy to debug in waveform debugger also.
TASK AND FUNCTION

Tasks and functions can bu used to in much the same manner but there are some
important differences that must be noted.

Functions

A function is unable to enable a task however functions can enable other functions.
A function will carry out its required duty in zero simulation time.
Within a function, no event, delay or timing control statements are permitted.
In the invocation of a function there must be at least one argument to be passed.
Functions will only return a single value and cannot use either output or inout
statements.
Functions are synthesysable.
Disable statements cannot be used.
Function cannot have nonblocking statements.

EXAMPLE:function
module function_calling(a, b,c);
input a, b ;
output c;
wire c;
function myfunction;
input a, b;
begin
myfunction = (a+b);
end
endfunction
assign c = myfunction (a,b);
endmodule

Task

Tasks are capable of enabling a function as well as enabling other versions of a Task
Tasks also run with a zero simulation however they can if required be executed in a
non zero simulation time.
Tasks are allowed to contain any of these statements.
A task is allowed to use zero or more arguments which are of type output, input or
inout.
A Task is unable to return a value but has the facility to pass multiple values via the
output and inout statements.
Tasks are not synthesisable.
Disable statements can be used.

EXAMPLE:task
module traffic_lights;
reg clock, red, amber, green;
parameter on = 1, off = 0, red_tics = 350,
amber_tics = 30, green_tics = 200;
initial red = off;
initial amber = off;

initial green = off;


always begin // sequence to control the lights.
red = on; // turn red light on
light(red, red_tics); // and wait.
green = on; // turn green light on
light(green, green_tics); // and wait.
amber = on; // turn amber light on
light(amber, amber_tics); // and wait.
end
// task to wait for tics positive edge clocks
// before turning color light off.
task light;
output color;
input [31:0] tics;
begin
repeat (tics) @ (posedge clock);
color = off; // turn light off.
end
endtask
always begin // waveform for the clock.
#100 clock = 0;
#100 clock = 1;
end
endmodule // traffic_lights.

Task And Function Queries:

Why a function cannot call a task?


As functions does not consume time, it can do any operation which does not
consume time. Mostly tasks are written which consumes time. So a task call inside a
function blocks the further execution of function utile it finished. But it~Rs not true.
A function can call task if the task call consumes zero time, but the IEEE LRM
doesn't allow.
Why tasks are not synthesized?
Wrong question! Tasks can be synthesized if it doesn't consume time.
Why a function should return a value?
There is no strong reason for this in Verilog. This restriction is removed in

SystemVerilog.
Why a function should have at least one input?
There is no strong reason for this in verilog. I think this restriction is not removed fin
SystemVerilog. Some requirements where the inputs are taken from the global
signal, those functions don~Rt need any input. A work around is to use a dummy
input. If you have a better reason, just mail me at gopi@testbench.in
Why a task cannot return a value?
If tasks can return values, then Lets take a look at the following example.
A=f1(B)+f2(C);
and f1 and f2 had delays of say 5 and 10? When would B and C be sampled, or
global inside f1 and f2 be sampled? How long does then entire statement block?
This is going to put programmers in a bad situation. So languages gurus made that
tasks can't return .
Why a function cannot have delays?
The answer is same as above. But in Open Vera, delays are allowed in function. A
function returns a value and therefore can be used as a part of any expression. This
does not allow any delay in the function.

Why disable statements are not allowed in functions?


If disable statement is used in function, it invalids the function and its return value.
So disable statements are not allowed in function.

Constant Function:

Constant function calls are used to support the building of complex calculations of
values at elaboration time. A constant function call shall be a function invocation of
a constant function local to the calling module where the arguments to the function
are constant expressions.

EXAMPLE:constant function.
module ram_model (address, write, chip_select, data);
parameter data_width = 8;
parameter ram_depth = 256;
localparam adder_width = clogb2(ram_depth);
input [adder_width - 1:0] address;

input write, chip_select;


inout [data_width - 1:0] data;
//define the clogb2 function
function integer clogb2;
input depth;
integer i,result;
begin
for (i = 0; 2 ** i < depth; i = i + 1)
result = i + 1;
clogb2 = result;
end
endfunction
Reentrant Tasks And Functions:

Tasks and functions without the optional keyword automatic are static , with all
declared items being statically allocated. These items shall be shared across all
uses of the task and functions executing concurrently. Task and functions with the
optional keyword automatic are automatic tasks and functions. All items declared
inside automatic tasks and functions are allocated dynamically for each invocation.
Automatic task items and function items cannot be accessed by hierarchical
references.

EXAMPLE:
module auto_task();
task automatic disp;
input integer a;
input integer d;
begin
#(d) $display("%t d is %d a is %d", $time,d,a);
end
endtask
initial
#10 disp(10,14);
initial
#14 disp(23,18);

initial
#4 disp(11,14);

initial
#100 $finish;
endmodule
RESULTS:
18 d is 14 a is 11
24 d is 14 a is 10
32 d is 18 a is 23

EXAMPLE:
module tryfact;
// define the function
function automatic integer factorial;
input [31:0] operand;
integer i;
if (operand >= 2)
factorial = factorial (operand - 1) * operand;
else
factorial = 1;
endfunction
// test the function
integer result;
integer n;
initial begin
for (n = 0; n <= 7; n = n+1) begin
result = factorial(n);
$display("%0d factorial=%0d", n, result);
end
end
endmodule // tryfact
RESULTS:
0
1
2
3
4

factorial=1
factorial=1
factorial=2
factorial=6
factorial=24

5 factorial=120
6 factorial=720
7 factorial=5040
WATCHDOG

A watchdog timer is a piece of code, that can take appropriate action when it judges
that a system is no longer executing the correct sequence of code. In this topic ,I
will discuss exactly the sort of scenarios a watch dog can detect, and the decision
that must be made by watchdog. Generally speaking, a watchdog timer is based on
a counter that counts down from some initial value to zero. If the counter reaches,
then the appropriate action is take. If the required functionality is archived,
watchdog can be disabled.
In software world, in watchdog articles you will see various terms like strobing,
stroking etc. In this topic I will use more visual metaphor of man kicking the dog
periodically-with apologies to animal lovers. If the man stops kicking the dog, the
dog will take advantage of hesitation and bite the man. The man has to take a
proper decision for the dog bite. The process of restarting the watchdog timer's
counter is sometimes called "kicking the dog.".Bugs in DUT can cause the testbench
to hang, if they lead to an infinite loop and creating a deadlock condition. A properly
designed watchdog should catch events that hang the testbench.
Once your watchdog has bitten ,you have to decide what action to be taken. The
testbench will usually assert the error message, other actions are also possible like
directly stop simulation or just give a warning in performance tests.
In the following example, I have taken a DUT model so its easy to understand than a
RTL to demonstrate watchdog.
DUT PROTOCOL:
DUT has 3 signals.Clock a,b;
output b should be 1 within 4 clock cycles after output a became 1.
There are two scenarios I generated in DUT. one is following the above protocol and
the other violated the above rule. The testbench watchdog shows how it caught

there two scenarios.


EXAMPLE:
module DUT(clock,a,b);
output a;
output b;
input clock;
reg a,b;
initial
begin
repeat(10)@(posedge clock) a = 0;b = 0;
@(posedge clock) a = 1;b = 0;
@(posedge clock) a = 0;b = 0;
@(posedge clock) a = 0;b = 0;
@(posedge clock) a = 0;b = 1;
repeat(10)@(posedge clock) a = 0;b = 0;
@(posedge clock) a = 1;b = 0;
@(posedge clock) a = 0;b = 0;
end
endmodule
module TB();
wire aa,bb;
reg clk;
DUT dut(clk,aa,bb);
always
#5 clk = ~clk;
initial
#400 $finish;
initial
begin
clk = 0;
$display(" TESTBENCH STARTED");
wait(aa == 1) ;
watchdog();
wait( aa == 1);
watchdog();
end
task watchdog();
begin

$display(" WATCHDOG : started at %0d ",$time);


fork : watch_dog
begin
wait( bb == 1);
$display(" bb is asserted time:%0d",$time);
$display(" KICKING THE WATCHDOG ");
disable watch_dog;
end
begin
repeat(4)@(negedge clk);
$display(" bb is not asserted time:%0d",$time);
$display(" WARNING::WATCHDOG BITED ");
disable watch_dog;
end
join
end
endtask
endmodule
RESULTS:
TESTBENCH STARTED
WATCHDOG : started at 105
bb is asserted time:135
KICKING THE WATCHDOG
WATCHDOG : started at 245
bb is not asserted time:280
WARNING::WATCHDOG BITED
Statement " disable watch_dog " is the trick hear. If that statement is not there, the
statement " wait(b == 1) " is waiting and the simulation goes hang. This watchdog
is just giving a warning about bite. You can also assert a ERROR message and call
$finish to stop simulation.
COMPILATION N SIMULATION SWITCHS

Compilation And Simulation Directives:

Conditional Compilation directive switches vs Simulation directive switches

Verilog has following conditional compiler directives.

`ifdef
`else
`elsif
`endif
`ifndef

The `ifdef compiler directive checks for the definition of a text_macro_name. If the
text_macro_name is defined, then the lines following the `ifdef directive are
included. If the text_macro_name is not defined and an `else directive exists, then
this source is
compiled. The `ifndef compiler directive checks for the definition of a
text_macro_name. If the text_macro_name is not defined, then the lines following
the `ifndef directive are included. If the text_macro_name is defined and an `else
directive exists, then this source is compiled. If the `elsif directive exists (instead of
the `else) the compiler checks for the definition of the text_macro_name. If the
name exists the lines following the `elsif directive are included. The `elsif directive
is equivalent to the compiler directive sequence `else `ifdef ... `endif. This directive
does not need a corresponding `endif directive. This directive must be preceded by
an `ifdef or `ifndef directive.

EXAMPLE:
module switches();
initial
begin
`ifdef TYPE_1
$display(" TYPE_1 message ");
`else
`ifdef TYPE_2
$display(" TYPE_2 message ");
`endif
`endif
end
endmodule

Compile with +define+TYPE_1


Then simulate,result is

RESULT:
TYPE_1 message

Compile with +define+TYPE_2


Then simulate,result is

RESULT:
TYPE_2 message

TYPE_1 and TYPE_2 are called switches.


In the above example, When TYPE_1 switch is given, statement " $display(" TYPE_1
message "); " is only compile and statement " $display(" TYPE_2 message "); " is not
compiled.
Similarly for TYPE_2 switch. It wont take much time to compile this small example.
Compilation time is not small for real time verification environment. Compiler takes
time for each change of conditional compilation switches.
Simulation directives are simple. This is archived by `define macros. The following
example demonstrated the same functionality as the above example.

EXAMPLE:
module switches();
initial
begin
if($test$plusargs("TYPE_1"))
$display(" TYPE_1 message ");
else
if($test$plusargs("TYPE_2"))
$display(" TYPE_2 message ");
end

endmodule

No need to give +define+TYPE_1 or +define+TYPE_2 during compilation


Simulate with +TYPE_1

RESULT:
TYPE_1 message

Simulate with +TYPE_2


Then simulate,result is

RESULT:
TYPE_2 message

With the above style of programing,we can save recompilation times.

This system function searches the list of plusargs (like the $test$plusargs system
function) for a user specified plusarg string. The string is specified in the first
argument to the system function as either a string or a register which is interpreted
as a string. If the string is found, the remainder of the string is converted to the type
specified in the user_string and the resulting value stored in the variable provided. If
a string is found, the function returns a non-zero integer. If no string is found
matching, the function returns the integer value zero and the variable provided is
not modified.
%d decimal conversion
%o octal conversion
%h hexadecimal conversion
%b binary conversion
%e real exponential conversion
%f real decimal conversion
%g real decimal or exponential conversion

%s string (no conversion)


The first string, from the list of plusargs provided to the simuator, which matches
the plusarg_string portion of the user_string specified shall be the plusarg string
available for conversion. The remainder string of the matching plusarg (the
remainder is the part of the plusarg string after the portion which matches the users
plusarg_string) shall be converted from a string into the format indicated by the
format string and stored in the variable provided. If there is no remaining string, the
value stored into the variable shall either be a zero (0) or an empty string value.

Example

module valuetest();
integer i;
real r;
reg [11:0] v;
reg [128:0] s;
initial
begin
if($value$plusargs("STRING=%s",s))
$display(" GOT STRING ");
if($value$plusargs("INTG=%d",i))
$display(" GOT INTEGER ");
if($value$plusargs("REAL=%f",r))
$display(" GOT REAL ");
if($value$plusargs("VECTOR=%b",v))
$display(" GOT VECTOR ");
$display( " String is %s ",s);
$display(" Integer is %d ",i);
$display(" Realnum is %f ",r);
$display(" Vector is %b ",v);
end
endmodule
Compilation :
command filename.v
Simulation :

command +STRING=rrf +INTG=123 +REAL=1.32 +VECTOR=10101


RESULTS:
GOT STRING
GOT INTEGER
GOT REAL
GOT VECTOR
String is rrf
Integer is 123
Realnum is 1.320000e+00
Vector is 000000010101

Вам также может понравиться