///
LSU EE 3755 Fall
2009
Computer Organization
//
///
Verilog Notes 5
///
Contents
//
Unsigned and Signged Adder
//
Construction of ALUs
///
References
//
// :P: Palnitkar, "Verilog
HDL"
// :Q: Qualis, "Verilog HDL Quick
Reference Card Revision 1.0"
// :PH: Patterson & Hennessy, "Computer
Organization & Design"
////////////////////////////////////////////////////////////////////////////////
//
:Example:
//
// An unsigned
adder with an overflow output.
// The overflow
is the carry out.
(Carry
// out and
overflow are not equivalent for signed adders.) In the
// examples in
this section the addition operator is used.
module
unsigned_adder(overflow,sum,a,b);
input [7:0] a,
b;
output [7:0]
sum;
output
overflow;
assign {overflow,sum} = a +
b;
endmodule
//
:Example:
//
// A signed adder
with an overflow output.
module
signed_adder(sum,overflow,a,b);
input [7:0] a,
b;
output [7:0]
sum;
output
overflow;
assign sum = a +
b;
wire sa = a[7];
wire sb = b[7];
wire ssum =
sum[7];
assign overflow = sa != sb ? 0 :
sb == ssum ? 0 : 1;
endmodule
//
:Example:
//
// A signed adder
in which the second input is half the size of
// the
first. The adder needs to
sign-extend the second input
// before adding
it.
module
signed_adder2(sum,overflow,a,b);
input [7:0]
a;
input [3:0]
b;
output [7:0]
sum;
output
overflow;
wire sa = a[7];
wire sb = b[3];
assign sum = a +
{ sb ? 4'b1 : 4'b0, b };
wire ssum =
sum[7];
assign overflow = sa != sb ? 0 :
sb == ssum ? 0 : 1;
endmodule
//
// We covered
this bfa_implicit at note 4.
// We will use
this at ALU below and 32bit ripple carry adder at the end.
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
////////////////////////////////////////////////////////////////////////////////
/// Construction
of ALUs
// /ALU/: The
primary device in a computer for performing integer
// arithmetic and
logical operations. [There may be
other /functional
// units/ that
perform additional integer and also floating-point
//
operations.]
/// Goal: Design
ALU that can share as much hardware as possible.
//
// First ALU
below does not share much hardware.
//
// In the second
ALU below adder is shared for addition, subtraction, and
// less than.
/// First ALU
//
//
Specifications
//
// Perform bitwise AND, bitwise OR, and
addition.
//
// Two-bit input for operation,
op.
//
// Operation encoding: and (0), or
(1), add (2)
// Step
1:
// Define a slice
module that can perform any of the operations
// (and, or, add)
on two one-bit inputs and a carry input.
//
// Step
2:
// Connect the
slices to construct the entire ALU.
//
:Example:
//
// Slice for
first alu. See : Figure
4.14
module
alu_slice(result,cout,a,b,cin,op);
input a, b,
cin;
input [1:0]
op;
output result,
cout;
wire sum;
parameter op_and = 0;
parameter op_or = 1;
parameter op_add = 2;
bfa_implicit
bfa(sum,cout,a,b,cin);
assign result
=
op == op_and ? a & b :
op == op_or ? a | b
:
op ==
op_add ? sum :
0;
endmodule
//
:Example:
//
// ALU using
slice above. See : Figure 4.15
module
alu(result,a,b,cin,op);
input [31:0] a,
b;
input
cin;
input [1:0] op;
output [31:0]
result;
wire [31:0] cout;
alu_slice
slice0(result[0],cout[0],a[0],b[0],cin,op);
alu_slice
slice1(result[1],cout[1],a[1],b[1],cout[0],op);
alu_slice
slice2(result[2],cout[2],a[2],b[2],cout[1],op);
alu_slice
slice3(result[3],cout[3],a[3],b[3],cout[2],op);
alu_slice
slice4(result[4],cout[4],a[4],b[4],cout[3],op);
alu_slice
slice5(result[5],cout[5],a[5],b[5],cout[4],op);
alu_slice
slice6(result[6],cout[6],a[6],b[6],cout[5],op);
alu_slice
slice7(result[7],cout[7],a[7],b[7],cout[6],op);
alu_slice
slice8(result[8],cout[8],a[8],b[8],cout[7],op);
alu_slice
slice9(result[9],cout[9],a[9],b[9],cout[8],op);
alu_slice
slice10(result[10],cout[10],a[10],b[10],cout[9],op);
alu_slice
slice11(result[11],cout[11],a[11],b[11],cout[10],op);
alu_slice
slice12(result[12],cout[12],a[12],b[12],cout[11],op);
alu_slice
slice13(result[13],cout[13],a[13],b[13],cout[12],op);
alu_slice
slice14(result[14],cout[14],a[14],b[14],cout[13],op);
alu_slice
slice15(result[15],cout[15],a[15],b[15],cout[14],op);
alu_slice
slice16(result[16],cout[16],a[16],b[16],cout[15],op);
alu_slice
slice17(result[17],cout[17],a[17],b[17],cout[16],op);
alu_slice
slice18(result[18],cout[18],a[18],b[18],cout[17],op);
alu_slice
slice19(result[19],cout[19],a[19],b[19],cout[18],op);
alu_slice
slice20(result[20],cout[20],a[20],b[20],cout[19],op);
alu_slice
slice21(result[21],cout[21],a[21],b[21],cout[20],op);
alu_slice
slice22(result[22],cout[22],a[22],b[22],cout[21],op);
alu_slice
slice23(result[23],cout[23],a[23],b[23],cout[22],op);
alu_slice
slice24(result[24],cout[24],a[24],b[24],cout[23],op);
alu_slice
slice25(result[25],cout[25],a[25],b[25],cout[24],op);
alu_slice
slice26(result[26],cout[26],a[26],b[26],cout[25],op);
alu_slice
slice27(result[27],cout[27],a[27],b[27],cout[26],op);
alu_slice
slice28(result[28],cout[28],a[28],b[28],cout[27],op);
alu_slice
slice29(result[29],cout[29],a[29],b[29],cout[28],op);
alu_slice
slice30(result[30],cout[30],a[30],b[30],cout[29],op);
alu_slice
slice31(result[31],cout[31],a[31],b[31],cout[30],op);
endmodule
/// Second ALU
//
// This ALU can
perform additional operations: subtract and less than.
// Both subtract
and less than use the adder's hardware.
// When it does
subtraction operation, it uses add with inverted b and
// carry input of
1.
// For set less
than(slt)operation,if a < b Result = 0...001,
// otherwise
Result =
0...000.
//
:Example:
//
// Slice for
second ALU. See : Figure
4.17
// generated by
MSB slice which is alu_slice2MSB (set output of ALU31 of
// Figure 4.18,
// for ALU0 and 0
for all the others(ALU1 to ALU31).
module
alu_slice2(result,cout,a,b,cin,op,binvert,less);
input a, b, cin, binvert,
less;
input [1:0]
op;
output result,
cout;
parameter sop_and = 0;
parameter sop_or = 1;
parameter sop_add = 2;
parameter sop_slt = 3;
wire b2 =
binvert ? ~b : b;
wire
sum;
bfa_implicit
bfa(sum,cout,a,b2,cin);
assign result
=
op == sop_and ? a & b :
op == sop_or ? a | b
:
op == sop_add ? sum :
less; // else, op == sop_slt
endmodule
//
:Example:
//
// Bit slice for
bit 31. This also generates a set
and overflow
//
output.
module
alu_slice2MSB(result,set,overflow,a,b,cin,op,binvert,less);
input a, b, cin, binvert,
less;
output set,
overflow;
input [1:0]
op;
output
result;
parameter sop_and = 0;
parameter sop_or = 1;
parameter sop_add = 2;
parameter sop_slt = 3;
wire b2 =
binvert ? ~b : b;
wire
sum;
assign overflow
=
op != sop_add ? 1'b0 :
a != b2 ? 1'b0
:
a == sum
? 1'b0 : 1'b1;
assign set = a == b ? sum :
a;
//set is sign
bit.
//we assume signed
numbers.
//bit 31 is sign
bit.
// A, B are 32 bit numbers and a,
b are sign bits of those numbers.
//
// sign bits
// a b
set
// 0 0 sum //do
subtraction, A - B and check
//for the sign bit.
//if A < B then sign bit of(A-B) is negative(1).
// 0 1 a //don't set.
//because A is positive number,
// B is negative number( A > B).
// 1 0 a //set.
// because A is negative number ,
//B is positive number(A < B).
// 1 1 sum //do
subtraction, A - B and
//check for the sign bit.
//if A < B then sign bit of(A-B) is negative(1).
// if A < B then the sign bit of(A-B)
//is negative(1).
// sum which is bit31 is the sign bit.
// so check for the sum bit.
// case of same sign
bits
// using ~b because we are doing
A-B.
// a b ~b carryln sum
A < B ?
// 0 0 1 0
1
A < B so set.
// 0 0 1 1
0
// 1 1 0 0
1
A < B so set.
// 1 1 0 1
0
bfa_implicit
bfa(sum,cout,a,b2,cin);
// we are using
b2, because sometimes we need subtraction operation
// (set_less_than
or subtraction).
assign result
=
op == sop_and ? a & b :
op == sop_or ? a | b
:
op == sop_add ? sum :
less; // else, op == sop_slt
endmodule
//
:Example:
//
// Second
ALU. The same module is used for
bits 0-30, bit 31
// is computed by
a special module(alu_slice2MSB)
// that also
determines overflow
// and whether a
< b.
module
alu2(result,overflow,a,b,alu_op);
input [31:0] a,
b;
input [2:0] alu_op;
output [31:0]
result;
output
overflow;
wire [31:0] cout;
parameter op_and =
0;
parameter op_or = 1;
parameter op_slt =
2;
parameter op_add =
3;
parameter op_sub =
4;
parameter sop_and =
0;
parameter sop_or = 1;
parameter sop_add =
2;
parameter sop_slt =
3;
wire [1:0] op
=
alu_op == op_and ? sop_and :
alu_op == op_or ?
sop_or :
alu_op == op_slt ? sop_slt :
alu_op == op_add ? sop_add :
alu_op == op_sub ? sop_add : 0;
wire binvert =
alu_op == op_sub || alu_op == op_slt;
wire set; // MSB of sum.
// using binvert for cin of the
LSB slice.
// when we do subtract or slt, the
binvert is set to 1.
alu_slice2
slice0(result[0],cout[0],a[0],b[0],binvert,op,binvert,set);
alu_slice2
slice1(result[1],cout[1],a[1],b[1],cout[0],op,binvert,1'b0);
alu_slice2
slice2(result[2],cout[2],a[2],b[2],cout[1],op,binvert,1'b0);
alu_slice2
slice3(result[3],cout[3],a[3],b[3],cout[2],op,binvert,1'b0);
alu_slice2
slice4(result[4],cout[4],a[4],b[4],cout[3],op,binvert,1'b0);
alu_slice2
slice5(result[5],cout[5],a[5],b[5],cout[4],op,binvert,1'b0);
alu_slice2 slice6(result[6],cout[6],a[6],b[6],cout[5],op,binvert,1'b0);
alu_slice2
slice7(result[7],cout[7],a[7],b[7],cout[6],op,binvert,1'b0);
alu_slice2
slice8(result[8],cout[8],a[8],b[8],cout[7],op,binvert,1'b0);
alu_slice2
slice9(result[9],cout[9],a[9],b[9],cout[8],op,binvert,1'b0);
alu_slice2
slice10(result[10],cout[10],a[10],b[10],cout[9],op,binvert,1'b0);
alu_slice2
slice11(result[11],cout[11],a[11],b[11],cout[10],op,binvert,1'b0);
alu_slice2
slice12(result[12],cout[12],a[12],b[12],cout[11],op,binvert,1'b0);
alu_slice2
slice13(result[13],cout[13],a[13],b[13],cout[12],op,binvert,1'b0);
alu_slice2
slice14(result[14],cout[14],a[14],b[14],cout[13],op,binvert,1'b0);
alu_slice2
slice15(result[15],cout[15],a[15],b[15],cout[14],op,binvert,1'b0);
alu_slice2
slice16(result[16],cout[16],a[16],b[16],cout[15],op,binvert,1'b0);
alu_slice2
slice17(result[17],cout[17],a[17],b[17],cout[16],op,binvert,1'b0);
alu_slice2
slice18(result[18],cout[18],a[18],b[18],cout[17],op,binvert,1'b0);
alu_slice2
slice19(result[19],cout[19],a[19],b[19],cout[18],op,binvert,1'b0);
alu_slice2
slice20(result[20],cout[20],a[20],b[20],cout[19],op,binvert,1'b0);
alu_slice2
slice21(result[21],cout[21],a[21],b[21],cout[20],op,binvert,1'b0);
alu_slice2
slice22(result[22],cout[22],a[22],b[22],cout[21],op,binvert,1'b0);
alu_slice2
slice23(result[23],cout[23],a[23],b[23],cout[22],op,binvert,1'b0);
alu_slice2
slice24(result[24],cout[24],a[24],b[24],cout[23],op,binvert,1'b0);
alu_slice2
slice25(result[25],cout[25],a[25],b[25],cout[24],op,binvert,1'b0);
alu_slice2
slice26(result[26],cout[26],a[26],b[26],cout[25],op,binvert,1'b0);
alu_slice2
slice27(result[27],cout[27],a[27],b[27],cout[26],op,binvert,1'b0);
alu_slice2
slice28(result[28],cout[28],a[28],b[28],cout[27],op,binvert,1'b0);
alu_slice2
slice29(result[29],cout[29],a[29],b[29],cout[28],op,binvert,1'b0);
alu_slice2
slice30(result[30],cout[30],a[30],b[30],cout[29],op,binvert,1'b0);
alu_slice2MSB
slice31(result[31],set,overflow,a[31],b[31],cout[30],op,binvert,
1'b0);
endmodule
//
// Testbench for
second ALU. Material for this
testbench not covered.
module
test_alu();
wire [31:0]
result;
wire
overflow;
reg [31:0] a, b;
reg [2:0] alu_op;
alu2
alu(result,overflow,a,b,alu_op);
integer i, shadow_result,
shadow_overflow, as, bs;
initial
begin
alu_op =
alu.op_sub;
for(i=0;
i<10000; i=i+1) begin
as = $random;
a =
as;
bs = $random;
b = bs;
alu_op = ( $random & 32'h7fffffff ) % 5;
case( alu_op )
alu.op_and:
begin
shadow_result = as & bs;
shadow_overflow = 0;
end
alu.op_or:
begin
shadow_result = as | bs;
shadow_overflow = 0;
end
alu.op_add:
begin
shadow_result = as + bs;
shadow_overflow = as > 0 && bs > 0 && shadow_result
< 0
|| as < 0 && bs < 0 && shadow_result >
0;
end
alu.op_sub:
begin
shadow_result = as - bs;
shadow_overflow = as > 0 && bs < 0 && shadow_result
< 0
|| as < 0 && bs > 0 && shadow_result >
0;
end
alu.op_slt:
begin
shadow_result = as < bs;
shadow_overflow = 0;
end
endcase
#1;
if( shadow_result != result ) begin
$display("Wrong result op %d,
%d op %d = %d != %d",
alu_op, a, b, shadow_result, result);
$stop;
end
if( shadow_overflow != overflow ) begin
$display("Wrong overflow op %d,
%x op %x; %d !=
%d",
alu_op, a, b, shadow_overflow, overflow);
$stop;
end
end
$display("Done
with test.");
end
endmodule