【问题标题】:Substraction in VerilogVerilog中的减法
【发布时间】:2018-01-28 00:00:28
【问题描述】:

我正在研究一个 Verilog 定点加法器,我也将使用它来做减法。当我做减法时,我并不总是得到正确的结果。

例如,1-1=0,但我得到 -0。

请查看下面提到的代码:

`timescale 1ns/1ps

module adder #(
//Parameterized values
parameter Q = 27,
parameter N = 32
)
(
input [N-1:0] a,
input [N-1:0] b,
output [N-1:0] c
);

reg [N-1:0] res;

assign c = res;

always @(a,b) begin
// both negative or both positive
if(a[N-1] == b[N-1]) begin              //Since they have the same sign, absolute magnitude increases
    res[N-2:0] = a[N-2:0] + b[N-2:0];   //So just the two numbers are added
    res[N-1] = a[N-1];                  //and the sign is set appropriately...       
    end     
//  one of them is negative...
else if(a[N-1] == 0 && b[N-1] == 1) begin           //  subtracts a-b
    if( a[N-2:0] > b[N-2:0] ) begin                 //  if a is greater than b,
        res[N-2:0] = a[N-2:0] - b[N-2:0];   
        res[N-1] = 0;                               //  manually the sign is set to positive
        end
    else begin                                      //  if a is less than b,
        res[N-2:0] = b[N-2:0] - a[N-2:0];           // subtracting a from b to avoid a 2's complement answer
        if (res[N-2:0] == 0)
            res[N-1] = 0;                          //   To remove negative zero....
        else
            res[N-1] = 1;                         //        and manually the sign is set to negative
        end
    end
else begin                                       // subtract b-a (a negative, b positive)
    if( a[N-2:0] > b[N-2:0] ) begin             //  if a is greater than b,
        res[N-2:0] = a[N-2:0] - b[N-2:0];       //      subtracting b from a to avoid a 2's complement answer
        if (res[N-2:0] == 0)
            res[N-1] = 0;                                       
        else
            res[N-1] = 1;                       //      and manually the sign is set to negative
        end
    else begin                                 //   if a is less than b,
        res[N-2:0] = b[N-2:0] - a[N-2:0];       
        res[N-1] = 0;                                   
        end
    end
end
endmodule

加法器的测试平台如下:

`timescale 1ns/1ps

module tb_adder (
);

reg clk;
reg [ 31 : 0 ] a;
reg [ 31 : 0 ] b;

wire [ 31: 0 ] c;

adder adder_i (
    .a(a),
    .b(b),
    .c(c)
    );

parameter CLKPERIODE = 100;

initial clk = 1'b1;
always #(CLKPERIODE/2) clk = !clk;

initial begin

$monitor ("adder=%h", c);

#1
    a = 32'h08000000;
    b = 32'hF8000000;

  #(CLKPERIODE)
  $finish();

end

endmodule

由于我是 Verilog 的新手,我很难找到哪里出错了。我正在使用这个模块来计算定点算术中的泰勒级数。有什么建议吗?

【问题讨论】:

  • 在二进制补码数中没有 -0 这样的东西。这意味着你的代码是错误的。你为什么要重新发明减法?只需使用带符号的向量,- 运算符将为您完成所有工作,并且不会出错。
  • 您究竟是从哪里获得-0 的?哪个工具报告它?无论如何,正如前面的评论所解释的那样,verilog 中没有这样的东西。您应该能够在 verilog 中显示二进制/十六进制数字以了解发生了什么。
  • 即使您出于教育目的重新发明减法,它也过于复杂。 adder 只需要一个异或和一个与门
  • 从您的实现来看,您似乎假设输入是符号+幅度格式。除非有一个非常非常好的理由这样做,否则您应该像其他人指出的那样使用二进制补码。这将在 Verilog 中为您提供开箱即用的加法/减法等。
  • -0 只存在于恭维中。 a - ba + twos_compliment(b) 相同。最好的部分是 ab 都可以表示为正或负的两个恭维。

标签: verilog fixed-point


【解决方案1】:

我能找到代码产生脏零的唯一情况是两个输入本身都是脏零。即

a = b = 32'h80000000 = "-0"

看起来会发生这种情况,因为在这种情况下,您的代码将分支置于

if(a[N-1] == b[N-1]) begin              //Since they have the same sign, absolute magnitude increases

并且该分支与其他专门避免它的分支没有相同的检查。您可以通过将该代码移动到 always 块的末尾来解决此问题,这样无论之前采用哪个分支,它都会运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    相关资源
    最近更新 更多