1 有符号数和无符号数的表示 三者的最高位均为符号位.
以8位为例:
原码 原码的表示范围-127~-0, +0~+127, 共256个数字。 正0的原码是0000 0000, 负0的原码是1000 0000, 有正0负0之分, 不符
合人的习惯,
反码 除符号位, 原码其余位取反而得 +0:0000 0000,-0:1111 1111 仍然有正0负0之分。
补码 在反码的基础上加1而得 对原码的两种0同时末位加1 +0:0000 0000,-0:0000 0000(因为溢出导致8位全0) 消除了正
0负0之别, 如此一来, 便节省出一个数值表示方式1000 0000, 不能浪费, 用来表示-128, -128特殊之处在于没有相应的反码原
码。也可以这样考虑:
-1: 1111 1111 -2: 1111 1110(在-1的基础上减1,直接将补码减1即可) -3: 1111 1101(在-2补码基础上减1,以下类似) -4: 1111 1100 …… -127:1000 0001 -128:1000 0000 1 2 3 4 5 6 7
如此以来:8位补码表示范围是-128~+127因为0只有一种形式所以,仍然是256个数 若8位代表无符号数, 则表示范围是 : 0~255, 这就是为什么高级语言讲到数据类型, 比如C++中的short类型时(16位长)说其表示范围是:-32768~+32767,而unsigned short表示的
范围则是:0~65535
- 在计算机中无符号数用原码表示,有符号数用补码表示
最高位 也称符号位,1表示负数,0表示正数,符号位为0时,和无符号数的表示是相同的,以下是4位补码的示例 0101=−0∗23+1∗22+0∗21+1∗20=50101=−0∗23+1∗22+0∗21+1∗20=5 1101=−1∗23+1∗22+0∗21+1∗20=−31101=−1∗23+1∗22+0∗21+1∗20=−3 w位的补码表示的数值范围是[-2w-1, 2w-1-1] 如4位的补码表示的最小值是-8(1000), 最大值是7(0111).
只有理解了有符号数的补码表示, 才能真正理解无符号数和有符号数的转换、有符号数的截断和溢出等问题.
下面结合modelsim仿真去理解有符号数与无符号数的一些加减法:
verilog和测试脚本年如下:
module sign(
input clk,
input rst,
input signed[7:0] data_1,
input signed[7:0] data_2,
output signed[8:0] data_out1,
output signed[15:0] data_out2,
output signed[15:0] data_out3,
output reg a
);
reg [8:0] data_out1_test;
reg [15:0] data_out2_test;
reg [15:0] data_out3_test;
// assign data_out=data_1+data_2;
always@(posedge clk )
if (rst)
a<=0;
else if (data_1<data_2)
a<=1;
else
a<=0;
always@(posedge clk )
if (rst)
begin
data_out1_test<=9’h0;
data_out2_test<=16’h0;
data_out3_test<=16’h0;
end
else
begin
data_out1_test<=data_1+data_2;
data_out2_test<={{8{data_1[7]}},data_1};
data_out3_test<={{8{data_2[7]}},data_2};
end
assign data_out1=data_out1_test;
assign data_out2=data_out2_test;
assign data_out3=data_out3_test;
endmodule
// Verilog Test Fixture Template
`timescale 1 ns / 1 ps
module sign_tb;
reg clk;
reg rst;
reg signed[7:0] data_1;
reg signed[7:0] data_2;
wire signed[8:0] data_out1;
wire signed[15:0] data_out2;
wire signed[15:0] data_out3;
wire a ;
sign u1 (
.clk (clk )
,.rst (rst )
,.data_1 (data_1 )
,.data_2 (data_2 )
,.data_out1 ( data_out1 )
,.data_out2 (data_out2 )
,.data_out3 (data_out3 )
,.a ( a )
);
initial
begin
rst = 1; #248; rst = 0;
clk = 1; forever #10 clk = ~clk;
end
initial
begin
data_1=8'h12;data_2=8'h23;
# 500; data_1=8'h12;data_2=8'h45;
# 500; data_1=8'h12;data_2=8'h80;
# 500; data_1=8'h80;data_2=8'h45;
# 500; data_1=8'h12;data_2=8'h45;
# 500; data_1=8'h90;data_2=8'h45;
# 500; data_1=8'h9a;data_2=8'h45;
# 500; data_1=8'h90;data_2=8'h9a;
end
endmodule