基于FPGA的数字信号处理(12)--定点数的舍入模式(3)收敛取整convergent

前言

在之前的文章介绍了定点数为什么需要舍入和几种常见的舍入模式。今天我们再来看看另外一种舍入模式:收敛取整convergent

10进制数的convergent

convergent收敛取整。它的舍入方式和四舍五入非常类似,都是舍入到最近的整数,比如1.75 convergent到2,-0.25 convergent到0等。二者唯一的区别在于对0.5这类数据的处理上。

  • 0.5这种处于中间,舍入到两边的整数距离都一样近,所以可以把它叫做 “中间数”

  • round对于正的中间数的处理相当于向上取整,对于负的中间数相当于向下取整。例如0.5的round结果是1,-0.5的round结果是-1

  • convergent对于中间数的处理是将其舍入到最近的偶数。例如0.5舍入到0,1.5舍入到2,-0.5舍入到0,-1.5舍入到-2

以-2到1.75之间的16个数据(步长0.25)为例,它们的convergent结果是这样的:

2进制数的convergent

2进制数的convergent和10进制的convergent类似。以Q4.2格式的定点数(字长4位,小数2位的有符号数)为例,对于负数的小数部分的处理:

  • -2(d) = 10_00(b) convergent后的值为 -2,等价于 10,即舍弃小数部分后的值(10)
  • -1.75(d) = 10_01(b) convergent后的值为 -2,等价于 10,即舍弃小数部分后的值(10)
  • -1.5(d) = 10_10(b) convergent后的值为 -1,等价于 11,即舍弃小数部分(10)后再加1
  • -1.25(d) = 10_11(b) convergent后的值为 -1,等价于 11,即舍弃小数部分(10)后再加1
  • -1(d) = 11_00(b) convergent后的值为 -1,等价于 11,即舍弃小数部分后的值(11)
  • -0.75(d) = 11_01(b) convergent后的值为 -1,等价于 11,即舍弃小数部分后的值(11)
  • -0.5(d) = 11_10(b) convergent后的值为 0,等价于 00,即舍弃小数部分(11)后再加1
  • -0.25(d) = 11_11(b) convergent后的值为 0,等价于 00,即舍弃小数部分(11)后再加1

对于0的处理:

  • 直接舍弃小数部分。

对于正数的小数部分的处理:

  • 1.75(d) = 01_11(b) convergent后的值为 2,此时溢出了,需要扩展位宽,处理方式也是舍弃小数部分(001)后再加1即010
  • 1.5(d) = 01_10(b) convergent后的值为 2,此时溢出了,需要扩展位宽,处理方式也是舍弃小数部分(001)后再加1即010
  • 1.25(d) = 01_01(b) convergent后的值为 1,等价于 01,即舍弃小数部分后(01)的值
  • 1(d) = 01_00(b) convergent后的值为 1,等价于 01,即舍弃小数部分后(01)的值
  • 0.75(d) = 00_11(b) convergent后的值为 1,等价于 01,即舍弃小数部分后(00)的值再加1
  • 0.5(d) = 00_10(b) convergent后的值为 1,等价于 01,即舍弃小数部分后(00)的值再加1
  • 0.25(d) = 00_01(b) convergent后的值为 0,等价于 00,即舍弃小数部分后(00)的值

总结一下,就是:

  • 对于正数的convergent处理:首先舍掉小数位,然后加一个进位值:

    • 当小数部分的最高位为0时,说明这个数的小数部分是小于0.5的,所以不需要进位,此时的进位值为0。
    • 当小数部分的最高位为1且其他位不为全0时,说明这个数的小数部分是大于0.5的,所以需要进位,即此时的进位值为1。
    • 当小数部分的最高位为1且其他位为全0时,说明这个数的小数部分是等于0.5的,所以需要进位,因为进位是需要进到最近的偶数,所以还需要看整数部分的最低位,如果最低位为0,说明此时的整数部分就是最近的偶数整数,所以进位值为0;如果为1,则说明+1后的整数才是距离最近的偶数,所以进位值为1。
  • 对于0的convergent处理:首先舍掉小数位,然后加一个进位值,该进位值恒定为0。

  • 对于负数的convergent处理:首先舍掉小数位,然后加一个进位值:

    • 当小数部分的最高位为0时,说明这个数的小数部分是小于0.5的,而整数部分又是个负数,相当于二者的和的小数部分小于 -0.5。例如10.01是-1.75,它的小数部分.01是0.25,整数部分10是-2,二者相加是-2+0.25 = -1.75,所以它们的处理方式都是先舍弃小数位,然后加0。
    • 当小数部分的最高位为1且其他位不为全0时,说明这个数的小数部分是大于0.5的,而整数部分又是个负数,相当于二者的和的小数部分大于-0.5。例如10.11是-1.25,它的小数部分.11是0.75,整数部分10是-2,二者相加是-2+0.75 = -1.25。所以它们的处理方式都是先舍弃小数位,然后加1。
    • 当小数部分的最高位为1且其他位为全0时,说明这个数的小数部分是等于0.5的,此时需要舍入到最近的偶数,如果此时整数部分的最低位的值是1,说明此时最近的偶数还需要加1,;如果此时整数部分的最低位的值是0,说明最近的偶数就是这个整数部分。例如10_10是 -1.5,convergent后的值为 -2(10),10_10的整数部分为10,其最低位为0,所以最近的偶数就是整数部分的值,所以进位值为0,即10_10>>10+0>>10;或者11_10是 -0.5,convergent后的值为 0(00),11_10的整数部分为11,其最低位为1,所以最近的偶数是整数部分的值+1,所以进位值为1,即11_10>>11+1>>00。

