Verilog负数赋值与加法运算
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
一、Verilog中如何给一个变量赋值为一个负数
Verilog中默认reg和wire中存放的是>=0的数如果要存放一个负数需要加关键字signed下面通过一个自加器的Modelsim仿真来了解一下如果不加signed直接赋值会发生什么。
add1和add2是两个简单的自加器。初始值-20步长为2flag信号用来判断是否是负数。关于flag_add1和flag_add2的产生逻辑如下列代码所示
reg signed [7:0] add1;
reg [7:0] add2;
reg flag_add1;
reg flag_add2;
initial begin
clk= 0;
add1=-20;
add2=-20;
forever clk=#5 ~clk ;
end
always@(posedge clk)
if(add1>0)
flag_add1<=1;
else
flag_add1<=0;
always@(posedge clk)
if(add2>0)
flag_add2<=1;
else
flag_add2<=0;
仿真结果如下图所示
可见在Modelsim中add1与add2显示均为8’b1110_1100这是补码形式的-20,说明二者在代码上没有区别但是两者的flag出现了不同的情况被signed定义过的add1其add1_flag值为0说明Verilog认为这是一个负数。而add2_flag值为1说明未经过signed定义Verilog不认为这是一个负数。
二、Verilog中如何进行负数的加减运算
首先明确两点:
①Verilog运算中会自动进行扩位将所有参与运算的变量位宽自动调整为位宽最高者的位宽所谓“调整”即是高位补足若有signed定义的变量自动补符号位若没有signed自动补0。
②运算时右边全为signed定义变量才按照符号位补全不做特定描述的常数也为signed类型否则按照无符号数自动补零。
举个粗糙的例子说明
代码A
reg a=1;
reg signed [5:0] b=6’b10_1010;
reg [6:0] c=7’b101_1010;
reg [7:0] d;
d <= a + b + c ;
上述参与运算的a,b,c,d位宽最高是d(8bit),所以运算时a,b,c要自动补足即a=8’b0000_0001;b是signed定义过但是右边存在a,c这种无符号变量所以b自动变为无符号变量补0即b=8’b0010_1010;c补0即c=8’b0101_1010;
Modelsim仿真如下d显示全部按照高位补0 的运算结果
同时再来关注一下a,b,c,d代表的十进制数如下图a所示Modelsim默认把二进制数当做有符号数显示所以看起来好像是-1-22-38=-123但是本次运算是无符号运算所以改为unsigned显示即可显示正确结果(图b)。
图a
图b
代码B
reg signed a=1;
reg signed [5:0] b=6’b10_1010;
reg signed [6:0] c=7’b101_1010;
reg signed [7:0] d;
d <= a + b + c ;
仿真结果如下图所示
与代码A的区别是a,b,c,d全部定义为signed有符号类型此时运算显示按照高位补符号位1的运算结果。再来关注一下a,b,c,d代表的十进制数首先分析a,在下图中可见其值是“-1”原因是1的位宽只有1位它的符号位也是1所以高位补足之后有符号数a=8’b1111_1111注意这是一个补码表示因为verilog存储有符号数皆用补码表示其源码是8’b1000_0001,即是“-1”。再看bModelsim认为这是-22。因为在定义时signed b=6’b10_1010,相当于手动输入了一个补码如果定义signed b=-22,计算机也会给其存储为10_1010。其原码是有符号数11_0110=-22。c,d同理。
另外需要注意不做特定描述的常数也为signed类型参考在代码B中赋值运算右边add“+2”a,b,c也会按照高位补符号位进行运算。