Why this code doesn't work?

P

Peng Yu

Guest
Hi,
The in and out of the first code list is always x. The second code
list is corrected. Why the first isn't correct? Must I use a function
instead of a module under this situation?
Thanks!
Peng

/////the code with errors
module reverse(output out, input in);
assign out = ~in;
endmodule

module timing;

reg in, clock;
wire out;

reverse reverse(out, in);

initial begin : init_value
in = 0;
clock = 0;
#50 $stop;
end

always begin
in <= out;
@(posedge clock);
$display("time=%0t,in=%b,out=%b,clock=%b", $time, in, out, clock);
end

always
#5 clock = ~clock;

endmodule
///////////the end of the incorrect code


////the code list without errors
module timing;

reg in, clock;

function reverse(input in);
reverse = ~in;
endfunction

initial begin : init_value
in = 0;
clock = 0;
#50 $stop;
end

always begin
in <= reverse(in);
@(posedge clock);
$display("time=%0t,in=%b,clock=%b", $time, in, clock);
end

always
#5 clock = ~clock;

endmodule
///////the end of the correct code
 
Hi Yu,

IMHO, both examples are not correct.
First is obvious - the beginning value for in is X (it is a register)
you execute processes in the order they appear in your code (but this
is not obligatory), so as first triggers the assign in reverse module
- you get X for out, then goes initial - you get 0 for in as the last
in <= out is executed which gives you x on in.
The second one works correctly by accident - it is a race too. But in
this case you do not have out wire. First goes the initial with 0
assigned to in and then the "correct" value from always statement.
I have to say that I did not check it, so I might be wrong. Please,
understand if I missed something here.

Marcin

yupeng_@hotmail.com (Peng Yu) wrote in message news:<d7b3726c.0308051402.258cd28f@posting.google.com>...
Hi,
The in and out of the first code list is always x. The second code
list is corrected. Why the first isn't correct? Must I use a function
instead of a module under this situation?
Thanks!
Peng

/////the code with errors
module reverse(output out, input in);
assign out = ~in;
endmodule

module timing;

reg in, clock;
wire out;

reverse reverse(out, in);

initial begin : init_value
in = 0;
clock = 0;
#50 $stop;
end

always begin
in <= out;
@(posedge clock);
$display("time=%0t,in=%b,out=%b,clock=%b", $time, in, out, clock);
end

always
#5 clock = ~clock;

endmodule
///////////the end of the incorrect code


////the code list without errors
module timing;

reg in, clock;

function reverse(input in);
reverse = ~in;
endfunction

initial begin : init_value
in = 0;
clock = 0;
#50 $stop;
end

always begin
in <= reverse(in);
@(posedge clock);
$display("time=%0t,in=%b,clock=%b", $time, in, clock);
end

always
#5 clock = ~clock;

endmodule
///////the end of the correct code
 
Hi Marcin,
If both of them aren't correct, could you tell me what's the correct
code? The next cycle value is always a function of the previous cycle
value.
Peng
chtruk@yahoo.com (Marcin) wrote in message news:<cf56decc.0308052117.3e3ae1c3@posting.google.com>...
Hi Yu,

IMHO, both examples are not correct.
First is obvious - the beginning value for in is X (it is a register)
you execute processes in the order they appear in your code (but this
is not obligatory), so as first triggers the assign in reverse module
- you get X for out, then goes initial - you get 0 for in as the last
in <= out is executed which gives you x on in.
The second one works correctly by accident - it is a race too. But in
this case you do not have out wire. First goes the initial with 0
assigned to in and then the "correct" value from always statement.
I have to say that I did not check it, so I might be wrong. Please,
understand if I missed something here.

Marcin
 
chtruk@yahoo.com (Marcin) wrote in message news:<cf56decc.0308052117.3e3ae1c3@posting.google.com>...
The second one works correctly by accident - it is a race too. But in
this case you do not have out wire. First goes the initial with 0
assigned to in and then the "correct" value from always statement.
I have to say that I did not check it, so I might be wrong. Please,
understand if I missed something here.
I believe your analysis is correct. In the second example, reversing
the order of the initial and always block in the source will cause
the result to be X in most simulators. Both examples contain race
conditions and their behavior is nondeterministic according to the
standard.
 
I'm not quite understand why it's wrong and how to write code that
don't have race conditions. You said "according to the standard". I
have the verilog-2001 standard at my hand. Could you tell me which
part I shall read to clarify my doubt? Could you introduce some more
materials on this issue?

