[Milkymist-devel] VCOMP problem with blocking assignments
Paul Campbell
paul at taniwha.com
Mon Feb 8 11:32:31 PST 2010
On Tue, 09 Feb 2010, Sébastien Bourdeauducq wrote:
> Hi Paul,
>
> I'm not sure if you are still maintaining VCOMP [1], but I'm trying to use
it
> to debug the texture mapping unit in Milkymist [2], an open source hardware
> SoC with 2D acceleration. Being a "compiled" simulator, I hope it would
bring
> speed advantages over GPL Cver that I'm currently using (full simulations of
> the texture mapping unit typically take several minutes on a fast machine).
> I have noticed two problems:
>
> * most importantly, blocking assignments sometimes do not work as expected,
> for example in the following code excerpt:
>
> correct = (err[16:0] > {1'b0, divisor_r[16:1]}) & ~err[17];
> if(positive) begin
> o = o + {1'b0, q_r}; // A
> if(correct)
> o = o + 18'd1; // B
> end else begin
> o = o - {1'b0, q_r}; // A'
> if(correct)
> o = o - 18'd1; // B'
> end
>
> If correct evaluates to true, then only lines B or B' are taken into account
> (not A and A'), yielding a wrong value for o (only incremented/decremented
by
> 1 while it should _also_ be added/subtracted {1'b0, q_r}). I am attaching
the
> full source code that provokes the problem.
this is a common verilog trap - not really a bug - more of something you need
to be aware of - it can catch you out in other simulators too
In essence "output reg o" is identical to "output o; reg r_o;assign o=r_o;"
except that assignments to o go quietly to r_o - the problem you're seeing is
that the scheduling of the "assign o=r_o" occur after the point where you
write r_o and may occur before you read o again - the compiler has to be able
to act differently from the way that other register assignments work because
the output wire must be evaluated in the context of all possible other wires
connected to that terminal (there could be hazards [XXXs] there for example)
The way to reliably code what you want to do is to make the register explicit:
module tmu2_geninterp18(
.....
output signed [17:0] o
);
reg [17:0] r_o;
assign o=r_o;
....
if(positive) begin
r_o = r_o + {1'b0, q_r}; // A
if(correct)
r_o = r_o + 18'd1; // B
end else begin
r_o = r_o - {1'b0, q_r}; // A'
if(correct)
r_o = r_o - 18'd1; // B'
end
that way you're sampling and writing the same thing
I'll have a look at the signed issue - you'll have to code around it in the
mean time
Paul
More information about the Devel
mailing list