// Testbench
module stimulus();
reg [2:0] A, B, C, D;
reg C_IN;
wire [2:0] OUT;
wire C_OUT;
mac my_mac ( .out(OUT), .c_out(C_OUT), .a(A), .b(B), .c(C), .d(D), .c_in(C_IN));
// Set up the monitoring for the signal values
initial
begin
$monitor($time," A= %d, B=%d, C=%d, D=%d, --- C_OUT= %d, OUT= %d\n",
A, B, C, D, C_OUT, OUT);
end
// Stimulate inputs
initial
begin
C_IN = 1'b0;
A = 4'd1; B = 4'd1; C = 4'd1; D = 4'd1;
#5 A = 4'd2; B = 4'd1; C = 4'd1; D = 4'd2;
#5 A = 4'd1; B = 4'd1; C = 4'd2; D = 4'd1;
#5 A = 4'd2; B = 4'd2; C = 4'd2; D = 4'd2;
end
endmodule
// Multiply Accumulate Unit
module mac(out, c_out, a, b, c, d, c_in);
// Input and output declarations (Interface)
output [2:0] out;
output c_out;
input [2:0] a, b, c, d;
input c_in;
// Dummy wires (Internals)
wire [5:0] p1, p2;
// Multipliers
multiplier M1(p1, a, b);
multiplier M2(p2, c, d);
// Adder
cla_add A1(out, c_out, p1[5:3], p2[5:3], c_in);
endmodule
// 3-bit Multiplier
module multiplier(p, a, b);
// Input and output declarations (Interface)
output [5:0] p;
input [2:0] a, b;
// Dummy wires (Internals)
wire a1b0, a2b0, c10, c11, c20, c21, s11, s12;
// Instantiate gate logic gate primitives
and (p[0], a[0], b[0]);
and (a1b0, a[1], b[0]);
and (a2b0, a[2], b[0]);
// Instantiate units with half adders
basic_cell_halfadd bc_ha1(p[1], c10, a[0], b[1], a1b0);
basic_cell_halfadd bc_ha2(p[2], c20, a[0], b[2], s11);
basic_cell_halfadd bc_ha3(s12, c12, a[2], b[1], c11);
// Instantiate units with full adders
basic_cell_fulladd bc_fa1(s11, c11, a[1], b[1], a2b0, c10);
basic_cell_fulladd bc_fa2(p[3], c21, a[1], b[2], s12, c20);
basic_cell_fulladd bc_fa3(p[4], p[5], a[2], b[2], c12, c21);
endmodule
// Basic cell of the multiplication unit with full adder
module basic_cell_fulladd(sum_out, c_out, a, b, sum_in, c_in);
// Input and output declarations (Interface)
output sum_out, c_out;
input a, b, sum_in, c_in;
//Dummy wires (Internals)
wire ab;
and (ab, a, b);
fulladd FA(sum_out, c_out, ab, sum_in, c_in);
endmodule
// Basic cell of the multiplication unit with half adder
module basic_cell_halfadd(sum_out, c_out, a, b, sum_in);
// Input and output declarations (Interface)
output sum_out, c_out;
input a, b, sum_in;
//Dummy wires (Internals)
wire ab;
and (ab, a, b);
halfadd HA(sum_out, c_out, ab, sum_in);
endmodule
// 3-bit Carry Lookahead Adder
module cla_add(sum, c_out, a, b, c_in);
// Input and output declarations (Interface)
output [2:0] sum;
output c_out;
input [2:0] a,b;
input c_in;
// Dummy wires (Internals)
wire p0,g0, p1,g1, p2,g2;
wire c1, c2, c3;
wire d1, d2, d3, d4, d5, d6;
// computation of the carry propagated for each stage
xor (p0,a[0],b[0]);
xor (p1,a[1],b[1]);
xor (p2,a[2],b[2]);
// computation of the carry generated for each stage
and (g0,a[0],b[0]);
and (g1,a[1],b[1]);
and (g2,a[2],b[2]);
// computation of the carry for each stage
and (d1,p0,c_in);
or (c1,g0,d1);
and (d2,p1,g0);
and (d3,p1,p0,c_in);
or (c2,g1,d2,d3);
and (d4,p2,g1);
and (d5,p2,p1,g0);
and (d6,p2,p1,p0,c_in);
or (c3,g2,d4,d5,d6);
// computation of the sum
xor (sum[0],p0,c_in);
xor (sum[1],p1,c1);
xor (sum[2],p2,c2);
// Assign carry output
assign c_out = c3;
endmodule
// 1-bit Full Adder
module fulladd(sum, c_out, a, b, c_in);
// I/O port declarations
output sum, c_out;
input a, b, c_in;
// Internal nets
wire s1, c1, c2;
// Instantiate logic gate primitives
xor (s1, a, b);
and (c1, a, b);
xor (sum, s1, c_in);
and (c2, s1, c_in);
xor (c_out, c2, c1);
endmodule
// 1-bit Half Adder
module halfadd(sum, c_out, a, b);
// I/O port declarations
output sum, c_out;
input a, b;
// Instantiate logic gate primitives
xor (sum, a, b);
and (c_out, a, b);
endmodule