//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