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

前言

尽管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)是无符号的,不管操作数是否有符号。

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

`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)如果某操作数是无符号数,则结果是无符号数;只有所有操作数都为有符号数,结果才是有符号数。

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

`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:

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.mzph.cn/pingmian/5051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣刷题Day2

题目链接: 24. 两两交换链表中的节点 - 力扣(LeetCode) 效果: 解题思路: 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 注意不可以只是单纯的改变节点内部的值,而…

《QT实用小工具·四十七》可交互的创意动态按钮

1、概述 源码放在文章末尾 该项目实现了可交互的创意动态按钮,包含如下功能: 所有颜色自定义 鼠标悬浮渐变 两种点击效果:鼠标点击渐变 / 水波纹动画(可多层波纹叠加) 额外鼠标移入/移出/按下/弹起的实时/延迟共8种事…

51单片机两个中断及中断嵌套

文章目录 前言一、中断嵌套是什么?二、两个同级别中断2.1 中断运行关系2.2 测试程序 三、两个不同级别中断实现中断嵌套3.1 中断运行关系3.2 测试程序 总结 前言 提示:这里可以添加本文要记录的大概内容: 课程需要: 提示&#x…

德国著名自动化公司Festo设计了一款仿生蜜蜂,仅重34g,支持多只蜜蜂编队飞行!...

德国著名的气动元件研发及自动化解决方案供应商Festo公司近日展示了一款仿生蜜蜂(BionicBee),重量只有34g,却完全可以实现自主飞行,还支持多只相同的蜜蜂机器人编队飞行。 BionicBee 重约 34 克,长 22 厘米…

Redis线程模型及性能优化概述

redis线程模型: 网络模块命令处理 redis的性能: 一个取决于物理内存,另一个是对于socket请求的处理速度。 4.0以前 单线程模式 请求流程:对于一个请求,线程会根据操作产生相应的事件(读,写事…

基于Springboot的水产养殖系统(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的水产养殖系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&…

【MyBatis】进阶使用 (动态SQL)

动态SQL \<if>\<trim>\<where>\<set>\<foreach>\<include> 在填写表单时&#xff0c;有些数据是非必填字段&#xff08;例如性别&#xff0c;年龄等字段&#xff09;&#xff0c;那就需要在接收到参数时判断&#xff0c;根据参数具体的情况…

【知识学习/复习】损失函数篇,包含理解应用与分类:回归、分类、排序、生成等任务

损失函数总结 一、损失函数理解二、不同任务的损失函数的应用1.图像分类2.目标检测3.语义分割4.自然语言处理&#xff08;NLP&#xff09;5.图神经网络&#xff08;GNN&#xff09;6.生成式网络 三、损失函数1. 回归任务损失函数常见损失函数IoU系列损失函数1. IoU损失函数&…

TiDB 利用binlog 恢复-反解析binlog

我们知道TiDB的binlog记录了所有已经执行成功的dml语句&#xff0c;类似mysql binlog row模式 &#xff0c;TiDB官方也提供了reparo可以进行解析binlog&#xff0c;如下所示: [2024/04/26 20:58:02.136 08:00] [INFO] [config.go:153] ["Parsed start TSO"] [ts449…

[C++][数据结构]二叉搜索树:介绍和实现

二叉搜索树 概念 二叉搜索树又称二叉排序树&#xff0c;它是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值它的左右子树也…

IoT Scenario: Smart Retail System-Multiple Sources and Multiple Terminals

物联网/大数据可视化领域发文可以联系&#xff1a;nascimsina.com IoT Scenario: Smart Retail System Overview The use of IoT in the retail industry enhances customer experiences, optimizes inventory management, and provides valuable insights into consumer beh…

【架构】后端项目如何分层及分层领域模型简化

文章目录 一. 如何分层1. 阿里规范2. 具体案例分析 二. 分层领域模型的转换1. 阿里规范2. 模型种类简化分析 三. 小结 本文描述后端项目中如何进行分层&#xff0c;以及分层领域模型简化 一. 如何分层 1. 阿里规范 阿里的编码规范中约束分层逻辑如下: 开放接口层&#xff1a…

Java全栈开发前端+后端(全栈工程师进阶之路)-环境搭建

在课程开始前我们要配置好我们的开发环境&#xff0c;这里我的电脑太乱了&#xff0c;我使用vm虚拟机进行搭建开发环境&#xff0c;如果有需要环境的或者安装包&#xff0c;可以私信我。 那我们开始 首先我们安装数据库 这里我们使用小皮面板 小皮面板(phpstudy) - 让天下没…

【计算机毕业设计】基于SSM++jsp的社区管理与服务系统【源码+lw+部署文档+讲解】

目录 摘 要 Abstract 第一章 绪论 第二章 系统关键技术 第三章 系统分析 3.1.1技术可行性 3.1.2经济可行性 3.1.3运行可行性 3.1.4法律可行性 3.4.1注册流程 3.4.2登录流程 3.4.3活动报名流程 第四章 系统设计 4.3.1登录模块顺序图 4.3.2添加信息模块顺序图 4.4.1 数据库E-…

【Node.js工程师养成计划】之express框架

一、Express 官网&#xff1a;http://www.expressjs.com.cn express 是一个基于内置核心 http 模块的&#xff0c;一个第三方的包&#xff0c;专注于 web 服务器的构建。 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用&…

使用LocalGPT+cpolar打造可远程访问的本地私有类chatgpt服务

文章目录 前言环境准备1. localGPT部署2. 启动和使用3. 安装cpolar 内网穿透4. 创建公网地址5. 公网地址访问6. 固定公网地址 前言 本文主要介绍如何本地部署LocalGPT并实现远程访问&#xff0c;由于localGPT只能通过本地局域网IP地址端口号的形式访问&#xff0c;实现远程访问…

iOS 实现视图遮罩效果

有时候&#xff0c;我们会遇到这种需求&#xff0c;只讲视图的某个部分展示出来 这时候&#xff0c;我们可以通过设置该视图layer.mask layerb来实现&#xff0c;需要注意的是&#xff0c;这里的layerb必须要设置backgroundColor&#xff0c;渐变layer有colors,否则达不到效果…

Java学习3:程序流程控制

Java程序流程控制 1.执行顺序 顺序结构分支顺序 if,switch 循环结构 for ,while ,do-while 2.if分支 三种形式 if(条件表达式){} else if(){} else{}3.switch分支 string week "周一"; switch(week){case "周一":stem.out.println("周一&qu…

UG NX二次开发(C++)-获取模型中所有的拉伸(Extrude)特征

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、在UG 12中创建几个拉伸特征3、UFun中获取对象类型4、通过NXOpen过渡5.测试结果1、前言 在采用UG NX二次开发时,有时需要在模型中获取特定的对象,比如拉伸特征、关联特征等等。但是通过…

vue2 实现echarts图表进入可视区域后再加载动画,以及 使用了resize之后,动画失效问题解决

Intersection Observer API 是一个现代的浏览器 API&#xff0c;用于监测一个或多个目标元素与其祖先元素或视窗&#xff08;viewport&#xff09;之间的交叉状态&#xff08;intersection&#xff09;的变化。它可以有效地监听元素是否进入或离开可视区域&#xff0c;从而实现…