Testbenches and the number of assignments per cycle

Guest
Hey everyone,

Im just wondering if people do or dont ever feel the need to make more
than just one assignment to a signal per clock cycle?

Is there a case where making more than one assignment to a signal (from
a testbench) in a clock cycle would be neccessary when testing a piece
of sequential logic?

I cant really see the need as any clk sensitive always blocks wont see
every assignment. Is it ok to say this is "bad" coding practice?

Sorry if this is stupid question but they're the kind i tend to ask :)

Cheers,


Rob.
 
robquigley@gmail.com wrote:
Hey everyone,

Im just wondering if people do or dont ever feel the need to make more
than just one assignment to a signal per clock cycle?

Is there a case where making more than one assignment to a signal (from
a testbench) in a clock cycle would be neccessary when testing a piece
of sequential logic?

I cant really see the need as any clk sensitive always blocks wont see
every assignment. Is it ok to say this is "bad" coding practice?
Certainly not. Rather, the use of multiple assignments can be the
result of good coding practice. The fact that the last assignment "wins"
can be used to express the code's intention more clearly.

The classic example is the use of default assignments. Consider the
case where a signal should get a default value most of the time,
and another value under some "exceptional" condition embedded in
complex control logic. Without a default assignment, you would have
to "decode" the "else" case of that condition "manually". With a
default assignment, the code is therefore much clearer and
maintainable.

There is also no reason to restrict this reasoning to test benches;
it applies to any kind of code, including synthesizable code.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
 
Jan Decaluwe wrote:
robquigley@gmail.com wrote:
Hey everyone,

Im just wondering if people do or dont ever feel the need to make more
than just one assignment to a signal per clock cycle?

Is there a case where making more than one assignment to a signal (from
a testbench) in a clock cycle would be neccessary when testing a piece
of sequential logic?

I cant really see the need as any clk sensitive always blocks wont see
every assignment. Is it ok to say this is "bad" coding practice?

Certainly not. Rather, the use of multiple assignments can be the
result of good coding practice. The fact that the last assignment "wins"
can be used to express the code's intention more clearly.

The classic example is the use of default assignments. Consider the
case where a signal should get a default value most of the time,
and another value under some "exceptional" condition embedded in
complex control logic. Without a default assignment, you would have
to "decode" the "else" case of that condition "manually". With a
default assignment, the code is therefore much clearer and
maintainable.

There is also no reason to restrict this reasoning to test benches;
it applies to any kind of code, including synthesizable code.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
I agree with Jan, whole-heartedly. Reassigning a variable multiple
times during a timestep is something I do almost every time I sit down
to write something, whether it be RTL or behavioral.

In the behavioral code, I don't think too much about reassigning a
variable... I code just like I would in another programming language.

While writing RTL, however, I tend to use non-blocking assigns (<=)
rather than blocking assigns (=). When coding with non-blocking
assigns I don't tend to reassign different values during the same time
step, though I've seen it done, and I know of some production ASICs
where blocks like this exist, and work happily:

always @(posedge clk or negedge rst) begin
state <= 2'd0;
end
else begin
state <= 2'd1;
state <= 2'd2;
state <= 2'd3;
state <= 2'd0;
end

The value in most simulators will be 2'd0, but I don't code like this,
and I don't recommend that you do either.
Technically, the value of state after any positive edge of clock should
be undefined. This is because (by definition) non-blocking assigns do
not block the next line from occuring simultaneously. At the end of
the time step, all four assignments (should) occur at the same instant.
This would imply that the state value after the posedge of clk would
be 2'dx, all the time.

In reality, most commercial simulators and synthesis tools will 'play
along' and do what the designer really meant, which was to have the
LAST assignment determine the value.
I know of one designer who used this 'feature' freely, and he produced
simulatable and synthesizable code.

I would recommend only doing the multiple assignments during a time
step when working with blocking assigns, like so:

