Verilog 16位ALU,尝试改变运算代码,结果还是一样

问题描述 投票:0回答:1

我正在尝试编写一个 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的波形就像我说的,不会随着操作的改变而改变。

提前致谢。

verilog modelsim alu
1个回答
0
投票

几个问题:

  • @(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 或对输出执行其他逻辑。
  • case 语句有
    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]};

// ...

代码可能还有其他问题。这些反馈应该足以让我们朝着正确的方向前进。

© www.soinside.com 2019 - 2024. All rights reserved.