【FPGA数学运算】verilog无符号数与有符号数,怎么才能不用错?

本文转载自:FPGA入门到精通微信公众号

FPGA开发中涉及到数学运算,那理解和掌握无符号数和有符号数就非常重要了,如果用错了,就容易出一些奇怪的错误。

今天我们来聊一聊verilog中的“有符号数”和“无符号数”。

文末会总结使用要点给大家参考。

一、原码、反码、补码

1、原码

原码是数字在计算机中的二进制表示形式,包括符号位和数值位。

对于正数,原码与其真值(即十进制数)相同。

对于负数,原码是其在补码表示下的反码再加 1。

2、反码

反码是原码的符号位除外,其余位取反。

无论正负,反码都是原码的反转。

3、补码

补码是反码再加 1。

对于正数,补码与原码相同;

对于负数,补码是其在反码表示下的加 1。

二、有符号数与无符号数

实际上FPGA运行逻辑中是不区分二进制数是“正”还是“负”的,它就是一个二进制数而已,对于正数或无符号数,存储的就是原码,对于负数,存储是补码。

1、有符号数

在有符号数中,最高位(最左边的位)用作符号位,1 表示负数,0 表示正数。

例如,一个 8 位的有符号整数可以表示范围为 -128 到 127 的整数。

2、无符号数

无符号数则没有符号位,所有的二进制位都用于表示数值。

无符号整数的取值范围通常是从 0 到 2 的 n 次方 -1,其中 n 是二进制位的位数。

例如,一个 8 位的无符号整数可以表示范围为 0 到 255 的整数。

三、加法与减法

1、加法运算

可以使用位运算或者真值运算实现。

写代码时要注意进位,防止溢出,另外有符号数还要注意位宽问题,可能需要复制符号位。

无符号数计算:

reg [7:0] a = 127;

reg [7:0] b = 127;

reg [8:0] c;

always@(posedge clk)

c <= a + b;

有符号数计算需要注意复制符号位

reg [7:0] a = -5;

reg [7:0] b = -6;

reg [8:0] c;

always@(posedge clk)

c <= {a[7], a} + {b[7], b};

2、减法运算

减法运算,实质是 a-b可转换为 a + b[补码]。

和加法一样,写代码时要注意进位,防止溢出,另外有符号数还要注意位宽问题,可能需要复制符号为。

四、Verilog中的Signed本质及用法

1、定义

在verilog中,有符号数可以加“signed”关键词来修饰,表示这个寄存器或变量是有符号数,没有加“signed”修饰,默认就是无符号数。

例如:

reg signed [7:0] a; // 定义一个 8 位的有符号整数变量 a

2、数学运算处理

在进行加法、减法、乘法等运算时,有符号数和无符号数会有不同的处理方式。

加了signed关键词的本质是运算时,会先将数据扩位至相同的位宽,然后按照有符号数的运算规则进行处理。

这里要注意了,有符号数和无符号数不能混合运算,否则容易出错;

(1)如果运算时,变量都加了signed关键词。

reg signed [7:0] a = -10;

reg signed [7:0] b = 5;

reg signed [8:0] c;

always@(posedge clk)

c <= a + b;

仿真结果:

分析:结果正确。

(2)如果运算时,无符号和有符号混合运算了。

reg signed [7:0] a = -10;

reg [7:0] b = 5;

reg signed [8:0] c;

always@(posedge clk)

c <= a+b

仿真结果:

分析:实际是按无符号数运算的。

五、总结

无符号数运算时,主要注意防止出现结果溢出。

有符号数运算是,注意符号位的处理,可以加关键字“signed”,也可以自己控制符号位复制来参与运算。

有符号数和无符号数不要混合运算,否则容易出错。

最新文章

最新文章