基于FPGA的数字信号处理(8)--RTL运算的溢出与保护

news2025/1/13 3:36:50

前言

在做加、减、乘、除等运算时,经常会发生 溢出 的情况。比如1个4bits的计数器(每个时钟累加1),在4’b1111 + 1 后,原本其期望值应该是 15+1 即16,但是4bits的寄存器能表示的最大值只是4‘b1111即15,所以它的值 溢出 了。 防止产生错误溢出的机制,就是所谓的 溢出保护

为了使运算结果不错误溢出从而导致功能错误,我们应该对运算结果的位宽进行合理的扩展,使其在不浪费资源的情况下保证运算结果的正确性。位宽选择的少了,那么就容易溢出;位宽选择的多了,又容易浪费电路面积。位宽的扩展比较复杂,不同的情况应具体判断,不能一概而论。


是不是所有溢出都需要保护?

先说结论,不是所有的溢出都需要保护的。举两个典型例子:1、计数器;2、补码加法。

计数器中的溢出

假设要设计的是这样一个计数器:

每个时钟周期累加1,从0~15循环计数。

为此可以写如下伪代码:

//代码1:带清零操作
always@(posedge clk)
begin
	if(cnt == 4'd15 )
		cnt <= 4'd0;
	else 
		cnt <= cnt + 4'd1;
end

我相信大多人都不会写这个代码,因为它对cnt的清零操作完全是多余的。实际上,这样写就完全足够:

//代码2:不带清零操作
always@(posedge clk)
	cnt <= cnt + 4'd1;
end

代码2的潜在逻辑是:利用 溢出 完成了原本的清零操作。当cnt为4’d15时,它的加1操作的结果是16即1_0000。因为16的表示需要5bits的位宽,所以它的最高位被截掉了,只剩下了低位的0000,即4’d0。利用了溢出机制的代码2生成的电路是要比代码1生成的电路要小的,因为代码1电路会多一个比较逻辑电路和选择逻辑电路。

可以看到,这样的溢出不光不需要采取保护措施,反而还能减小设计电路的面积。当然,只能是从最小值计数到最大值的计数器(反着来的也可以)才能合理利用溢出机制,只计数到中间值的计数器显然不行。比如,从0计数到10,就无法利用溢出,只能老老实实用比较器来判断。

补码加法中的溢出

补码本身就是一种利用 溢出 的编码机制,它可以使得减法转化成加法:即减去一个数等价于加上一个数。例如:

将算式 7 - 3 =4 转换成补码加法,等价于:7 + (-3) = 4。

image-20240415172324668

保留溢出的情况下,结果是1_0100,解释成有符号数就是 -12,这显然是错的。但如果舍去溢出位,那么结果是0100,即解释成有符号数的结果是 4,结果正确。为什么呢?

舍去溢出位的操作是不是可以看做是一个减法?对于这个例子来说,就是减5‘b1_0000即16。然后 -3 的补码如果将其看做是一个无符号数是不是就是4’b1101,即13。那么整个算式实际上就转化成了:

7 - 3 = = 7 + (-3) = 7 + 13 - 16 = 7 - (16 - 13)

利用溢出机制和补码机制,就把减法操作给转换成了加法操作。


需要做溢出保护的情况

上面的例子讨论的是不需要做溢出保护的情况,下面则例举一些常见的需要做溢出保护的例子。

两个无符号数的加法

这种情况最常见,也最简单。两个无符号数的加法就是两个正数相加,这种情况只要考虑最极端的情况就行了。比如两个4bits的数相加,最极端的情况就是:

4‘b1111 + 4’b1111 = 15 + 15 = 30

30如果还用4bits表示,那么就溢出了,所以需要扩大结果的位宽。能表示30这个数的寄存器的最小位宽是6(2^6 = 32),位宽大于6也能表示30,但就没必要浪费电路面积了。

多个无符号数的加法

这种情况和两个无符号数的加法类似,都是利用极端情况来推断就行了,例如4个4bits的无符号数相加,最极端的情况是:

4‘b1111 + 4’b1111 + 4‘b1111 + 4’b1111 = 15 + 15 + 15 +15 = 60

因为log2(60)≈ 5.9,对结果向上取整,所以需要的最小位宽是6bits。

两个无符号数的减法

两个无符号数的加法可以分成两种情况:

  • 减法结果是正数或零
  • 减法结果是负数

对于结果是正数或零的情况是不会存在溢出的情况的,因为它的值必然小于被减数,位宽不可能会溢出,所以不需要做什么特殊的处理。

减法结果是负数的情况则麻烦一些,因为负数必然是有符号数,那就意味着最高位只能表示符号而不能再表示数值了。比如:

两个4bits数的减法0 - 1 = -1, 等价于 4’b0000 - 4’b0001 = 4’b0000 + 4’b1111 = 4’b1111,这个值如果看成是有符号数那是-1,结果是正确的,如果看成是无符号是那么是15,结果就是错误的。这样看,似乎只要将减法的结果定义为有符号数即可解决问题,但如此新的问题也会随之而来。

4bits的有符号数和4bits的无符号数的表示范围是不一致的,前者是-87,后者则是015。两个4bits的无符号数的减法的取值范围则是:

max(最大 - 最小): 15 - 0 =15

min(最小 - 最大): 0-15 = -15

可以看到,仅仅将减法结果改成有符号数仍是无法表示这段范围的,需要将减法结果从4bits扩展到5bits,就可以表示该范围了,5bits有符号数的表示范围是 -16~15。

此类情况的处理办法是将减法结果扩展1bits,防止因为负数结果的产生而导致的错误溢出。如果两个数的位宽一样,那减法结果的位宽应该+1;如果两个数的位宽不一样,那就在位宽大的那个的数的位宽基础上+1。

无符号数的加减混合运算

依然用极限情况来推断运算结果的范围,然后再设计相应的溢出保护即可,例如:

wire [3:0] a;	//0~15
wire [4:0] b;	//0~31
wire [5:0] c;	//0~63
wire [2:0] d;	//0~7
wire [6:0] e;	//0~127

assign sum = a + b + c - d - e;

(a + b + c) 的取值范围是 0 ~109,(d + e)的取值范围是 0 ~134,而sum的取值则范围是 -134 ~ 109,所以其位宽应是9位(-256~255)。当然,这样做的前提条件是所有的运算都在一个式子里完成,所以只需要考虑最后结果的位宽。如果运算是分步完成的,那么就要对每一个中间结果的位宽分别讨论。

两个有符号数的加减法

首先,对于有符号数来说,减法和加法是没有区别的(都可以看做是加法),所以只需要讨论加法的情况即可。

两个有符号数的加法一共有3种情况:

  • 正数 + 正数
  • 负数 + 负数
  • 正数 + 负数

接下来分别讨论:

(1)正数 + 正数

这种情况可能发生溢出,且需要对运算结果进行溢出保护,例如极端情况:

4’d7 + 4’d7 = 4’b0111 + 4’b0111 = 4’b1110

因为最高位的符号位变成了1,导致结果从一个正数(+14)变成了负数(-2),显然是不对的。如果把结果的位宽扩展1位到5位,那么结果5’b01110就是正确的结果即+14了。

(2)负数 + 负数

这种情况和上一种情况类似,考虑极端情况:

-4’d8 + (- 4’d8) = 4’b1000 + 4’b1000 = 5’b1_0000

如果舍去最高的溢出位,那么结果4‘b0000(0)就是错误的;如果不舍去溢出位,那么结果5’b1_0000(-16)就是正确的,所以这种情况也需要对运算结果进行位扩展以实现溢出保护。

(3)正数 + 负数

一方面,在上一章我们已经讨论过了,正数 + 负数 是要依靠溢出才能正确地实现运算;另一方面,从(正数 + 正数)和(负数 + 负数)的讨论,我们又得出结论:需要扩展位宽以实现对结果的溢出保护。这么看,似乎陷入了死局,何解?

常见的做法是:

对两个加数进行符号位扩展,同时把结果的位宽也扩展一位。

还是上面例子,两个4bits有符号数的加法,应该用Verilog这么写:

wire 	[3:0]	add1,add2;	//有符号数
wire	[4:0]	sum;		//有符号数

assign sum = {add1[3],add1} + {add2[3],add2};	//两个加数都补上最高位的符号位

仍然用上面的例子:

将算式 7 - 3 =4 转换成补码加法,等价与:7 + (-3) = 4。

image-20240504110116998

因为结果是5bits,所以最高位(第6位)会被舍去,只留下了5bits的结果5’b00100(4),结果正确。

综合这3种情况,可以得出结论:

对于2个有符号数的加减法,结果的位宽为其中位宽较大者的位宽+1,同时运算时,需要将两个加数的最高位补符号位到与结果位宽相同。

两个无符号数的乘法

假设其中一个数的位宽是a,另一个数的位宽是b,那么积的位宽就是(a + b)。也可以用极限情况来分析,比如两个4bits的无符号数乘法,最大的值是1111 × 1111 = 15 × 15 = 225,那么就是需要8位来表示(2^8 = 256)。其实也可以将乘法看成是移位,15 × 15 ≈ 15 × 16,而乘16相当于作为4bits,所以积的位宽应该是在前者的位宽基础上加上4,即二者的位宽相加。

两个有符号数的乘法

这种情况,积的位宽也是两个乘数的位宽之和。

这样的结果是有点反直觉的,因为两个乘数都有一个符号位,相乘之后这个符号位显然又不需要2bits来表示,那么位宽应该是二者的位宽之和减1才对。造成这一结果的原因是因为有符号数对负数的表示和正数的表示是不对称的,比如4bits的有符号数的表示范围是 -8~7,负数的范围比正数的表示要多一个数(-8),-8的补码是 1000。假设1000不表示 -8,而和0000同样表示0,那么它的范围就变成了 -7~7,此时二者的乘法就是乘数相加,再加一个符号位,即3+3+1 = 7位。

但是很遗憾,1000就是 -8 而不是 - 0 ,所以当两个 -8 相乘的时候,结果就会在6bits的基础上溢出了(-8 × -8 = 64, 即100_0000),再加上符号位,此时积的位宽就需要 6+1+1 = 8位了。

除法

除法的实现是四则基础运算中最麻烦。因为两个整数的除法,其结果可能是小数,比如11/10=1.1,而1.1又是个无法用有限位数就能表示的小数,它涉及到浮点数的定点化问题,不同的方案对定点化的定标要求可能也不一致,所以除法的结果位宽不能用一个统一的标准来判断。


限制运算结果位宽的情况

严格来说,这类情况实际上是要解决如何处理数据的溢出,而不仅仅是对结果扩展位宽以防止溢出产生错误。比如2个3bits的无符号数相加,同时限制和的位宽也是3bits,常见的做法有两种:

  • 如果有溢出则将和的结果锁定在最大值,比如 3+6 = 9,但是3bits能表示的最大结果是7,所以输出的和就是7。
  • 如果有溢出则将溢出舍去,而将低位保留。比如 9 = 3 + 6 = 011 + 110 = 1_001,将溢出的最高位舍去,而将最低位保留,那么和的结果就是001即1。

关于这两种溢出模式的处理,我们在下一篇文章再细说。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1641495.html

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

相关文章

Server 2022 IIS10 PHP 7.2.33 升级至 PHP 8.3 (8.3.6)

下载最新版本 PHP 8.3 (8.3.6)&#xff0c;因为是 FastCGI 执行方式&#xff0c;选择 Non Thread Safe(非线程安全)。 若有以下提示&#xff1a; The mysqli extension is missing. Please check your PHP configuration. 或者 PHP Fatal error: Uncaught Error: Class &qu…

PDF Shaper Ultimate 免安装中文破姐版 v14.1

软件介绍 PDF Shaper是一套完整的多功能PDF编辑工具&#xff0c;可实现最高的生产力和文档安全性。它允许你分割&#xff0c;合并&#xff0c;水印&#xff0c;署名&#xff0c;优化&#xff0c;转换&#xff0c;加密和解密您的PDF文件&#xff0c;也可插入和移动页&#xff0…

每日OJ题_DFS爆搜深搜回溯剪枝①_力扣784. 字母大小写全排列

目录 力扣784. 字母大小写全排列 解析代码1_path是全局变量 解析代码2_path是函数参数 力扣784. 字母大小写全排列 784. 字母大小写全排列 难度 中等 给定一个字符串 s &#xff0c;通过将字符串 s 中的每个字母转变大小写&#xff0c;我们可以获得一个新的字符串。 返回…

SpringSecurity6 学习

学习介绍 网上关于SpringSecurity的教程大部分都停留在6以前的版本 但是&#xff0c;SpringSecurity6.x版本后的内容进行大量的整改&#xff0c;网上的教程已经不能够满足 最新的版本使用。这里我查看了很多教程 发现一个宝藏课程&#xff0c;并且博主也出了一个关于SpringSec…

解决: 0x803f7001 在运行Microsoft Windows 非核心版本的计算机上,运行“ slui.exe 0x2a 0x803f7001 “以显示错误文本,激活win10步骤流程。

一. 解决 0x803F7001在运行Microsoft Windows非核心版本的计算机错误 首先&#xff0c;按下winR打开"运行",输入 regedit 后回车&#xff0c;打开注册表。   然后再注册表下输入地址HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProt…

ssh远程访问windows系统下的jupyterlab

网上配置这一堆那一堆&#xff0c;特别乱&#xff0c;找了好久整理后发在这里 由于既想打游戏又想做深度学习&#xff0c;不舍得显卡性能白白消耗&#xff0c;这里尝试使用笔记本连接主机 OpenSSH 最初是为 Linux 系统开发的&#xff0c;现在也支持包括 Windows 和 macOS 在内…

【第三版 系统集成项目管理工程师】第2章 信息技术发展(知识总结)

持续更新。。。。。。。。。。。。。。。 【第2章】 信息技术发展 考情分析2. 1信息技术及其发展2.1.1 计算机软硬件-P501.计算机硬件2.计算机软件-P51 2.1.2计算机网络1.通信基础-P522.网络基础-P534.网络标准协议-P543.网络设备-P535.软件定义网络-P576.第五代移动通信技术-P…

【论文阅读】Tutorial on Diffusion Models for Imaging and Vision

1.The Basics: Variational Auto-Encoder 1.1 VAE Setting 自动编码器有一个输入变量x和一个潜在变量z Example. 获得图像的潜在表现并不是一件陌生的事情。回到jpeg压缩&#xff0c;使用离散余弦变换&#xff08;dct&#xff09;基φn对图像的底层图像/块进行编码。如果你给…

【Redis面试题】Redis常见的一些高频面试题

分享几个Redis入门级常见面试过程中遇到的题目! 你项目中哪里使用到了redis?可以讲一讲嘛 这个题目无论是大公司还是小公司都经常考,建议大家根据自己的项目做总结 redis的几种基础数据结构 redis为什么那么快&#xff1f; 1.基于内存实现&#xff1a;我们都知道内存读写是…

50个前端实战项目之04:隐藏的搜索小组件

大家好&#xff0c;我是宝哥。 今天讲50个前端实战项目之04&#xff1a;隐藏的搜索小组件。 源码下载地址 https://github.com/bradtraversy/50projects50days/tree/master/hidden-search 前端实战项目系列正在更新&#xff1a;04/50 01&#xff1a;可展开卡片02&#xff1a;进…

Springboot+Vue项目-基于Java+MySQL的图书商城管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

中国各省地图(高清晰一亿像素)

hello&#xff0c;我是小索奇 不知道大家有没有使用地图的习惯&#xff0c;反正小索奇去一个地方&#xff0c;就会使用地图&#xff0c;也会经常看世界地图&#xff0c;因为地理学得不好&#xff0c;有时候也记不住部分省份在哪里。所以会经常使用到地图 但去百度搜索里面寻找…

windows驱动开发-PNP管理器

PNP技术是由Microsoft提出的&#xff0c;英文Plug and play的缩写&#xff0c;中译即插即用&#xff0c;意思是系统自动侦测周边设备和板卡并自动安装设备驱动程序&#xff0c;做到插上就能用&#xff0c;无须人工干预&#xff0c;是Windows自带的一项技术。所谓即插即用是指将…

阿里云API网关 产品的使用笔记

阿里云的产品虽多&#xff0c;还是一如既往的一用一个看不懂&#xff0c;该模块的文档依旧保持“稳定”发挥&#xff0c;磕了半天才全部跑通。 用阿里云API网关的原因是&#xff0c;在Agent中写插件调用API的时候&#xff0c;需要使用Https协议&#xff0c;又嫌搞备案、证书等事…

关于YOLO8学习(三)训练自定义的数据集

前文 关于YOLO8学习(一)环境搭建,官方检测模型部署到手机 关于YOLO8学习(二)数据集收集,处理 简介 本文将会讲解: (1)如何通过PyCharm,进行训练数据,实现人脸检测 开发环境 win10、python 3.11、cmake、pytorch2.0.1+cu117、pycharm、ultralytics==8.0.134 要特…

解决layui的bug 在layui tree 组件中 禁用选中父节点后自动选中子节点功能

最近做权限管理后台&#xff0c;用了layui tree 组件&#xff0c;发现选中了父节点后&#xff0c;自动选中了子节点。不满足现实业务需求。所以微调了下源代码。 在用树形组件中&#xff0c;在用文档中 tree.setChecked(demoId, [2, 3]); //批量勾选 id 为 2、3 的节点 用这句…

Python 贪吃蛇

文章目录 效果图&#xff1a;项目目录结构main.pygame/apple.pygame/base.pygame/snake.pyconstant.py 效果图&#xff1a; 项目目录结构 main.py from snake.game.apple import Apple # 导入苹果类 from snake.game.base import * # 导入游戏基类 from snake.game.snake im…

基于SpringBoot的饭店外卖平台的设计与实现

项目描述 这是一款基于SpringBoot的饭店外卖平台的系统 模块描述 用户端 登录 首页 商家信息 点餐 菜品列表 下单 订单列表 账号下单列表 个人中心 个人资料 修改信息 评论管理 评论菜品 查看评论 打赏骑手 打赏骑手 管理员 登录 菜品管理 修改 下架 订单列表 下单记录 菜品管理…

Json数据概念及C# 环境下的序列化、反序列化操作

什么是Json&#xff1f; JSON的全称是JavaScript Object Notation&#xff0c;是一种轻量级的数据交换格式&#xff0c;主要用于数据的序列化和交互。常用于Web中&#xff0c;其他领域也经常出现JSON的身影。 与xml相比&#xff0c;更快&#xff0c;更小&#xff0c;更容易解析…

银河麒麟桌面版开机后网络无法自动链接 麒麟系统开机没有连接ens33

1.每次虚拟机开机启动麒麟操作系统&#xff0c;都要输入账号&#xff0c;密码。 进入点击这个ens33 内网才连接 2. 如何开机就脸上呢&#xff1f; 2.1. 进入 cd /etc/sysconfig/network-scripts 2.2 修改参数 onbootyes 改为yes 2.3 重启即可 a. 直接重启机器查看是否正常&…