Verilog中的逻辑位移与算术位移的区别

一、起源

在菜鸟教程学习Verilog语法的时候,在移位操作符下面给出了一个实例,就是下面这个:

A = 4'b1100 ;
B = 4'b0010 ;
A = A >> 2 ;        //结果为 4'b0011
A = A << 1;         //结果为 4'b1000
A = A <<< 1 ;       //结果为 4'b1000
C = B + (A>>>2);    //结果为 2 + (-4/4) = 1, 4'b0001

总是感觉不对劲,因此在vivado上面跑了一下,越跑越迷糊,这是得到的波形,完全和结果对应不上,最后得到的C结果为5,这是为什么呢??? 

二、过程

这是我最开始的对变量的定义:

reg [3:0]A;
reg [3:0]B;
reg [3:0]C;

猜想是不是因为没有定义signed类型的原因, 于是对于要应用算术位移的A变量定义为了signed类型,reg signed[3:0] A:

也就是说,其实这儿并没有把算术位移应用进去,然后就越来越混乱,因为结果也没有改变。。。那么算术位移到底在什么情况下会应用呢?

根据实际情况,定义了以下几个变量,同时考虑正负的问题:

reg Clk;
reg signed [3:0]SA;
reg [3:0]B;
    
    
initial Clk = 1;
always #10 Clk = ~Clk;
    
initial begin
    SA = 4'b1010 ;
    B = 4'b1010 ;
    # 2000;
    SA = -4'b1010;
    B = -4'b1010 ;
    # 2000;
    $stop;
end

运行结果如下:

最开始SA=1010,对于SA本身来说,因为是符号型,最高位为1,因此1010相当于-2,但是因为前面并没有负号,因此还是按照原码的形式存放,所以在内存中直接按照1010存放,B=1010,是无符号型,也是按照1010的格式存放。

但是当SA=-1010的时候,前面的负号对编译器而言,相当于把后面的数值当作负数看,因此在内存中就存的是1010的补码形式,即0110,同理,对于B=-1010的时候也同理

因此,得到结论是,在编译器中,究竟将一个数值按照补码还是原码存放进内存中,取决于前面有没有负号,而不是取决于数据本身。即使定义的是一个符号型变量且最高位为1,那还是按照原码形式存放。

但是到目前还没有探究算术位移到底如何实现?同理,继续延续上述的变量定义,SA为符号型,B为无符号型,测试代码如下:

initial begin
    SA = 4'b1010 ;
    B = 4'b1010 ;
    # 2000;
    SA = SA>>>1;
    B = B>>>1 ;
    # 2000;
    $stop;
end

结果如下: 

经过测试,可以看到,实际上,只有定义为符号型之后,算术位移才会起作用,否则仍然按照逻辑位移的方式直接位移。

三、总结 

  1. 在实际的信号编译中,在内存中是按照原码显示还是将其当作负数按照补码形式显示,本质上取决于定义数据的时候是否添加了负号,而于定义的数据本身无关。
  2. 如果想要实现算术位移,那么就要求在定义变量的时候将其定义为符号型变量。如果不加定义,Verilog中默认认为数据是无符号型的,就会导致算术位移仍然按照逻辑位移的方式执行。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值