Wednesday, May 18, 2011

Assign From God

This post is an explanation of the "assign" keyword. I remember being confused at times about when it was okay to use this keyword when I first learned Verilog.

First, assign is structural, not procedural. What does that mean? Well, structural code is just what it sounds like: it's anything that specifies structure. Basically that means wire connections to modules or gate primitives such as "and" and "or" gates. The "assign" keyword is structural because it essentially defines what a wire (or more generally, a net) is structurally. Here's an example:

assign x = a;

This means that x takes on whatever value a has. The right hand does not have to be just another symbol; it can be a logical expression, something like:
assign x = (a & b) ^ c;
That's the easy part. The confusing thing is always know exactly when and where you can use things in verilog.

Here are the rules for assign:

The symbol on the left hand of the assign must be a net (as opposed to a variable). That means a wire, wor, wand, tri0, tri1, etc.

The symbol on the right hand, however, can be either a net or a variable. Variable types include reg, real, time, etc.

You can only use assign once for any net. You cannot, for example, have the following:

assign x = a;
assign x = b;

Remember, assign specifies structure, so this doesn't make sense. You're not specifying a changing value for x over time or program execution as you might in procedural code. Which brings me to my next point...

You cannot use assign in procedural blocks. For example:

always @(*) begin
 if(a)
  assign x = b;
end

That makes no sense. Procedural code is something that is run or executed like a program. You cannot specify the structure of something procedurally. That's just crazy-talk.

So, here, in the context of a module, is a valid use of assign:
module foo(output x, input a, input b);
 assign x = a | b;
endmodule

[EDIT: The above code is apparently syntactically valid, but it does NOT do what you want. It is also deprecated and not all compilers will warn you.]

The functionality of this module is actually to be an OR gate. Alternatively, we could have achieved the same functionality with:
module foo(output reg x, input a, input b);
 always @(a,b) begin
  x = a | b;
 end
endmodule

Notice that there, x is declared as a reg and we do not use assign. That's because this is procedural code, not structural code.

Okay, that's it! :D