//LSU EE 3755 – Fall 2009 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 AND. (There is also a logical AND, discussed
later.)
//
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 AND. (Not to be
confused with bitwise AND!)
//
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