3.1 Verilog Continuous Assignment
Category Verilog Tutorial
Keywords: assign, full adder
The continuous assignment statement is the fundamental statement for dataflow modeling in Verilog, used to assign values to wire-type variables.
The format is as follows:
assign LHS_target = RHS_expression ;
LHS (left hand side) refers to the left side of the assignment operation, and RHS (right hand side) refers to the right side of the assignment operation.
The keyword assign begins any continuous assignment statement for a wire variable that has been declared, for example:
wire Cout, A, B ;
assign Cout = A & B ; //Implements the functionality of A and B
It should be noted that:
LHS_target must be a scalar or a vector, not a register type.
The type of RHS_expression is not required; it can be a scalar, a vector, or a register vector, or a function call.
As long as there is an event in the operands of the RHS_expression (a change in value), the RHS_expression will be recalculated immediately and assigned to LHS_target.
Verilog also provides another simple method for assigning to wire types, which is to assign a value to the wire type variable at the time of its declaration. A wire type variable can only be assigned once, so this continuous assignment method can also only be used once. For example, the following assignment method is consistent with the above assignment example.
wire A, B ;
wire Cout = A & B ;
Full Adder
The following uses a dataflow description method to design a 1-bit full adder.
Let Ai, Bi, and Ci be the augend, addend, and carry-in from the adjacent lower bit, respectively, and So and Co be the sum and carry-out of this bit.
The truth table is as follows:
Input | Output | |||
---|---|---|---|---|
Ci | Ai | Bi | So | Co |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
The expression for the full adder is:
So = Ai ⊕ Bi ⊕ Ci ;
Co = AiBi + Ci(Ai+Bi)
The RTL code (full_adder1.v) is as follows:
Example
module full_adder1(
input Ai, Bi, Ci,
output So, Co);
assign So = Ai ^ Bi ^ Ci ;
assign Co = (Ai & Bi) | (Ci & (Ai | Bi));
endmodule
Of course, a more adder-oriented code description can be:
Example
module full_adder1(
input Ai, Bi, Ci
output So, Co);
assign {Co, So} = Ai + Bi + Ci ;
endmodule
The testbench (test.sv) reference is as follows:
Example
``
timescale 1ns/1ns
module test ;
reg Ai, Bi, Ci ;
wire So, Co ;
initial begin
{Ai, Bi, Ci} = 3'b0;
forever begin
#10 ;
{Ai, Bi, Ci} = {Ai, Bi, Ci} + 1'b1;
end
end
full_adder1 u_adder(
.Ai (Ai),
.Bi (Bi),
.Ci (Ci),
.So (So),
.Co (Co));
initial begin
forever begin
#100;
//$display("---gyc---%d", $time);
if ($time >= 1000) begin
$finish ;