基于FPGA的数字信号处理(6)--如何确定Verilog表达式的符号

server/2024/9/26 3:19:28/

前言

尽管signed语法的使用能带来很多便利,但同时也给表达式的符号确定带来了更多的不确定性。比如一个有符号数和一个无符号数的加法/乘法结果是有符号数还是无符号数?一个有符号数和一个无符号数的比较结果是有符号数还是无符号数?等等。接下来就一起研究下–如何确定一个表达式的正负符号。


一般规则

Verilog规定了计算赋值的步骤如下:

  1. 根据赋值位长确定原则,确定RHS(表达式右边)的位长
  2. 如果需要,就扩展RHS。不管LHS(表达式左边)的符号是什么,扩展时都不考虑LHS的符号,只有当RHS是signed,才做符号扩展。
  3. 赋值时,如果RHS的位长大于LHS的位长,那么直接把多出的位丢弃,以匹配LHS的位长。(有可能把符号位截去)

Verilog语法对于表达式符号位的确定的一般规则:

(1)RHS表达式的符号不依赖于LHS,仅取决于RHS操作数

比如右边是两个有符号数相加,而左边是定义的无符号数,例如:

`timescale 1ns/1ns
module tb_test();reg	signed	[3:0] in1,in2;
reg 		[4:0] out;initial beginin1 = 4'b1001;		//-7in2 = 4'b0010;		//2out = in1 + in2;	//-5
end	endmodule

仿真结果:

image-20240403174705613

因为结果多出了1位,所以两个加数都会扩展1位,又因为它们都是有符号数,所以高位补符号位,in1从1001到11001,in2从0010到00010,二者相加的结果为:11011。而out是定义的无符号数,所以11011会被解释成 27 ,这就预计的结果 -5 对不上。但-5 的补码又刚好是 11011,说明有符号数之间的运算,其结果也应该定义成有符号数,不然就会出错。

(2)10进制数是有符号数

这里的10进制数是指没有指定位宽和基数的10进制常数,比如1,-12,200等。这很好理解,因为没有指定位宽和基数,肯定只有有符号数才能表示正数和负数。例如:

`timescale 1ns/1ns
module tb_test();initial begin	$display("-4'd1 = 2'b%b",-1);
end	endmodule

打印结果:

-4’d1 = 2’b11111111111111111111111111111111

可以看出来这肯定是一个有符号数,不然它的值就不是-1了,而是2^32 - 1。

(3)带有基数(base)的数是无符号数(哪怕它没有指定位宽),但是有 s声明的除外。例如:

`timescale 1ns/1ns
module tb_test();reg	[32:0] comp1;
reg	[4 :0] comp2,comp3;	//只要看comp的最高位是什么就知道后面的数是有符号数还是无符号数了
initial begincomp1 = 'd4;comp2 = 4'd8;	comp3 = 4'sd8;$display("%b",comp1);	//没有指定位宽,但是指定了基数,结果是无符号数$display("%b",comp2);	//指定了位宽和基数,结果是无符号数$display("%b",comp3);	//指定了位宽和基数,同时通过s 指定了它是一个有符号数	
end	endmodule

打印结果如下:

000000000000000000000000000000100
01000
11000

comp1、comp2和comp3分别是3个数扩展1位的变量,只要根据它们的首位是0还是1就可以判断这三个数是有符号数还是无符号数(因为结果多了一位,所以会扩充被操作数的符号位,从而可以判断这个数是有符号数还是无符号数)。

(4)位选(bit-select)的结果是无符号数,不管位选操作数是否有符号。域选(part-select)的结果是无符号数,不管域选操作数是否有符号,即使域选的结果是整个向量。

位选就是选中向量的某一位,而域选则是选中向量的某几位。例如:

`timescale 1ns/1ns
module tb_test();reg	signed [3:0] comp;	//定义一个有符号数comp
reg [1:0] comp_bit;
reg [3:0] comp_part;
reg [4:0] comp_full;//只要看comp的最高位是什么就知道后面的数是有符号数还是无符号数了
initial begincomp  = 4'b1001;		//-7comp_bit  = comp[3];	//位选中comp的最高位,结果是无符号数	comp_part = comp[3:1];	//域选中comp的高3位,结果是无符号数	comp_full = comp[3:0];	//域选中comp全部,结果是无符号数	$display("%b",comp_bit);	$display("%b",comp_part);	$display("%b",comp_full);	
end	endmodule

