On 2006-06-16, Timothy Miller wrote:
> What should Lesson 4 be about?

My vote would be to introduce sequential blocks, so that we can start
implementing microprocessors ;-).  Okay, CPUs'll wait.

> Have we covered combinatiorial behavioral code well enough?  Do we
> need more of that, or should I move on to sequential?  Or is there
> something more basic I need to cover?

One thing I would like to understand is in which case a 'reg' is a
register.  I think I can make a guess.  You may have skipped explaining
this, because a flip-flop used for the registers needs a clock.  E.g.
since there is no clock involved in

    reg u, v, w;
    always @(x,y) begin
        u = x & y;
        v = x & u;
        w = u & v;
    end

the synthesiser can turn the whole thing into continuous assignments.
Is there anything we can do with combinatorial behavioural blocks that
can't be done with continuous assignments and some patience in unrolling
loops etc?

However, if we introduce a clock, we have

    reg u, v, w;
    always @(posedge clk) begin
        u = x & y;  // register
        v = x & u;  // register
        w = u & v;  // not a register
    end

This can be transformed to

    reg u, v;
    wire w;
    always @(posedge clk) begin
        u = x & y;
        v = x & u;
    end
    assign w = u & v;

'v' can not be taken out of the behavioural block because it would then
get updated with new values of 'x' before the clock rises.  For 'w' this
is not a problem because it only depends on values which are already
clocked.

Is this correct?  Are there cases where a synthesiser would create
registers in absence of 'posedge' or 'negedge'?  I think I read that is
an error to intentionally leave out variables from the sensitivity list
to condition the whole behavioural block to execute only when some of
the values are changed.  This makes sense, of course.


Some minor points.  Verilog accepts a precise syntax for bus constants

    91                  -- 32 bit value
    4'b1001             -- 4 bit value 5 given in binary
    32'h8000_0000       -- 32 bit value in hex (_ is for readability)
    8{1'b0} = 8'b11111111
    4{8'hd0} = 32'hd0d0d0d0 -- (I guess?)

they can be combined with wires and registers in {} constructs:

    {addr,2'b0}         -- addr padded with two 0-bits on the right

Another point, it is valid to re-assign variables.  This is useful to
make defaults for variables assigned in conditional code

    wire[1:0] op;
    wire[15:0] x, y;
    reg[15:0] z;
    always @(op, x, y) begin
        carry = 0; // only default
        case (op)
            OP_ADD: {carry,z} = {1'b0,x} + {1'b0,y};
            OP_SUB: {carry,z} = {borrow,x} - {1'b0,y}; // correct?
            OP_AND: z = x & y;  // carry takes default 0
            OP_NOT: z = ~x;     // carry takes default 0
        endcase
    end

Notice the convenient Verilog feature that {} can be used on the LHS of
an assignment.

OTOH, even if the loop bounds are constant in the following code, I
believe this code does not behave as expected or is even valid:

    wire x[31:0];
    reg y[31:0];
    integer i;
    always @(x) begin
        y = x;
        for (i = 0; i < 8: ++i)
            y = (y ^ (y >> 7)) - ((y >> 11) ^ (key >> 19));
    end

It would be a big opportunity for gate-bloat if it worked as expected.


Thanks for the tutorial!
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to