我正在尝试编写一个 16 位 ALU。我已经编译成功了,但是当操作代码
alu_code
改变时,结果C
保持不变(第一个操作结果)
这是我的 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
这是测试平台:
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
C的波形就像我说的,不会随着操作的改变而改变。
提前致谢。
几个问题:
@(alu_code or A or B)
应该是 @*
,因为 C
取决于 C_add
、C_addu
、C_sub
、C_subu
,而不是直接 A
或 B
。通过在敏感度列表中使用 A
和 B
,您可以在分配 C
的 Always 块与 CLA 模块之间创建竞争条件。 @*
(或同义 @(*)
)是自动灵敏度,您应该对几乎所有组合块使用 always @*
。指定组合逻辑的敏感度列表仅应用于旧的 IEEE1364-1995 风格或模糊的不可综合总线功能模型中的编码。比 always @*
更好的是使用 SystemVerilog 的 always_comb
overflow_temp
上有多个驱动程序。如果驱动值存在冲突,结果将是x
。每个输出只能有一个驱动器。您可以与连接外部的其他逻辑进行 OR、MUX 或对输出执行其他逻辑。00010
和 00011
分别被视为十和十一。您需要为基数添加前缀才能将其视为二进制。代码应修改为包括:
// ...
wire [1:0] overflow_temp;
// ...
CLA add(.A(As), .B(Bs), .Sum(C_add), .overflow(overflow_temp[0]));
CLA addu(.A(A), .B(B), .Sum(C_addu), .overflow(overflow_temp[1]));
CLA sub(.A(As), .B(Bs2s), .Sum(C_sub), .overflow(overflow_temp[2]));
CLA subu(.A(A), .B(B2s), .Sum(C_subu), .overflow(overflow_temp[3]));
always @* begin
case(alu_code)
5'b00000 : C = C_add;
5'b00001 : C = C_addu;
5'b00010 : C = C_sub;
5'b00011 : C = C_subu;
endcase
end
assign over = {overflow_temp[alu_code], C[15]};
// ...
代码可能还有其他问题。这些反馈应该足以让我们朝着正确的方向前进。