verilog中移位操作时,有符号数和无符号数的区别


原文链接(相关文章合集)OFDM 802.11a的xilinx FPGA实现

1.前言

前面OFDM 802.11a的FPGA实现中的文章在涉及到加窗操作的时候,使用到了移位操作,但是没有考虑到有符号数的问题,今天发现了这一问题,特详细对verilog中移位操作时,有符号数和无符号数的区别进行讲解,并且设计补码、反码、原码的知识。

image

2.Verilog的移位运算符分类:

逻辑移位:>>/<<。

逻辑左移右移代表不管符号位,整体做移动。

算数移位:>>>/<<<。

算术左移右移代表保留符号位不动。

两者都是非循环的移位操作。

若移位赋值目标位数多于源数据,对于有符号数右移,先拿符号位填充多出的bit位再按照下面的移位运算方式进行运算。

对于无符号数,逻辑移位和算数移位的效果完全一致。空缺拿0来补充。

2.1算数移位

算数右移(>>>)

当移位数据为有符号数,高位补符号位。

当移位数据为无符号数,高位补0。

算数左移(<<<)

有符号数与无符号数效果一致,空缺拿0来补充。

2.1逻辑移位

逻辑右移(>>)

不论移位数据为有符号数、无符号数,高位补零。

逻辑左移(<<)

有符号数与无符号数效果一致,空缺拿0来补充。

2.Verilog中的移位运算符易错点

对于左移,有符号数与无符号数效果一致,空缺拿0来补充,唯一需要注意的是溢出问题,这个使用的时候很容易想到,不多做赘述。

而对于逻辑右移:“>>”

不区分无符号和有符号移位,即对有符号和无符号数进行">>"操作结果一致。

对有符号数使用">>“进行右移,高位补"0”;

对无符号数使用">>“进行右移,高位补"0”;

**如果有符号数,直接使用“>>”,会导致计算结果错误,比如:

a = -6;
//其原码为: 4'b1110;
//负数以补码形式存储(原码除符号位取反+1),
//补码为4'b1010
//若
b = a >> 1;
//得到
b = 4'b0101;
//此时b = 5,正确的值应该是-3才对

对于算术右移:“>>>”

区分无符号和有符号移位,即对有符号和无符号数进行">>>"操作结果不一样。

对有符号数使用">>>"进行右移,高位补符号位;

对无符号数使用">>>“进行右移,高位补"0”;

a = -6//其原码为: 4'b1110;
//负数以补码形式存储(原码取反+1),补码为4'b1010
//若
b = a >>> 1;
//得到
b = 4'b1101;
//此时b的原码为(补码除符号位取反+1)//4'b1011,对应的值为-3
//此时的结果才是正确的

但是,你以为只是简单的在你想得到有符号的结果时用“>>>”就会正确吗?那就大错特错了!!!!

之前做的设计,在加窗时需要用到除以2,即右移一位操作,我简单的使用了“>>”。由于只对其中个别数据进行这一操作,运气好,没遇到负数,所以之前仿真的时候也没出现问题。

OFDM802.11a的FPGA实现(十三)加窗(含verilog和matlab代码)

OFDM802.11a的FPGA实现(十五)短训练序列:STS(含Matlab和verilog代码

直到后面在设计长训练序列(LTS)时,遇到了负数,此时怎么也对不上结果。

STS_dout <= {Short_Mem[0][15:8]>>1,Short_Mem[0][7:0]>>1};

即使改成算术右移:“>>>”也不管用。

STS_dout <= {Short_Mem[0][15:8]>>>1,Short_Mem[0][7:0]>>>1};

因为如果操作数是无符号的,使用“>>”和">>>“都是逻辑移位,会导致结果错误。

3.定义数据类型为signed或使用$signed

在verilog中有时会用signed修饰符来修饰定义的数据,运算的时候也会用 s i g n e d ()任务来强制转换数据,那么 s i g n e d 的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?其实不是的,因为有符号数和无符号数据在做运算时,电路结构是一样的, signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?其实不是的,因为有符号数和无符号数据在做运算时,电路结构是一样的, signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?其实不是的,因为有符号数和无符号数据在做运算时,电路结构是一样的,signed()的真正作用是决定如何对操作数扩位的问题。

对于verilog中的移位操作signed修饰的时候,高位会进行补符号位操作。

对于verilog中的加法和乘法操作,会先对操作数据扩位成结果相同的位宽,然后进行加法或者乘法处理。比如a/b都为4位数据,c为5位数据,c = a + b,这个运算的时候会先把a和b扩位成5位,然后按照无符号加法进行相加。a/b没有被signed修饰的时候会按照无符号数的扩位方式进行扩位,即高位补0,加法的结果当然也是a、b为无符号数相加的结果。

所以说正确的代码应该如下:

STS_dout <= {$signed(Short_Mem[0][15:8])>>>1,$signed(Short_Mem[0][7:0])>>>1};

前面展示的代码链接:

OFDM802.11a的FPGA实现(十三)加窗(含verilog和matlab代码)

OFDM802.11a的FPGA实现(十五)短训练序列:STS(含Matlab和verilog代码
需要更正这节所提到的问题,才能保证后期不出错误。

原文链接(相关文章合集)OFDM 802.11a的xilinx FPGA实现

  • 21
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog,有符号数的移位可以通过算术右移实现。算术右移需要考虑符号位,右移一位,如果符号位为1,则在左边补1;否则,补0。这种移位操作可以进行有符号数的除法运算,每右移一位相当于除以2的n次方。 Verilog语言可以使用移位减方式实现64位除以32位数据的除法器。这种方式资源消耗较少,运算速度约为64个钟周期,也可以方便地自动修改运算位数。 在Verilog,使用移位运算符进行移位操作。a >> n表示逻辑右移,左边补零;a << n表示逻辑左移,右边补零。这两种移位运算都用0来填补移出的空位。 举个例子来说明:假设有一个有符号数start,初始值为0001,我们进行start << 2移位操作移位后start的值为0100,然后赋给result。这样就实现了有符号数的移位操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Verilog 移位(算术移位, 逻辑移位, 循环移位)](https://blog.csdn.net/Reborn_Lee/article/details/89813616)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [FPGA 64位除法器(Verilog)](https://download.csdn.net/download/XingouChen/13216328)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值