systemverilog中的组合逻辑“IF”和“assign”语句

时间:2015-02-27 13:33:19

标签: system-verilog alu

我在设计ALU时发现了一种非常奇怪的行为,希望有人可以看看它并告诉我发生了什么。

这是代码

module adder (
output logic signed[31:0] y,
output logic Cout,
input logic signed[31:0] a, b,
input logic Cin, sub
);

logic [31:0] adder_b;

assign adder_b = b ^ {32{sub}};
assign {Cout, y} = {a[31],a} + {adder_b[31],adder_b} +Cin;

endmodule

////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////



module andlogic (
output logic [31:0] y,
input logic [31:0] a, b
);

assign y = a & b;

endmodule



////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////

module orlogic (
output logic [31:0] y,
input logic [31:0] a, b
);

assign y = a | b;

endmodule

////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////


module xorlogic (
output logic [31:0] y,
input logic [31:0] a, b
);

assign y = a ^ b;

endmodule


///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////

module ALU(
output logic signed[31:0] Result,
output logic N,Z,C,V,
input logic signed[31:0] a, b,
input logic [2:0] ALU_control
);

wire [31:0] adder_rlt, and_rlt, or_rlt, xor_rlt;
logic Cin;


adder adder (
        .y (adder_rlt),
    .a (a),
    .b (b),
    .Cin (Cin),
    .Cout (Cout),
    .sub (sub)
);

andlogic andlogic (
        .y (and_rlt),
    .a (a),
    .b (b)
);

orlogic orlogic (
        .y (or_rlt),
    .a (a),
    .b (b)
);

xorlogic xorlogic (
        .y (xor_rlt),
    .a (a),
    .b (b)
);


assign C = Cout;
assign sub = ALU_control[1];
assign Cin = ALU_control[1];
assign N = Result[31];
//assign Z = (Result ==0 )? 1:0;
assign V = {{~a[31]} & {~b[31]} & Result[31]}|{a[31] & b[31] & {~Result[31]}};

always_comb
begin 

 if (Result == 0)   Z = 1;
 else   Z = 0;

 case(ALU_control)

 3'b001:  Result = adder_rlt;

 3'b010:  Result = adder_rlt;

 3'b011:  Result = and_rlt;

 3'b100:  Result = or_rlt;

 3'b101:  Result = xor_rlt;

 default: Result = 0;

 endcase

end

endmodule   

前4个模块是我的ALU的单独功能,加法器包含加法和减法。然后这是奇怪的事情:

我的ALU有4个标志,Z表示零,它在输出Result的值为0时设置。如果我使用这些代码来描述Z的行为

always_comb
begin 

 if (Result == 0)   Z = 1;
 else   Z = 0;

模拟结果错误,Z有些时间为1,有些时间为0,看起来根本不依赖于Result的值。

更奇怪的是合成结果的结果。这张图显示了我的synplify综合结果的一部分。

Synthesis result

门级看起来正确,Z是所有反转结果信号的AND门,当Result == 0时,输出Z应为1.

但是,我昨天整个下午都试着弄清楚如何修复这个错误,我想说如果我使用assign语句而不是使用if语句,那么模拟会给出正确的行为。 assign Z = (Result ==0 )? 1:0;

我认为这两个版本描述Z应该是一样的!我使用

修改代码后
assign Z = (Result ==0 )? 1:0;

合成结果仍与上图所示相同......

有人可以告诉我发生了什么事吗? 非常感谢!!!

1 个答案:

答案 0 :(得分:4)

我认为问题在于您的操作顺序。 always_comb块从上到下以程序方式执行。在模拟中,Z首先使用现有值Result进行更新(从上一次执行always块开始)。 Result已更新,Z未重新评估。 Result不是敏感列表的一部分,因为它是左手值。因此,在分配Z的信号发生变化之前,Result不会更新。

合成不同,它连接等效逻辑门,可能导致异步反馈。逻辑等价物与功能等价物不同。这就是为什么综合为您提供逻辑上的意图,RTL模拟给出了您的功能写作。解释差异的原因超出了本问题的范围。

编写RTL组合块时,只需做一点自我检查并问自己:

  • 此单次传递结束时的值是否始终阻止预期的最终值?如果不是,请重新安排代码。
  • 使用此always-block中的任何当前值是否会在下一次传递中分配任何值?如果是,请重新排列代码或与触发器同步。

在ALU的情况下,tt是一个简单的解决方案。变化:

always_comb begin
  if (Result==0) Z = 1;  // <-- Z is evaluated using the previous value of Result
  else Z = 0;

  /*Logic to assign Result*/ // <-- change to Result does not re-trigger the always 
end

要:

always_comb begin
  /*Logic to assign Result*/  // <-- update Result first

  if (Result==0) Z = 1; // <-- Z is evaluated using the final value of Result
  else Z = 0;
end

另一种解决方案(我 非常不鼓励 )是将always_comb替换为IEEE1364-1995组合逻辑。灵敏度列表是手动定义的。您可以在此处添加Result以获取反馈更新:

always @(ALU_control or adder_rlt or add_rlt or or_rtl or xor_rtl or Result)

高度劝阻 因为很容易错过必要的信号,unessary信号浪费模拟时间,造成零时无限循环的风险,你仍然没有获得RTL和综合之间的保证功能等价物。