打印结果如下:

01
0100
01001

从它们的最高位可以看出来都是无符号数。

(5)拼接操作符的结果是无符号的,不管操作数是否有符号,即使是只有一个有符号操作数也是如此。

无论拼接操作是一个或多个有符号数和一个或多个无符号数,它的结果都是无符号数。例如:

`timescale 1ns/1ns
module tb_test();reg	signed [3:0] s_a,s_b;					//定义有符号数a,b
reg	signed [3:0] us_a,us_b;					//定义无符号数a,b
reg [8:0] con1,con2,con3,con4;				//拼接结果扩展一位,通过高位判断结果是否有sign
reg [4:0] con5,con6;						//拼接结果扩展一位,通过高位判断结果是否有sign//只要看con的最高位是什么就知道后面的数是有符号数还是无符号数了
initial begins_a  = 4'b1001;		s_b  = 4'b1001;		us_a = 4'b1001;		us_b = 4'b1001;		con1 = {us_a,us_a};	//2个无符号数拼接	con2 = {us_a,s_a};	//1个无符号数和1个有符号数拼接	con3 = {s_a,us_a};	//1个有符号数和1个无符号数拼接		con4 = {s_a,s_a};	//2个有符号数拼接con5 = {us_a};		//1个无符号数拼接con6 = {s_a};		//1个有符号数拼接	$display("%b",con1);	$display("%b",con2);	$display("%b",con3);	$display("%b",con4);	$display("%b",con5);	$display("%b",con6);	
end	endmodule

打印结果如下:

010011001

010011001

010011001

010011001

01001

01001

从它们的最高位可以看出来都是无符号数。

(6)比较操作符的结果(1、0)是无符号的,不管操作数是否有符号。

因为比较结果其实就是 ,完全没必要定义成有符号数。例如:

Verilog">`timescale 1ns/1ns
module tb_test();reg	signed [3:0] s_a,s_b;	//定义2个有符号数a,b
reg [1:0] comp;				//拼接结果扩展一位,通过高位判断结果是否有sign//只要看con的最高位是什么就知道后面的数是有符号数还是无符号数了
initial begins_a  = 4'b1010;			//-6s_b  = 4'b1001;			//-7	comp = (s_a > s_b);		//结果为1的无符号数			$display("%b",comp);	//所以高位扩展0,结果是01	
end	endmodule

打印结果如下:

01

从它们的最高位可以看出来是无符号数。

(7)如果某操作数是无符号数,则结果是无符号数;只有所有操作数都为有符号数,结果才是有符号数。

但凡运算式中有一个无符号数,那么结果就一定是无符号数,所以最好不要混用有符号数和无符号数。例如:

Verilog">`timescale 1ns/1ns
module tb_test();reg signed [3:0] a;
reg signed [4:0] b;//只要看con的最高位是什么就知道后面的数是有符号数还是无符号数了
initial begina = 4'b1010;	//-6	b = a + 1'b1;	//1'b1是无符号数,导致(a+1'b1)也成了一个有符号数		//$display("%b",pi_int);	
end	endmodule

仿真结果:

image-20240403211309912

因为表达式中的1’b1是一个无符号数,于是a也被强制转换成了无符号数,然后将其都扩位到5位,等价于5’b01010 + 5’b00001 = 5’b01011,即11。而非预期的(-6+1=-5),即11011。

如果改成这样:

b = a + 1;	//1是有符号数,所以(a+1)也是有符号数	

那么结果就是11011(即-5),如下所示:

image-20240403211351099


赋值和截断

  • 截断(truncation):长位宽数赋值给短位宽数,无论左操作数或右操作数是有符号数还是无符号数,都是直接截断高位
  • 赋值(assignments):短位宽数赋值给长位宽数,需要对高位进行位扩展,具体是扩展1还是扩展0,则依据右操作数而定。如果右操作数是无符号数,则高位扩展0;如果右操作数是有符号数,则高位扩展符号位。

接下来看几个例子,例1

