//LSU EE 3755 �
Fall 2004� Computer
Organization
/// Verilog Notes 2 -- Expressions
///
Contents
//
Continuous Assignment
//
Operators:� Bitwise Logical
//
Vectors, Bit Selects, and Part Select
//
Sized Numbers and Constants (Parameters)
//
Operators: Bitwise with Vectors
//
Operators: Arithmetic
//
Operators: Logical AND, etc
///
References
// :P:�� Palnitkar, "Verilog
HDL"
// :Q:�� Qualis, "Verilog HDL Quick
Reference Card Revision 1.0"
// :PH:� Patterson
& Hennessy, "Computer Organization & Design"
////////////////////////////////////////////////////////////////////////////////
///
Continuous Assignment
// :P: 6.1����
//
Continuous assignment specifies a value for a wire using an
//
expression.
//
//
//
Continuous assignments can be made using the /assign/ keyword and in a
//
wire [or other net] declaration.
// :Keyword: assign
//
// :Sample:� assign a =
b;
//
//
Here "b" is the expression.
//
The left hand side of an assignment always should be a wire[net].
// :Example:
//
//
A simple use of the assign keyword.�
Output x is given
//
the value of "a".� Whenever
"a" changes "x" also changes.
//
Don't forget that: Whenever "a" changes
"x" also changes.
//
//
The module below passes the signal through unchanged.
module really_simple(x,a);
�� input a;
�� output x;
�� assign x = a;
endmodule
// :Example:
//
//
The module below is functionally equivalent to the one
above.
module really_simple_with_a_gate(x,a);
�� input a;
�� output x;
�� and a1(x,a);
��
endmodule
// :Example:
//
//
The module below also passes a signal through the
module unchanged,
//
but this time it goes through an extra wire, w.�
Whenever "a"
//
changes, w will change and that will change x.
module something_similar(x,a);
�� input a;
�� output x;
�� wire ��w;
�� assign w = a;
�� assign x = w;
endmodule
// :Example:
//
//
The module below is like the one above except that
//
continuous assignment to w is done in the wire declaration
//
rather than with a separate assign statement.
module something_else_similar(x,a);
�� input a;
�� output x;
�� wire�� w = a;
�� assign x = w;
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Operators:� Bitwise Logical
// :P: 6.3,6.4
// :P: 6.4.5��
//
Operators for performing bitwise logical operations.
//
//
(The meaning of bitwise and logical will be explained in the Vector
//
section below.)
//
//
//
Operators:
//� &� bitwise and
//� |� bitwise or
//� ~� bitwise not
//� ^� bitwise exclusive or
// :Example:
//
//
A module implementing: x = ab + c;
module my_abc_module(x,a,b,c);
�� input a, b, c;
�� output x;
�� assign x = a &
b | c;
endmodule
// :Example:
//
//
The module below is functionally equivalent but less
readable than
//
the one above.
module my_abc_module_gates(x,a,b,c);
�� input a, b, c;
�� output x;
�� wire�� ab;
��
�� and a1(ab,a,b);
�� or o1(x,ab,c);
endmodule
// :Example:
//
//
Simple uses of the &, |, and ~ operators along
with truth tables.
module operator_demo(x1,x2,x3,x4,a,b);
�� input a, b;
�� output x1, x2, x3,
x4;
�� // Bitwise
�� //
�� assign x1 = a &
b;
�� //
�� // a� b�
|� a & b
�� //
""""""""""""""
�� // 0� 0� |��� 0
�� // 0� 1�
|��� 0
�� // 1� 0�
|��� 0
�� // 1� 1� |��� 1
�� // Bitwise OR.� (There is also a logical OR, discussed
later.)
�� //
�� assign x2 = a | b;
�� //
�� // a� b�
|� a | b
�� //
""""""""""""""
�� // 0� 0� |��� 0
�� // 0� 1�
|��� 1
�� // 1� 0�
|��� 1
�� // 1� 1� |��� 1
�� // Bitwise XOR.
�� //
�� assign x3 = a ^ b;
�� //
�� // a� b�
|� a ^ b
�� //
""""""""""""""
�� // 0� 0� |��� 0
�� // 0� 1�
|��� 1
�� // 1� 0�
|��� 1
�� // 1� 1� |��� 0
�� // Bitwise NOT;
�� //
�� assign x4 = ~a;
�� //
�� // a��
|� ~a
�� //
""""""""""""
�� // 0��
|�� 1
�� // 1��
|�� 0
endmodule
// :Example:
//
//
A binary-full adder using operators.�
Some consider this more
//
readable than the earlier version.� Note
how spaces and returns
//
(whitespace) are used to make the assignment to sum
readable.
module bfa_implicit(sum,cout,a,b,cin);
�� input a,b,cin;
�� output sum,cout;
�� assign sum =
��������� ~a & ~b &� cin |
��������� ~a &� b & ~cin
|
���������� a & ~b
& ~cin |
���������� a
&� b &� cin;
�� assign cout = a & b | b & cin |
a & cin;
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Vectors, Bit Selects, and Part Select
// :P: 3.2.4��
///
Vectors
//
//
So far only 1-bit wires have been shown.
//
//
A /vector/ is a wire [or reg] that is more than one
bit.
//
//
The size and the bit numbering are specified in the
declaration.
//
(See examples.)
// :Sample:� wire
[10:0] a;
// :Sample:� output
[10:0] b;
//
//
Declares wire a and output b with least-significant
bit 0 and
//
most-significant bit 10 (for a total of 11 bits).
�/// Bit and Part Selects
//
//
A bit select is used to extract a single bit from a wire [or reg].
// :Sample:� assign x =
a[1]; // Extract bit 1.
//
//
A part select is used to extract several consecutive bits from a
//
wire [or reg].
// :Sample:� assign y =
a[5:3]; // Set y to 3 bits of a, bits 5 to 3.
// :Example:
//
This example does not use vectors. The author, who
knew nothing
//
about vectors, wanted a 4-bit input "a" and a 4-bit output x,
//
plus a one-bit output msb.
module
without_vectors(msb,x3,x2,x1,x0,a3,a2,a1,a0);
�� output msb;
�� output x3, x2, x1,
x0;
�� input� a3, a2, a1, a0;
�� assign msb = a3;
�� assign x3 = a3;
�� assign x2 = a2;
�� assign x1 = a1;
�� assign x0 = a0;
endmodule
// :Example:
//
//
This is the way the module above should be done.� Here input "a"
//
and output "x" are declared as 4-bit vectors.� A bit select
//
is used in the assignment to msb.
module with_vectors(msb,x,a);
�� output msb;
�� // Declare x as a
4-bit input, bit 3 is the most-significant bit (MSB).
�� output [3:0] x;
�� input� [3:0] a;
�� assign������ msb =
a[3];� // Extract bit 3 from a, which is
the MSB.
�� assign������ x = a;
endmodule
// :Example:
//
//
This module does the same thing as the one above.� It is written
//
differently: 0 is used to indicate the MSB (rather than 3).� Some
//
prefer that the MSB be the highest-numbered bit, some like it to be
//
the lowest-numbered bit.
module more_vectors(msb,x,a);
�� output msb;
�� output [0:3] x; //
Here MSB is 0 and LSB is 3.
�� input� [0:3] a;
�� assign������ msb = a[0];
�� assign������ x = a;
endmodule
// :Example:
//
//
Here the vector declaration is used in a wire, rather than
//
a port (input or output).
module and_more_vectors(x,a);
�� input [15:0] a;
�� output [15:0] x;
�� wire [15:0]�� w;
�� assign������� w = a;
�� assign������� x = w;
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Sized Numbers and Constants (Parameters)
// :P: 3.1.4, 3.2.8�
�/// Sized Numbers
//
//
In Verilog numbers can be written with a specific
size and using
//
one of four radices (bases).
//
The number consists of a size (in bits) followed by an
apostrophe,
//
followed by a b,o,d, or h
(for binary, octal, decimal,
//
hexadecimal), followed by the number.
//
// :Sample: 16'd5
//
//
The number five using 16 bits written in decimal.
//
// :Sample: 16'b101
//
//
The number five represented using 16 bits written in
binary.
�/// Constants
//
//
Constants are specified using the /parameter/ keyword.
//
// :Sample:� parameter
limit = 5;
//
//
This specifies a parameter named limit with a value of
5.
//
Identifier limit can be used in expressions but cannot be
//
assigned.� For more information see parameter_examples module
//
below.
// :Keyword:
//
parameter
// :Example:
//
//
The number one and the number ten are specified in a
variety of
//
ways.� Note the size of the wires and
that each wire is assigned
//
multiple times. (In this class, one should not assign the same wire
//
multiple times. [Elsewhere, it might be done if the wire is a bus
//
and is driven by tri-state devices.])
module fixed(one,ten);
�� output [7:0] one;
�� output [15:0] ten;
�� // All assignments below do the same
thing.�
�� //
�� // Use the one that's easiest to read.
�� //
�� assign������� one = 1;���� // No size specified.
�� assign������� one = 8'b1;� // One specified in binary.
�� assign������� one = 8'b00000001;� // One specified in binary.
�� assign������� one = 4'b1;� // Sloppy, but works: Specified wrong size.
�� assign������� one = 8'd1;� // One specified in decimal.
�� assign������� one = 8'h1;� // One specified in hexadecimal;
�� // All assignments below do the same thing.
�� //
�� // Use the one that's easiest to read.
�� //
�� assign������� ten = 10;
�� assign������� ten = 16'b1010;
�� assign����� ��ten = 16'b0000000000001010;
�� assign������� ten = 16'd10;
�� assign������� ten = 16'ha;
�� assign������� ten = 16'h000a;
endmodule
// :Example:
//
//
A sized number is used to specify the carry in of one of the bfa's
//
in a two-bit ripple adder.� It's
important to use a sized number
//
(rather than a regular number) for connections to modules.
module ripple_2(sum,cout,a,b);
�� input [1:0] a, b;
�� output [1:0] sum;
�� output������ cout;
�� wire�������� c0;
�� bfa_implicit bfa0(sum[0],c0,a[0],b[0],1'b0);
�� bfa_implicit bfa1(sum[1],cout,a[1],b[1],c0);
endmodule
// :Example:
//
//
A module illustrating the use of parameters (as constants).
module parameter_examples(an_input);
�� input [7:0] an_input;
�� parameter one = 1;
�� // Parameters can be sized numbers.
�� parameter two =
10'd2;
�� // The value of seconds_per_day is computed once, at analysis
�� // (usually compile) time.
�� parameter seconds_per_day = 60 * 60 * 24;
�� parameter width =
12;
�� parameter height =
21;
�� // The value of area is computed once, at analysis
�� // (usually compile) time.
�� parameter area =
width * height;
�� // The line below
is an error because "an_input" is not a
constant.
�� // parameter double_input
= an_input * two;
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Operators:� Bitwise with Vectors
//
The same references as the earlier bitwise logical
section.
//
// :P: 6.3,6.4
// :P: 6.4.5��
//
Operators &, |, ~, ^ are called /bitwise/ because when
//
the operands are vectors the operation is done on each
//
bit of the vector.
// :Example:
//
//
An appropriate use of a bitwise operator, followed by
//
code that does the same thing the hard way.
module and_again(x1,a,b);
�� input [2:0] a,
b;�� // Both a and b are 3 bits.
�� output [2:0] x1;
�� // An appropriate
use.
�� //
�� // Bitwise AND, but
this time operands are 3-bit vectors.
�� //
�� assign x1 = a &
b;� // ANDs
three pairs of bits.
�� // The same thing
the hard way:
�� //
�� assign x1[0] = a[0]
& b[0];
�� assign x1[1] = a[1]
& b[1];
�� assign x1[2] = a[2]
& b[2];
�� //
�� // Examples:
�� //
�� // a���
b��� |� a & b
�� //
""""""""""""""
�� // 000� 000� |� 000
�� // 000� 001�
|� 000
�� // 010� 111�
| �010
�� // 100� 110�
|� 100
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Operators: Arithmetic
// :P: 6.4.1
//
//
The arithmetic operators are:
//�� + (addition), - (subtraction), *
(multiplication), / (division),
//�� and % (remainder).
//
They operate on wires and data types to be covered
later.
// :Example:
//
//
A simple demonstration of arithmetic operators.
module arith_op(sum,diff,prod,quot,rem,a,b);
�� input [15:0] a, b;
�� output [15:0] sum,
diff, prod, quot, rem;
�� // For these
operators vectors are interpreted as integers.
�� // Addition
�� assign sum = a + b;
�� // Subtraction
�� assign diff = a -
b;
�� // Multiplication
�� assign prod = a *
b;
�� // Division
�� assign quot = a / b;
�� // Remainder (Modulo)
�� assign rem = a % b;
�� //
�� // Examples:
�� //
�� // a���
b��� |� a % b
�� //
""""""""""""""""""
�� // 3���
5��� |� 3
�� // 5���
3��� |� 2
�� // 7���
7��� |� 0
endmodule
// :Example:
//
//
The input to the module below is a complex number
(specified
//
with a real and imaginary part); the output is the square
//
of that number.
module complex_square(sr,si,ar,ai);
�� input [31:0] ar, ai;
�� output [31:0] sr, si;
�� assign������ sr = ar * ar - ai
* ai;
�� assign������ si = 2 * ar * ai;
�� // Notes on code above:
�� //
�� // Multiplication has higher precedence than
subtraction and so
�� // subtraction done last.
�� //
�� // A constant is used in the si expression.
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Operators: Logical AND, etc
// :P: 6.4.2
//
There is a logical AND operator, &&, that is different than
//
the bitwise AND, &.
//
Likewise there is a logical OR, ||, and a logical NOT, !.
//
See the example.
// :Example:
//
//
Illustration of logical operators, and how they are different than
//
the bitwise operators.
module and_again_again(x1,x2,x3,x4,a,b);
�� input [2:0] a,
b;�� // Both a and b are 3 bits.
�� output [2:0] x1;
�� output������ x2, x3, x4;
�� // Bitwise AND, but
this time operands are 3-bit vectors.
�� //
�� assign x1 = a &
b;� // ANDs
three pairs of bits.
�� //
�� // The same thing
the hard way:
�� //
�� assign x1[0] = a[0]
& b[0];
�� assign x1[1] = a[1]
& b[1];
�� assign x1[2] = a[2]
& b[2];
�� //
�� // Examples:
�� //
�� // a���
b��� |� a & b
�� //
""""""""""""""""""
�� // 000� 000� |� 000
�� // 000� 001�
|� 000
�� // 010� 111�
|� 010
�� // 100� 110�
|� 100
�� // Logical
�� //
�� assign x2 = a
&& b;
�� //
�� // Here both a and
b are 3 bits, but x2 is a single bit.
�� // Wire a is treated as logical true if any
bit is 1;
�� // it is treated as logical false if all
bits are 0.
�� //
�� // Therefore x2 is
set to 1 if a and b are true and to zero
�� // if a or b is
false.
�� //
�� // Examples:
�� //
�� // a���
b��� |� a && b
�� //
""""""""""""""""""
�� // 000� 000� |� 0
�� // 000� 001�
|� 0
�� // 010� 101�
|� 1
�� // 100� 110�
|� 1
�� // Logical OR. (Not to be confused with
bitwise OR.)
�� //
�� assign x3 = a || b;
�� //
�� // Operands are treated as logical values as
described for &&.
�� //
�� // Wire x3 is set to 1 if a or b is true and
to zero
�� // if a and b are
false.
�� //
�� // Examples:
�� //
�� // a���
b��� |� a || b
�� //
""""""""""""""""""
�� // 000� 000� |� 0
�� // 000� 001�
|� 1
�� // 010� 101�
|� 1
�� // 100� 110�
|� 1
�� // Logical NOT.
�� //
�� assign x4 = !a;
�� //
�� // Wire x4 is set to zero if any bit in a is
1,
�� // x4 is set to one if all bits in a are zero.
endmodule