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 _______________________________________________ http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org IRC: #milkym...@freenode Webchat: www.milkymist.org/irc.html Wiki: www.milkymist.org/wiki