You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

16位ALU故障:操作码alu_code变更后输出C始终不变

问题

编写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确实不会随操作码的变更而改变。


问题分析与解决方案

核心问题点

  • 信号冲突:四个CLA实例同时驱动同一个overflow_temp信号,硬件层面会出现线与/线或冲突,导致信号值不确定,进而干扰后续逻辑。
  • 敏感列表不完整:第一个always块仅监听alu_code、A、B,但C_add、C_addu等运算结果变化时无法触发块执行,C自然不会更新。
  • 溢出逻辑错误:用同一个overflow_temp处理四种运算的溢出,逻辑完全失效,每种运算的溢出状态需要独立判断。

修改方案

  1. 给每个CLA实例分配独立的溢出信号,避免信号冲突。
  2. 将第一个always块改为@(*)自动敏感列表,确保所有相关信号变化时都能触发更新。
  3. 针对不同运算类型,在case分支里直接绑定对应运算的溢出信号。
  4. 修正CLA4bit中运算优先级的括号缺失问题,避免逻辑错误。

修改后的完整代码

module ALU (
    input [15:0] A, B,
    input [4:0] alu_code,
    output reg [15:0] C,
    output reg overflow
);

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;
// 为每个CLA实例分配独立的溢出信号
wire overflow_add, overflow_addu, overflow_sub, overflow_subu;

assign B2s = ~B + 1;
assign As = A;
assign Bs = B;
assign Bs2s = ~Bs + 1;

// 每个CLA实例连接独立的溢出输出
CLA add(.A(As), .B(Bs), .Sum(C_add), .overflow(overflow_add));
CLA addu(.A(A), .B(B), .Sum(C_addu), .overflow(overflow_addu));
CLA sub(.A(As), .B(Bs2s), .Sum(C_sub), .overflow(overflow_sub));
CLA subu(.A(A), .B(B2s), .Sum(C_subu), .overflow(overflow_subu));

// 使用@(*)自动敏感列表,覆盖所有输入信号
always @(*) begin
    case(alu_code)
        5'b00000 : begin
            C = C_add;
            overflow = overflow_add;
        end
        5'b00001 : begin
            C = C_addu;
            overflow = overflow_addu;
        end
        5'b00010 : begin
            C = C_sub;
            overflow = overflow_sub;
        end
        5'b00011 : begin
            C = C_subu;
            overflow = overflow_subu;
        end
        default : begin // 增加默认分支,避免综合警告
            C = 16'h0;
            overflow = 1'b0;
        end
    endcase
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 

优化后的测试平台(可选)

添加$monitor实时打印信号,方便观察运算结果变化:

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
    $monitor("Time=%0t, alu_code=%b, A=%h, B=%h, C=%h, overflow=%b", $time, alu_code, A, B, C, overflow);
    A = 16'h00AA; B = 16'h00AA; // 扩展为16位,避免高位默认0的歧义
    #50; alu_code = 5'b00000;
    #50; alu_code = 5'b00001;
    #50; alu_code = 5'b00010;
    #50; alu_code = 5'b00011;
    #50; $finish;
end
endmodule 

内容的提问来源于stack exchange,提问作者JarvisLYu1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 13:27:02