上面的内容可以再精简:

  • 当小数部分的最高位为0时,相当于整数部分 + 进位值,进位值等于0即小数部分的最高位
  • 当小数部分的最高位为1且其他位不为全0时,相当于整数部分 + 进位值,进位值等于1即小数部分的最高位
  • 当小数部分的最高位为1且其他位为全0时,相当于整数部分 + 进位值,进位值等于整数部分的最低位

image-20240421161601871

下面以 用convergent的方式来实现Q4.2格式定点数转Q2.0格式定点数为例,Verilog代码如下:

module test(
    input	[3:0]	data_4Q2,				//有符号数,符号1位,字长4位,小数2位	
    output	[1:0]	data_2Q0				//有符号数,符号1位,字长2位,小数0位	
);

wire	carry;

assign	carry = (data_4Q2[1] && ~data_4Q2[0]) ? data_4Q2[2] : data_4Q2[1];				
assign	data_2Q0 = data_4Q2[3:2] + carry;	//舍弃低位(即整个小数部分)后再加进位

endmodule

因为一共只有16个数,所以我们可以用穷举的方式来测试,TB如下:

`timescale 1ns/1ns
module test_tb();

reg	 [3:0]	data_4Q2;			//有符号数,符号1位,整数2位,小数2位	
wire [1:0]	data_2Q0;			//有符号数,符号1位,整数2位,小数0位	
	
integer i;						//循环变量

initial begin
	data_4Q2 = 0;				//输入赋初值	
	for(i=0;i<16;i=i+1)begin	//遍历所有的输入,共16个	
		data_4Q2 = i;						
		#5; 
		$display("data_4Q2:%h		data_2Q0:%h",data_4Q2,data_2Q0);
	end
	#20 $stop();				//结束仿真
end

//例化被测试模块
test	test_inst(
	.data_4Q2	(data_4Q2),	
	.data_2Q0	(data_2Q0)
);

endmodule

同时,我们也用matlab来实现同样的功能,观察两者的输出是否一致:

%--------------------------------------------------
% 关闭无关内容
clear;
close all;
clc;

%-------------------------------------------------------------------------------
% 生成数据并做convergent处理
x = -2:0.25:1.75;
F = fimath('RoundingMethod','convergent');         	% 设定舍入模式为convergent
%F_c = fimath('RoundingMethod','Convergent');      	% 设定舍入模式为convergent
data_4Q2 = fi(x,1,4,2,F);                         	% 生成Q4.2格式的定点数
data_2Q0 = fi(data_4Q2,1,2,0,F);                  	% 从Q4.2格式转换成Q2.0格式

下图是2者分别输出的数据(16进制),可以看到有2个数是对不上的:

image-20240421013707229

你如果记性不错的话,就会发现这两个数正是前面讨论的正数会出现溢出的情况。这2个数分别是0110/0111,即10进制数1.5/1.75,它们的convergent结果应该是2。从上图来看,好像是matlab错了,而RTL对了,但实际情况恰恰相反。现在想想结果是什么格式的?Q2.0!它能表示的最大的数是多少?是10进制的1!所以结果溢出了!

那为什么RTL的结果又 ”对“ 了呢?这纯属是乌龙。因为打印结果是16进制的,并不表示10进制数值,结合结果的2位位宽,可知 ”2“,实际上就是10,它是01的溢出产生的,这个数在Q2.0格式的定点数中并不表示 ”数字2“,而是数字 ”-1“。

matlab是有溢出处理进制的(saturate),它把溢出值把都饱和在了最大值,即01(10进制的1),所以为了防止这种情况的发生,我们也要设计对应的溢出处理机制。因为负数的最小值只取决于整数(小数部分是正的权重),而正数的最大值同时取决于小数和整数,例如Q4.2格式的最小值是-2即10_00,而最大值则是1.75即01_11,所以溢出只会是正向的溢出,那么就只要限定最大值即可。把Verilog代码改一下:

module test(
    input	[3:0]	data_4Q2,				//有符号数,符号1位,字长4位,小数2位	
    output	[1:0]	data_2Q0				//有符号数,符号1位,字长2位,小数0位	
);

wire	carry;
wire	[2:0]	data_temp;					//扩展1bit,防止溢出

assign	carry = (data_4Q2[1] && ~data_4Q2[0]) ? data_4Q2[2] : data_4Q2[1];	
assign	data_temp = {data_4Q2[3],data_4Q2[3:2]} + {2'b00,carry};		//中间变量,舍弃低位(即整个小数部分)后再加进位    
assign	data_2Q0 = (data_temp[2:1]==2'b01) ? 2'b01 : data_temp[1:0];	//data_2Q0的高2位为01说明产生了正向的进位,即溢出
			
endmodule

这样结果就是正确的了:

image-20240421121204033

定点数从Q4.2格式转Q2.0格式是一个比较特殊的例子,因为它相当于把小数部分全部舍弃掉了,如果舍入要求不是全部小数位,而是部分小数位,那么处理方式是一样的吗?

是一样的。对于其他情况则相当于把小数点移动到了对应的位置。例如Q5.3格式的定点数转Q3.1格式,则只需要把最后两位小数舍弃并加上进位即可即可。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过金山和微软虚拟打印机转换PDF文件,流程方法及优劣对比

文章目录 一、WPS/金山 PDF虚拟打印机1、常规流程2、PDF文件位置3、严重缺陷二、微软虚拟打印机Microsoft Print to Pdf1、安装流程2、微软虚拟打印机的优势一、WPS/金山 PDF虚拟打印机 1、常规流程 安装过WPS办公组件或金山PDF独立版的电脑,会有一个或两个WPS/金山 PDF虚拟…

leetcode-151 翻转字符串里的单词

一、题目描述 给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 输入&#xff1a;s "the sky is blue" 输出&#xff1a;"blue is sky the"输入&#…

数据结构-查找-哈希表

一、哈希表的映射方法 1、直接定址法&#xff08;值的分布范围集中&#xff09; 比如统计字符串中字符出现的次数&#xff0c;字符范围集中。 2、除留余数法&#xff08;值的分布范围分散) hashi key % n 但是这种方法会导致&#xff0c;哈希冲突&#xff1a;不同的值映射…

【Python探索之旅】初识Python

目录 发展史&#xff1a; 环境安装&#xff1a; 入门案例&#xff1a; 变量类型 标准数据类型 数字类型&#xff1a; 字符串&#xff1a; 全篇总结&#xff1a; 前言&#xff1a; Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设…

CSS 之 圆形波浪进度条效果

一、简介 ​ 本篇博客讲述了如何实现一个圆形波浪进度条的样式效果&#xff0c;具体效果参考下方GIF图。该样式的加载进度条可以用在页面跳转或数据处理等情况下的加载动画&#xff0c;比起普通的横条进度条来说&#xff0c;样式效果更生动美观。 实现思路&#xff1a; ​ 这…

Wikimedia To Opensearch

概览 Wikimedia ⇒ Kafka ⇒ OpensearchJava Library&#xff1a;OKhttp3和OkHttp EventSource&#xff1b;生产者&#xff1a;Wikimedia&#xff1a;WikimediaChangeHandler和WikimediaChangeProducer&#xff1b;消费者&#xff1a;Opensearch&#xff1a;OpenSearchConsume…

代码随想录-算法训练营day38【动态规划01:理论基础、斐波那契数、爬楼梯、使用最小花费爬楼梯】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第九章 动态规划part01● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯 详细布置 今天正式开始动态规划&#xff01;理论基础 无论大家之前对动态规划学到什么程度&#xff0c;一定要先看…

【Linux】了解信号产生的五种方式

文章目录 正文前的知识准备kill 命令查看信号man手册查看信号信号的处理方法 认识信号产生的5种方式1. 工具2. 键盘3. 系统调用kill 向任意进程发送任意信号raise 给调用方发送任意信号abort 给调用方发送SIGABRT信号 4. 软件条件5. 异常 正文前的知识准备 kill 命令查看信号 …

项目8-头像的上传

js实现头像上传并且预览图片功能以及提交 - 掘金 (juejin.cn) 我们简单建立一个表 1.前端知识储备 1.1 addClass的使用 1.基本语法 addClass() 方法向被选元素添加一个或多个类。 该方法不会移除已存在的 class 属性&#xff0c;仅仅添加一个或多个 class 属性。 提示&…

CentOS使用Docker搭建Nacos结合内网穿透实现无公网IP远程登录本地管理平台

文章目录 1. Docker 运行Nacos2. 本地访问Nacos3. Linux安装Cpolar4. 配置Nacos UI界面公网地址5. 远程访问 Nacos UI界面6. 固定Nacos UI界面公网地址7. 固定地址访问Nacos Nacos是阿里开放的一款中间件,也是一款服务注册中心&#xff0c;它主要提供三种功能&#xff1a;持久化…

LeetCode题练习与总结:不同的二叉搜索树Ⅱ--95

一、题目描述 给你一个整数 n &#xff0c;请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,nul…

CNN/TCN/LSTM/BiGRU-Attention到底哪个模型效果最好?注意力机制全家桶来啦!

​ 声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 数据介绍 效果展示 原理简介 代…

Python---NumPy万字总结【此篇文章内容难度较大,线性代数模块】(3)

NumPy的应用&#xff08;3&#xff09; 向量 向量&#xff08;vector&#xff09;也叫矢量&#xff0c;是一个同时具有大小和方向&#xff0c;且满足平行四边形法则的几何对象。与向量相对的概念叫标量或数量&#xff0c;标量只有大小&#xff0c;绝大多数情况下没有方向。我们…

Ubuntu 超级终端Terminator常用使用技巧

Ubuntu 超级终端Terminator常用使用技巧 Terminator 是一款功能强大的终端模拟器&#xff0c;它特别适合于需要同时管理多个终端会话的用户。以下是如何在 Ubuntu 上使用 Terminator 的详细指南&#xff1a; 安装 Terminator 如果你的系统尚未安装 Terminator&#xff0c;你…

Prompt Engineering ,Fine-tuning , RAG ?

Prompt Engineering ,Fine-tuning , RAG 总结&#xff1a;1 prompt engineering2 RAG (Retrieval Augmented Generation)**RAG特点****RAG优势****RAG劣势** 3 微调&#xff08;Fine-tuning&#xff09;**微调特点****微调优势****微调劣势** 4 三者共性和区别5 RAG和微调的适应…

港中深「户外自重构蜗牛机器人集群」登Nature子刊!

在科幻电影《超能陆战队》中&#xff0c;我们见证了一种由成千上万个微小磁性单元组成的机器人通过磁力相互连接&#xff0c;形成各种复杂的三维结构。香港中文大学&#xff08;深圳&#xff09;林天麟教授团队致力于将这一科幻转化为现实&#xff0c;近年来开发了一系列自由形…

C++基础与深度解析 | 数组 | vector | string

文章目录 一、数组1.一维数组2.多维数组 二、vector三、string 一、数组 1.一维数组 在C中&#xff0c;数组用于存储具有相同类型和特定大小的元素集合。数组在内存中是连续存储的&#xff0c;并且支持通过索引快速访问元素。 数组的声明&#xff1a; 数组的声明指定了元素的…

【基础技能】Windows常用快捷键

最近做知识管理&#xff0c;梳理了下个人技能&#xff0c;存在好多基础技能都是一知半解&#xff0c;用的时候都是现搜现查&#xff0c;没有形成一个完整的知识体系&#xff0c;导致一些基础不牢靠&#xff0c;需要再次筑基&#xff01; 于是就翻阅了微软的官网&#xff0c;撸…

5.13网络编程

只要在一个电脑中的两个进程之间可以通过网络进行通信那么拥有公网ip的两个计算机的通信是一样的。但是一个局域网中的两台电脑上的虚拟机是不能进行通信的&#xff0c;因为这两个虚拟机在电脑中又有各自的局域网所以通信很难实现。 socket套接字是一种用于网络间进行通信的方…

Linux进程间几种通信机制

一. 简介 经过前一篇文章的学习&#xff0c; 我们知道Linux下有两种标准&#xff1a;system V标准和 Posix标准。 System V 和 POSIX 标准是操作系统提供的接口标准&#xff0c;它们规定了操作系统应该如何实现一些基本功能&#xff0c;比如线程、进程间通信、文件处理等。 …