/// LSU EE 3755 Computer Organization

//

/// Verilog Notes 5 Fall 2004

 

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

 

// :PH: 4.5

 

// /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 :PH: 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 :PH: 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 :PH: Figure 4.17.Input less is

// generated by MSB slice which is alu_slice2MSB (set output of ALU31 of

// PH: Figure 4.18 which is fed to less input of ALU0)

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