数字电路中的有符号数
数字电路中的有符号数
在数字电路中,数据是按照二进制的格式进行存储的。对于数字电路中的变量,可以进行算数运算和逻辑运算。
1,算数运算和逻辑运算:
算数运算:包括数值的加,减,乘,除,幂运算,开方运算等。不同的运算类型有不同的电路形式,减法运算,乘法运算都可以等效为加法运算。幂运算由可以等效为乘法运算。可以搭建专门的电路来加速处理不同类型的运算。数值运算的本质是将变量当做一个进制数来对待。
逻辑运算:即布尔代数运算,包括基本的与,或,非运算。更复杂的逻辑运算也是由基本的逻辑运算符组合而成的。逻辑运算的本质是要将变量看做时有由多比特信号组成的信号集。兼有二进制数和信号集的特点,只是在不同场合利用其不同特性而已。
无论是进制数还是多比特的信号集,只是变量的不同的理解形式,其本质还是一串有序排列的二进制数集合。
2,Verilog中有符号数的定义:
二进制数又分为 无符号数和有符号数。若要定义有符号类型数,需要加上关键词:signed 。不加关键词signed的默认为无符号变量。
例如: wire signed [7:0] a;
reg signed [7:0] b;
对于无符号数,只能表示0和正整数,在电路中按照原码存储(其实也可以理解为按照补码存储,只是正整数和0的补码和原码相同)。
对于有符号数,可以表示正数,负数,0。其数值在电路中是按照补码的形式进行存储的。即正数和0存储器二进制原码,负数存储除符号位外,其余各位取反加一后计算得到的数值。
不管是有符号变量还是无符号变量,若将一个负数赋给该变量,编译器则会自动转换成其二进制补码形式后再赋给该变量。例如:
Reg signed [3:0] rega;
Rega=-2; //rega的值为1110(14),表示-2的补码。
Verilog中定义的变量,默认下为无符号类型。
3,有符号数与无符号数运算:
1.只有两个操作数都是有符号数,才会把两个操作数都看作有符号数计算,否则无论是有符号数还是无符号数都会按照无符号数计算。
2,当变量定义为无符号时,将输入的值当做无符号数,按照无符号数的计算规则来进行计算,进行大小比较。计算得到的输出值按照无符号数进行解析时,结果才正确。
3,当变量定义为有符号类型时,输入的数值被转换为补码,按照补码的计算规则来进行数值计算,输出的计算结果要按照补码来解析。
利用数值的补码来进行数值做加法计算时,就不需要考虑数值的符号位,直接将两个数当做无符号的二进制数送入到二进制全加器进行计算即可。利用补码来做数值运算,不用额外的电路来检测符号位,利用补码可以有效的减少电路的复杂程度。其计算的输出结果也是以补码的形式来表示的。
4,测试代码:
module signed_test
(
input [7:0] in_a,
input [7:0] in_b,
output [8:0] out_c,
output [15:0] out_d,
output [8:0] uout_c,
output [15:0] uout_d
);
unsigned_module unsigned_module_m0
(
.in_a ( in_a ),
.in_b ( in_b ),
.out_c ( uout_c ),
.out_d ( uout_d )
);
signed_module signed_module_m0
(
.in_a ( in_a ),
.in_b ( in_b ),
.out_c ( out_c ),
.out_d ( out_d )
);
endmodule
module unsigned_module //无符号数值计算模块
(
input [7:0] in_a, //信号默认为无符号
input [7:0] in_b,
output [8:0] out_c,
output [15:0] out_d
);
assign out_c = in_a + in_b;
assign out_d = in_a * in_b;
endmodule
module signed_module //有符号数值计算模块
(
input signed [7:0] in_a, //信号设置为有符号
input signed [7:0] in_b,
output signed [8:0] out_c,
output signed [15:0] out_d
);
assign out_c = in_a + in_b;
assign out_d = in_a * in_b;
endmodule
测试代码:
`timescale 1 ps/ 1 ps
module signed_test_vlg_tst();
reg [7:0] in_a;
reg [7:0] in_b;
wire [7:0] uin_a;
wire [7:0] uin_b;
wire [8:0] out_c;
wire [15:0] out_d;
wire [8:0] uout_c;
wire [15:0] uout_d;
assign uin_a = in_a;
assign uin_b = in_b;
signed_test i1 (
.in_a(in_a),
.in_b(in_b),
.out_c(out_c),
.out_d(out_d),
.uout_c(uout_c),
.uout_d(uout_d)
);
initial
begin
in_a = 0;
in_b = 0;
#500 $stop(2);
end
always
begin
#20
in_a = $random;
in_b = $random;
end
endmodule
仿真结果如图:
第一二行信号是输入的二进制原码。
第二组(3,4,5,6行)的变量定义为有符号,此时,用有符号数(补码)的形式来解析输入输出数值,结果才正确。如果用无符号数的形式来解析输入输出数值,结果反而正确。
第三组(7,8,9,10行)的变量定义为无符号,此时,用无符号数(原码)的形式来解析输入输出数值,结果才正确。如果用有符号数的形式来解析输入输出数值,结果反而正确。
如下图是错误解码(将有符号数按照无符号数显示,将有符号数按照无符号数显示)时,显示计算输出结果不准确:
关注公众号:“数字积木”,获取更多精彩内容,技术干货。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人