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)