I am trying to write a 16-bit ALU. I have compiled everything successfully, but when the operation code alu_code changes, the result C stays the same (the first operation result).
Here's my code for ALU:
module ALU (
input [15:0] A, B,
input [4:0] alu_code,
output reg [15:0] C,
output reg overflow
);
wire [1:0] over;
wire signed [15:0] As, Bs, Bs2s;
wire signed [15:0] C_add, C_sub;
wire [15:0] C_addu, C_subu;
wire [15:0] B2s;
wire overflow_temp;
assign B2s = ~B + 1;
assign As = A;
assign Bs = B;
assign Bs2s = ~Bs + 1;
CLA add(.A(As), .B(Bs), .Sum(C_add), .overflow(overflow_temp));
CLA addu(.A(A), .B(B), .Sum(C_addu), .overflow(overflow_temp));
CLA sub(.A(As), .B(Bs2s), .Sum(C_sub), .overflow(overflow_temp));
CLA subu(.A(A), .B(B2s), .Sum(C_subu), .overflow(overflow_temp));
always @(alu_code or A or B) begin
case(alu_code)
00000 : C = C_add;
00001 : C = C_addu;
00010 : C = C_sub;
00011 : C = C_subu;
endcase
end
assign over = {overflow_temp, C[15]};
always @(*) begin
if (over == 2'b01) overflow = 1;
else overflow = 0;
end
endmodule
module CLA (
input [15:0] A, B,
output [15:0] Sum,
output overflow
);
wire c1, c2, c3;
CLA4bit CLA1 (.A(A[3:0]), .B(B[3:0]), .Cin(1'b0), .Sum(Sum[3:0]), .Cout(c1));
CLA4bit CLA2 (.A(A[7:4]), .B(B[7:4]), .Cin(c1), .Sum(Sum[7:4]), .Cout(c2));
CLA4bit CLA3(.A(A[11:8]), .B(B[11:8]), .Cin(c2), .Sum(Sum[11:8]), .Cout(c3));
CLA4bit CLA4(.A(A[15:12]), .B(B[15:12]), .Cin(c3), .Sum(Sum[15:12]), .Cout(overflow));
endmodule
module CLA4bit(
input [3:0] A, B,
input Cin,
output [3:0] Sum,
output Cout
);
wire [3:0] P, G, C;
assign P = A ^ B;
assign G = A & B;
assign C[0] = Cin;
assign C[1] = G[0] | (P[0] & C[0]);
assign C[2] = G[1] | (P[1] & G[0]) | P[1] & P[0] & C[0];
assign C[3] = G[2] | (P[2] & G[1]) | P[2] & P[1] & G[0] | P[2] & P[1] & P[0] & C[0];
assign Cout = G[3] | (P[3] & G[2]) | P[3] & P[2] & G[1] | P[3] & P[2] & P[1] & G[0] | P[3] & P[2] & P[1] & P[0] & C[0];
assign Sum = P ^ C;
endmodule
Here is the testbench:
module tbALU();
reg [15:0] A, B;
reg [4:0] alu_code;
wire [15:0] C;
wire overflow;
ALU uut(A, B, alu_code, C, overflow);
initial begin
A = 8'hAA; B = 8'hAA;
#50; alu_code = 0;
#50; alu_code = 1;
#50; alu_code = 2;
#50; alu_code = 3;
end
endmodule
The waveform of C is just like what I said; it never changes corresponding to change of operation.
A couple of issues:
@(alu_code or A or B)should be@*asCdepends onC_add,C_addu,C_sub,C_subuand not directlyAorB. By usingAandBin the sensitivity list, you create a race condition between the always block that assignsCand the CLA modules.@*(or synonymous@(*)) is automatic sensitivity, and you should usealways @*for just about all combinational blocks. Specify the sensitivity list for combinational logic is should only be used for coding in the old IEEE1364-1995 style or obscure non-synthesizable bus-functional-models. Better thanalways @*would be to use SystemVerilog'salways_comboverflow_temp. If there are conflicting values being driven, the result will bex. There should be only one driver per output. You can OR, MUX, or perform other logic to the output with other logic outside of the connection.casestatement has00010and00011which is treated as ten and eleven respectively. You need to prefix the radix to have it treated as binary.The code should be modified to include:
There might be other issues with the code. This feedback should be enough to get in in the correct direction.