sharp@cadence.com (Steven Sharp) wrote in message news:<3a8e124e.0308061144.680319ad@posting.google.com>...
I believe your analysis is correct. In the second example, reversing
the order of the initial and always block in the source will cause
the result to be X in most simulators. Both examples contain race
conditions and their behavior is nondeterministic according to the
standard.
 
yupeng_@hotmail.com (Peng Yu) wrote in message news:<d7b3726c.0308061844.4ec63872@posting.google.com>...
I'm not quite understand why it's wrong and how to write code that
don't have race conditions. You said "according to the standard". I
have the verilog-2001 standard at my hand. Could you tell me which
part I shall read to clarify my doubt? Could you introduce some more
materials on this issue?
There are a variety of references to indeterminate execution order
in the standard. Section 5 tries to describe most of this, though
it doesn't do it very well. Sections on specific constructs will
mention the lack of determinate execution order between processes
executing at the same time.

Given this information, it is up to you to figure out whether your
code contains race conditions. If two different execution orders
allowed by the standard would give different results, then your
code is faulty. Figuring this out may require mentally tracing
through the possible orders that things could execute in and
the sequence of assignments that would occur (as one of the other
posters did for your examples).

There are sets of coding guidelines that will avoid race conditions
if followed. A good Verilog textbook will probably present a set
of these.

The particular problem in your code is that you are assigning to
the same variable at the same time (time zero) in two different
processes (the initial and always block). You are also mixing
blocking and nonblocking assignments to the same variable, which
can lead to problems.
 
Hi,

Is it a testcase only? A part of your testbench? In this case you can
consider something like this :

module timing;

reg in, clock;

function reverse(input in);
reverse = ~in;
endfunction


initial #50 $stop;

initial begin
in = 1;
forever @(posedge clock) begin
in = reverse(in);
$display("time=%0t,in=%b,clock=%b", $time, in, clock);
end
end

initial begin
clock = 0;
forever #5 clock = ~clock;
end

endmodule

Marcin

yupeng_@hotmail.com (Peng Yu) wrote in message news:<d7b3726c.0308060833.3b1f8d56@posting.google.com>...
Hi Marcin,
If both of them aren't correct, could you tell me what's the correct
code? The next cycle value is always a function of the previous cycle
value.
Peng
chtruk@yahoo.com (Marcin) wrote in message news:<cf56decc.0308052117.3e3ae1c3@posting.google.com>...
Hi Yu,

IMHO, both examples are not correct.
First is obvious - the beginning value for in is X (it is a register)
you execute processes in the order they appear in your code (but this
is not obligatory), so as first triggers the assign in reverse module
- you get X for out, then goes initial - you get 0 for in as the last
in <= out is executed which gives you x on in.
The second one works correctly by accident - it is a race too. But in
this case you do not have out wire. First goes the initial with 0
assigned to in and then the "correct" value from always statement.
I have to say that I did not check it, so I might be wrong. Please,
understand if I missed something here.

Marcin
 
yupeng_@hotmail.com (Peng Yu) wrote in message news:<d7b3726c.0308071806.249655c0@posting.google.com>...
sharp@cadence.com (Steven Sharp) wrote in message news:<3a8e124e.0308071100.623d6b5f@posting.google.com>...
Sections on specific constructs will
mention the lack of determinate execution order between processes
executing at the same time.
I searched "specific constructs" in the verilog-2001 standard. But I
didn't find this term. Could you tell me which chapter it's in?
That was not a technical term, it was an English phrase. Some of the
documentation on this is in the sections specific to the construct
(e.g. initial block, always block, nonblocking assignment, fork-join)
that it applies to. For example, section 9.9 on structured procedures
mentions that there shall be no implied order of execution between
initial and always constructs.

I have Verilog HDL (by Samir Palnitkar), which is very popular. But I
don't find the guidelines in this book. Could you tell me some other
books talking about that?
I am not a designer, so perhaps you can get some advice from someone
else. Most guidelines assume that you are writing synthesizable RTL
code. Just the restrictions on that would have prevented your problem.
The initial block would have been illegal for synthesis, and writing to
the same reg from two different blocks is probably illegal with most
synthesis tools.

You can find some papers containing guidelines for avoiding some kinds
of race conditions at www.sunburst-design.com. However, these papers
will assume that you already understand how to write synthesizable RTL
code. And not everyone agrees with all of these particular guidelines.
 

Welcome to EDABoard.com

Sponsor

Back
Top