reg 		[5:0] a; 
reg signed 	[4:0] b;initial begina = 8'hff; 	// After the assignment, a = 6'h3fb = 8'hff; 	// After the assignment, b = 5'h1f
end

结果:

image-20240403214106257

因为a和b的位宽分别是6位和5位,所以要将对应的8’hff的高位截断,结果分别为 a = 6’h3f 和 b = 5’h1f。

例2:

reg 		[5:0] a; 
reg signed 	[4:0] b, c; initial begina = 8'sh8f; 	// After the assignment, a = 6'h0fb = 8'sh8f; 	// After the assignment, b = 5'h0fc = -113; 		// After the assignment, c = 15
end

结果:

image-20240403214027214

因为 8’sh8f 即 8’b1000_1111,截断到a的6位位宽后,所以 a = 6’b00_1111 = 6’h0f;同理,b = 8’sh8f。-113是一个默认的有符号数,位宽为32bit,即32’b1111····10001111,截断到c的4位位宽后,所以 c = 4’b1111 = 15。

例3:

Verilog">reg 		[3:0] a; 
reg signed 	[3:0] b;
reg 		[7:0] c1,c2; 
reg signed 	[7:0] d1,d2;initial begina = 4'b1001; 	b = 4'b1001; c1 = a;c2 = b;d1 = a;d2 = b;
end

结果:

image-20240403214429274

因为c1和d1都是被a赋值的,所以虽然它俩分别是无有符号数和有符号数,但是结果是一样的。因为a是无符号数,所以赋值给8位宽时,需要在高位扩展0,即结果为0000_1001。

因为c2和dd都是被b赋值的,所以虽然它俩分别是无有符号数和有符号数,但是结果是一样的。因为b是有符号数,所以赋值给8位宽时,需要在高位扩展符号位(1),即结果为1111_1001。


http://www.ppmy.cn/server/24424.html

相关文章

python+flask监控钉钉通讯录变更+webhook告警

Python工具开源专栏 Py0005 pythonflask监控钉钉通讯录变更webhook告警 Python工具开源专栏前言目录结构配置钉钉后台微应用的事件订阅配置钉钉群聊机器人的Webhook部分演示完整代码已在GitHub上开源 前言 pythonflask监听钉钉通讯录的变更,通过Webhook发送给钉钉群…

使用CSgetshell到3389端口远程桌面

中间使用了这个Akagi64.exe提权,网上可以找到,高版本的cs网上也可以找到。

Docker(Docker的安装和介绍,常用命令,镜像制作,服务编排,docker私服)

目录 一、简介 1. docker简介 1 什么是docker 2 容器和虚拟机对比 2. 安装docker 1 docker相关概念 2 安装docker 1 安装docker 2 设置注册中心(仓库) 3. 小结 二、常用命令【重点】 1. 服务管理 2. 镜像管理 1 语法说明 2 使用练习 3. 容器管理 1 容器介绍 2…

opencv_22_图像卷积操作

void blur_demo(Mat& image); void ColorInvert::blur_demo(Mat& image) { Mat dst; blur(image, dst, Size(13, 13), Point(-1, -1)); imshow("图像模糊", dst); }

动手学深度学习3.4 softmax回归-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。 本节课程地址:09 Softmax 回归 损失函数 图片分类数据集【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址…

技术速递|Java on Azure Tooling 3月更新 - Java on Azure 开发工具未来六个月路线图发布

作者:Jialuo Gan - Program Manager, Developer Division At Microsoft 排版:Alan Wang 大家好,欢迎阅读 Java on Azure 工具的三月更新。在本次更新中,我们将分享未来几个月对 Java on Azure 开发工具的投资。此外,我…

每周一算法:单源次短路

题目描述 “您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。 比荷卢经济联盟有很多公交线路。每天公共汽车都会从一座城市开往另一座城市。沿途汽车可能会在一些城市(零或更多)停靠。 旅行社计划旅途从 S S S 城市出发,到 F …

用Typescript写自动化工作流

项目地址:acao 挺早之前写过一个工具帮我构建项目并发布到指定平台,主要流程就是获取项目根目录下的配置文件,然后根据配置文件在本地通过 docker 构建一个镜像然后 push 到镜像仓库,最后通过 ssh 连接指定的服务区执行发布任务 …