always @(state) begin
case (state)
state = 2'd1;
state = 2'd2;
state = 2'd3;
state = 2'd0;
endcase
end

By definition, blocking assignments occur in order, even during a
single timestep. This means that if the simulator/synthesis tool
follows specification, you'll get what you expect every time, which is
to have the last assignment override all earlier ones.

If you try to use non-blocking assigns to the same variable during a
single timestep, be aware that the results you get in various
simulators/synthesis tools may vary (which is something you rarely
want).

Brandon
 
robquigley@gmail.com wrote:
Hey everyone,
Im just wondering if people do or dont ever feel the need to make
more
than just one assignment to a signal per clock cycle?
Is there a case where making more than one assignment to a signal
(from
a testbench) in a clock cycle would be neccessary when testing a piece
of sequential logic?
I cant really see the need as any clk sensitive always blocks wont
see
every assignment. Is it ok to say this is "bad" coding practice?
Jan Decaluwe <jan@jandecaluwe.com> replied:

Certainly not. Rather, the use of multiple assignments can be the
result of good coding practice. The fact that the last assignment "wins"
can be used to express the code's intention more clearly.

The classic example is the use of default assignments. Consider the
case where a signal should get a default value most of the time,
and another value under some "exceptional" condition embedded in
complex control logic. Without a default assignment, you would have
to "decode" the "else" case of that condition "manually". With a
default assignment, the code is therefore much clearer and
maintainable.

There is also no reason to restrict this reasoning to test benches;
it applies to any kind of code, including synthesizable code.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
As Jan points out "default assignments" are a very good coding style
for synthesizable code (and for any code that it helps to make
clearer). However, as to the other part of your question, I don't
think one could write a testbench that does multiple assignments
within a single block with the intention that the DUT (device under
test) will get those values sequentially and react to them. The
Verilog standard (and its various rules about non-determinism) makes
such a supposition highly unlikely.

Thus, the following makes sense:

signal = 1; // default assignment
if (this && that || x || y && z)
then begin
signal = 2;
end;
if (a || b && c || d && e && f)
then begin
signal = 3;
end;

The code below does not:

signal = 1;
if (response != 1) //check what DUT did with signal = 1
then begin
test_fail();
end;
signal = 2;
if (response != 2) //check what DUT did with signal = 2
then begin
test_fail();
end;

Unless it was more like:

signal = 1;
@(posedge response_valid); // this waits for the DUT to say it's ready
response_valid = 0;
if (response != 1) //check what DUT did with signal = 1
then begin
test_fail();
end;
signal = 2;
@(posedge response_valid); // this waits for the DUT to say it's ready
response_valid = 0;
if (response != 2) //check what DUT did with signal = 2
then begin
test_fail();
end;

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
gorjusborg wrote:
Technically, the value of state after any positive edge of clock should
be undefined. This is because (by definition) non-blocking assigns do
not block the next line from occuring simultaneously. At the end of
the time step, all four assignments (should) occur at the same instant.
This would imply that the state value after the posedge of clk would
be 2'dx, all the time.
The Verilog-XL and OVI Verilog standard specified that this was
undefined. However, it was common practice to rely on the fact that
the simulator would actually execute them in the expected order. As a
result, the IEEE 1364-1995 standard tried to mandate that they would
actually execute in this order. But the older text stating that it was
undefined was still present, so there was a contradiction.

The intent was that the statement about deterministic order was
supposed to override the statement about the order being undefined. In
the IEEE 1364-2001 standard, the text was fixed to be consistent about
the deterministic order. If two nonblocking assignments execute in a
deterministic order (e.g. one is later in the same sequential block),
then the assignments are guaranteed to occur in that order also, so
that the last one wins. So this formerly bad practice is now
legitimate.

Nonblocking assignments are generally much more expensive to simulate
than blocking ones, so extra unnecessary ones are best avoided for
performance reasons.
 

Welcome to EDABoard.com

Sponsor

Back
Top