赞
踩
此文以quartus为例,使用Verilog语言简单编写验证。并对常见赋值运算进行介绍,读者可采用附带程序进行验证和理解。
很神奇的一件事,机器运算仅可以完成最简单的“1+1”,而“1+1”在二进制中可以完成不同bit的加减。他是如何实现的呢?
a.(相同位宽减法)例如-8‘d8可以表示为1000_1000,首位表示正负,命名为符号位,1表示负,0表示正。
-8的补码为反码1111_0111(反码)加一,即1111_1000(补码)。
1111_0111(反码)+0000_0001=1111_1000(补码)
让我们来计算一下10-8(8bits),
0000_1010(10) | |
- | 0000_1000(8) |
0000_0010(2) |
如果我们把-8写为补码1111_1000,则此时应该为10+(-8)
0000_1010(10) | |
+ | 1111_1000(-8补码) |
1_0000_0010 |
可见此时,计算结果溢出第九位,按8bits截取结果依然正确。
b.(不同位宽减法)在不同位宽的计算中,显然加法不会出现问题,减法直接用源码去计算也不会出现问题(如果计算结果大于0),让我们来试一下不同位宽的减法使用补码计算是否还可以成立。8’d8-4'd4
0000_1000(8) | |
+ | _____1100(-4补码) |
0001_0100(2) |
此时按8bits高位截取发现出现错误。
问题在于短位宽应补齐至高位宽(按首位补),计算如下
0000_1000(8) | |
+ | 1111_1100(-4补码) |
1_0000_0100(2) |
c1(signed) = a(unsigned) - b(unsigned)
a.相同位宽操作8‘d4-8'd6,我们先采用源码计算
0000_0100(4) | |
- | 0000_0110(6) |
此时发现会被无限借位。
如果我们采用补码计算,
0000_0100(4) | |
+ | 1111_1010(-6补码) |
1111_1110(-2补码) |
此时计算正确。
c1(signed) = a(unsigned) - b(unsigned)
c(unsigned) = a(unsigned) - b(unsigned)
在仿真中,不管我们是否定义结果是否赋值为符号值,都默认算出补码。但是未声明符号值的结果将被视为1_1111_1110(510),如果再继续进行计算将出现错误。
b.我们再来试一下不同位宽的小数减大数,8‘d4-4'd6
0000_0100(4) | |
+ | 1111_1010(-6补码) |
1111_1110(-2补码) |
如果我们按最高位补位计算可以顺利进行。所以在机器计算中,默认负数以补码存在。
Verilog 运算中只要出现无符号位,此式按无符号位运算,这句话经常看到,但是我们将无符号位的两个数相减,赋值给带符号为的值,例如c1(signed) = a(unsigned) - b(unsigned),由仿真结果来看,计算结果还是正确的,但是此时机器存储的并不认为是补码,而是源码,继续计算就会出错。所以我们尽可能的避免混用。
这句话用来描述逻辑运算会更适合。这就要提及较为简单而又interesting的比较器。
如果我们将无符号值与有符号值进行比较大小,此时会出现很大问题,因为这个运算将按无符号位计算,然而在负数中,机器以补码的方式存储,如果将补码视为源码,将是很大的正值。
例如,8'd6 与 -8’d2
6 | < | -2 |
0000_0110 | < | 1111_1110 |
例如,-8'd6 与 -8’d2
-6 | < | -2 |
1111_1010 | < | 1111_1110 |
在比较时,出现负数如何进行比较呢?
我们建议使用parameter signed L0=1‘b0;先定义被比较值为符号值。
reg signed [7:0] c1
if( c1 >= L0)
下面为.v文件,可直接复制。
- module signed_1(
- input clk,
- input rst_n,
- input wire unsigned [7:0] a,
- input wire unsigned [7:0] b,
- input wire signed [4:0] a1,
- input wire signed [8:0] b1,
- output reg unsigned [9:0] c,
- output reg signed [8:0] c1
- );
-
- parameter signed x0='d0;
- always @(posedge clk or negedge rst_n)
- begin
- if (!rst_n)begin
- c1 <= 'd0;
- c <= 'd0;end
-
- else if (a1 > x0)
- c1 <= 'd1;
- else if (a1 < x0)
- c1 <=(a1);
- end
- endmodule

下面为测试仿真文件,可借助modelsim进行仿真验证。
- `timescale 1ns/1ns
- module signed_1_tb();
- reg clk ;
- reg rst_n ;
- wire unsigned [7:0] a ;
- wire unsigned [7:0] b ;
- wire signed [4:0] a1 ;
- wire signed [8:0] b1 ;
- wire unsigned [9:0] c ;
- wire signed [8:0] c1 ;
-
- unassign a = 8'd8;
- unassign b = 8'd5;
- assign a1 = -5'd8;
- assign b1 = 9'd5;
-
-
-
- initial
- begin
- clk = 1'b0;
- #3000 $stop;
- end
- always #10 clk = ~clk;
-
- initial
- begin
- rst_n = 1'b0;
- #80 rst_n = 1'b1;
- end
-
- signed_1 signed_0(
- .clk (clk ),
- .rst_n (rst_n ),
- .a (a ),
- .a1 (a1 ),
- .b (b ),
- .b1 (b1 ),
- .c (c ),
- .c1 (c1 )
- );
-
- endmodule

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。