对有符号数,取绝对值算法,Verilog实现

 

 

好的,下面是几种 Verilog 实现有符号数取绝对值的算法,包括不同复杂度和适用场景的实现方法。

1. 简单的条件判断 (使用 if-else 或三元运算符)

这是最直观、最易于理解的实现方法。 适用于小型的应用,对性能要求不高的情况。

module abs_signed_if_else (
  input  signed [31:0]  in_signed,
  output signed [31:0]  out_abs
);

  always @(*) begin
    if (in_signed < 0) begin
      out_abs = -in_signed;
    end else begin
      out_abs = in_signed;
    end
  end

endmodule

//  等价的三元运算符版本
module abs_signed_ternary (
  input  signed [31:0]  in_signed,
  output signed [31:0]  out_abs
);

  assign out_abs = (in_signed < 0) ? -in_signed : in_signed;

endmodule
1
  • 优点: 简单易懂,易于实现。
  • 缺点: 在 FPGA 中,if-else 语句通常会产生多路复用器 (mux),这可能会略微增加延迟。 对于关键路径,这种方案可能不是最优的。

 

2. 使用补码 (Two's Complement) 取反加一

对于有符号数,负数的补码是其绝对值的表示。 如果是负数,可以使用补码的特性,将其取反加一,就可以得到绝对值.

module abs_signed_twos_complement (
  input  signed [31:0]  in_signed,
  output signed [31:0]  out_abs
);

  assign out_abs = (in_signed[31] == 1'b1) ? (~in_signed + 1'b1) : in_signed;

endmodule
2
  • 优点: 比 if-else 稍微高效,减少了 MUX 的使用。 适合大多数场景。
  • 原理: 检查最高位 (符号位)。 如果为 1 (负数),进行取反加 1 (补码操作).
  • 说明: Verilog 中,取反操作 (~in_signed) 会对所有位进行取反,然后加 1 得到补码(即绝对值)。 加 1 的操作会根据情况产生进位。

3. 更高效的,使用 XOR 和加法

这种方法可以避免条件判断,效率更高。

module abs_signed_xor_add (
  input  signed [31:0]  in_signed,
  output signed [31:0]  out_abs
);

  wire [31:0] sign_bit;
  assign sign_bit = {31{in_signed[31]}}; // 符号位扩展

  assign out_abs = (in_signed ^ sign_bit) - sign_bit;

endmodule
3
  • 工作原理:

    1. 使用符号位扩展到整个宽度。
    2. 使用 XOR 运算。如果输入是正数,结果不变。如果输入是负数,所有位取反 (相当于取反码)。
    3. 减去符号位。 对于正数,减去 0 不变。 对于负数, 相当于取反码 +1 (相当于补码)。
  • 优点: 去掉了条件判断, 减少了 MUX 的使用, 提高处理速度。 对于 FPGA, 可以优化资源使用。

  • 说明: 这是一种常用的优化方法, 避免了分支预测的开销。

4. 混合方案(结合补码和移位)

这种方法结合了取反和移位操作,用于某些特定场景。

module abs_signed_shift_complement (
  input  signed [31:0]  in_signed,
  output signed [31:0]  out_abs
);

  wire [31:0] neg_in;
  assign neg_in = ~in_signed + 1'b1;

  assign out_abs = (in_signed[31] == 1'b1) ? neg_in : in_signed;

endmodule
4
  • 原理: 和补码实现类似,先对负数取符号位,然后取反加一。
  • 效率: 与使用补码相近,但实现方式不同。

选择哪种实现方式?

  • 简单性: 对于小型设计或者原型验证,使用 if-else 或者三元运算符版本是最简单的。
  • 性能: 对于关键路径,建议采用使用 XOR 和加法的方案,或者补码方案.
  • 资源: 考虑你的 FPGA 的资源使用。 测试不同的实现方式,并查看综合后的资源占用情况。
  • 位宽: 上述所有代码都适用于不同位宽的数据。 只需要改变参数中的位宽即可。

如何使用这些模块?

  1. 例化模块: 在你的 Verilog 设计中例化这些模块。
  2. 连接信号: 将有符号输入信号连接到模块的 in_signed 端口,将绝对值输出信号连接到 out_abs 端口。
  3. 仿真: 使用 Verilog 仿真器来验证这些模块的功能。
  4. 综合和实现: 将你的设计综合、实现到 FPGA 中。

示例

module top;

  // 测试信号
  reg signed [31:0] test_in;
  wire signed [31:0] abs_out_if_else;
  wire signed [31:0] abs_out_twos_complement;
  wire signed [31:0] abs_out_xor_add;
  wire signed [31:0] abs_out_shift_complement;


  // 例化模块
  abs_signed_if_else u_abs_if_else (
    .in_signed(test_in),
    .out_abs(abs_out_if_else)
  );

  abs_signed_twos_complement u_abs_twos_complement (
    .in_signed(test_in),
    .out_abs(abs_out_twos_complement)
  );
  abs_signed_xor_add u_abs_xor_add (
    .in_signed(test_in),
    .out_abs(abs_out_xor_add)
  );
  abs_signed_shift_complement u_abs_shift_complement (
    .in_signed(test_in),
    .out_abs(abs_out_shift_complement)
  );

  // 仿真激励
  initial begin
    test_in = -10;
    #10; // 10ns 后
    $display("Test Input: %d, abs_if_else: %d, abs_twos_complement: %d, abs_xor_add: %d, abs_shift_complement: %d",
              test_in, abs_out_if_else, abs_out_twos_complement, abs_out_xor_add, abs_out_shift_complement);

    test_in = 5;
    #10;
    $display("Test Input: %d, abs_if_else: %d, abs_twos_complement: %d, abs_xor_add: %d, abs_shift_complement: %d",
              test_in, abs_out_if_else, abs_out_twos_complement, abs_out_xor_add, abs_out_shift_complement);

     test_in = -2147483648; // 最小的负整数
    #10;
    $display("Test Input: %d, abs_if_else: %d, abs_twos_complement: %d, abs_xor_add: %d, abs_shift_complement: %d",
              test_in, abs_out_if_else, abs_out_twos_complement, abs_out_xor_add, abs_out_shift_complement);

    $finish;
  end

endmodule
View Code
  • 仿真结果: 会输出不同输入值的绝对值,验证功能的正确性。

总结:

选择最合适的绝对值算法取决于你的特定需求。 如果性能非常关键,xor_add 方法通常是最佳选择。 如果简单和可读性更重要,if-else 或补码操作就足够了。 在实际使用中,请务必进行测试和验证,以确保算法的正确性和性能符合你的要求。

 

来自gpt-4

posted on 2025-08-21 09:46  taylorrrrrrrrrr  阅读(307)  评论(0)    收藏  举报