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

Reply via email to