基于FPGA的数字表示

在FPGA系统中有两个基本准则非常重要,分别为:数字表示法和代数运算的实现。本博文主要介绍数字表示。

参考文献:数字信号处理的FPGA实现(第3版)中文版 && 基于FPGA的数字信号处理 [高亚军 编著] 2015年版,可以购买相关书籍进行研读。

零、计数系统框架

一 、整数的表示
  数字信号处理中需要考虑的基本要点是数字的表示,数字信号处理需要将量值用有限精度的数字表示。 一方面,该表示必须足够准确地处理数字信号处理系统中真实世界的输入和输出; 另一方面, 该表示必须在硬件实现方面具有高效性。
  二进制数的使用是任何数字系统的基础, 当处理大型复杂的 DSP 系统时, 每秒将需要处理数十亿次的乘加运算。 因此, 通过减少位数来降低硬件开销的方法将变得非常有意义。
  假设有一个使用 16 位分辨率运算的 DSP 滤波应用, 因此对于一个 16 位乘 16 位并行乘法 , 硬件开销的量级为 16 X 16 = 256 个单元。 使用 16 位字长的原因是它就是 DSP处理器通常使用的字长, 鉴于习惯仍然选择一样的字长。 在 FPGA世界中可以选择分辨率。 因此, 如果说 9 位分辨率已经足够了, 乘法器的硬件开销即为 9 X 9= 81 个单元。 这大约是使用 16 位计算开销的 30%。
  因此正确选择字长很重要: 使用太多位浪费硬件资源, 而太少则会损失分辨率。 所以, 保证选择正确的字长的前提是掌握算法和 DSP 知识。

1.1 二进制反码
  可使用二进制反码描述正数和负数。 求一个数的反码只需对所有的位取反。 然而需要注意, 当使用反码时, 有两种表示数字 0 的方法, 通常来说, 用反码并不能直接表示算术运算。
  当在这种数字系统中执行二进制运算时, 将遇到奇怪的问题, 这是由于数字 0 有两个表示版本。 事实上,-0 小于+0,这是由于使用反码表示时: -0+ 1 =+0;+0 -1=-0。
  实现上述功能需要相当复杂的硬件。 实际需要的是这样一种系统, 其处理正数和负数与处理无符号数字一样, 不需要增加硬件的复杂性。
  反码实际上从来没有在实时 DSP 或数字系统中使用过, 但是它能够引出标准形式的二进制补码的概念。

1.2 二进制补码
  对于+0 和-0 来说, 更加合理的数字系统为只有一个 0 的二进制补码。 表 1.1 给出了二进制补码的表示。
  生成 0 的第 9 位可被忽略, 注意用二进制补码可以表示- 128,但不能表示+ 128。在对正值取反时, 会发现需要用第 9 位表示负零。 然而, 如果简单地忽略这个第 9 位 , 那么这个负零与正零的表示将完全相同。

注意在数值系统中, 每个位置上阶的意义。 例如对于十进制 156 来说:

也就是说字符串“156”代表数字 156,它是每个位置上的值与其阶的乘积的和。

如表1.2 所示, 这个规则对二进制数也同样适用。 如表 1.3 所示, 对于二进制补码整数, 如果将最左列考虑为负值, 则结果同样适。

二、 非整数值的表示
  在数字信号处理系统中, 经常希望描述诸如正弦波的信号, 显然需要处理非整数数值的情况。 对这种非整数值要求的一种可能的解决办法是允许正弦波幅度按比例增加并以整数形式来表示。

  这种方法很常见, 但在某些情况下, 需要表示 0~1 之间的数值, 也需要表示整数之间的数值。用十进制表示小数很容易。 通过引入十进制小数点来描述非整数, 并在小数点的右边插人数字。 例如:

在式中, 字符串“10.34”代表数字 10. 34 ,即 10 的乘方的倍数的总和。

同样地, 可以对二进制数执行同样的运算:

在式屮, 字符串“10.01”表示数字 2.25,即 2 的乘方的倍数的总和。

2.1 定点二进制数
  定点数就是二进制小数点在固定位罝的数。 二进制小数点左边部分的位被定义为整数位, 而该点右边部分的位被定义成小数位。 举例来说: “101.01011”有 3 个整数位, 5个小数位。如表 2.1 所示, 定点数按类似的方式处理有符号整数。

根据表 2.1可得, 110.00111( 二进制数) = - 1.78125( 十进制数)

如表 2.2所示 , 一种非常重要的定点数字类型只有一个整数位。

  例如, Motorola StarCore 和 TI C62x DSP 处理器都使用只有一个整数位的定点表示法。 这种格式可能是有问题的, 因为它不能表示+ 1.0,实际上, 任何定点格式都不能表示其负数最小值的相反数。

  所以在使用定点数时要多加注意。 一些 DSP 处理器结构允许利用扩展位对格式进行 1 个整数位的扩展( 这些扩展位就是附加的整数位)。

2.2 定点量化
  重新考虑数字的格式:aaa. bbbb 表示 3 个整数位, 5 个小数位。 可以表示- 4 和3.96785 之间的数, 数之间的步长为 0.03125。 由于具有 8 位, 故具有 28 = 256 个不同的值。 需要注意使用定点时的量化,将有± 1 /2LSB( 最低有效位) 的误差。
  量化就是使用有限数位来表示无限精度的数。 在十进制中, 很熟悉处理给定位数的十进制小数的方法。 实数可以表示为 3.14159265… , 可以量化或将其表述为带 4 个十进制位的小数 3.1416。 如果在这里使用舍人, 则误差为:

3.14159265…- 3.1416 =- 0.00000735

  如果使用截断法( 即第 4 位小数以后的位数被扔掉) , 则误差将变得更大, 如下:

3.14159265…- 3.1415 = 0.00009265

  很明显, 舍人是比较合适的能够得到预期精度的方法。 然而该方法也会有一些硬件开销。 尽管开销相对较小, 但它的确不是免费的。
  当乘以小数时需要处理到给定数目的位数。 例如, 如果需要计算两个十进制小数位, 则计算过程如下:

0.57 X 0.43 = 0.2451

  可被舍人到 0.25,或者截断到 0.24。结果是不同的。
  一旦开始在数字信号处理系统中执行上亿次的乘加运算, 就不难发现这些微小的误差会因为累积而造成严重的影响。

2.3归一化处理
  使川二进制小数使得算术运算变得容易, 也易于处理字长增长。 作为一个例子, 考这样一个“ 机器”, 它有 4 位十进制数和一个具有 4 个数字位的算术单元, 范围为-9999~+9999。 两个 4 位数相乘将导致多达 8 个有效数字。
6787 X 4198 = 28491826 -->(标定)2849.1826–>(截断)2849
  如果想把这个数送到该机器的下一级( 算术运算具有 4 位的精度 ) , 那么需要按比例减小 10000 倍, 然后截断 。
  将其归一化到范围-0.9999 ~+0.9999。

0.6787 X 0.4198 = 0.28491826 —>(截断) 0.2849

  现在截断到 4 位的操作变得相当容易。 当然两种结果是严格一致的, 而差别仅仅在于如何执行截断和标定。
  然而对输入执行归一化操作, 所有的输人值都位于-1~ + 1 的区间内。 可以注意到该区间内任意两个数的乘积同样存在于-1 +1 的区间之内。
  同样的归一化操作也适用于二进制, 而且大多数数字信号处理系统也使用二进制点。
  下面考虑 二 进 制 补 码 中 的 8 位 数 值。 因 此 该 数 值 的 取 值 范 围 是 10 0 0 0 0 0 0~01111111 (-128~+127)。
   如果将这些数归一化到-1~ 1 之间( 除以 128 ), 那么二进制的范围是 1.0000000~0.1111111( -1~ 0.9921875,其中 127/128= 0.9921875 )。 所以把十进制乘法中归一化的概念用于二进制。
  十进制乘法 36 X 97=3492 等价于二进制乘法 0010 0100 X 0110 0001 = 0000 1101 1010010。 在二进制中,将值归一化就是计算 0.0100100 X 0.1100001 =0.00110110100100。 等价于十进制中:

0.28125 X 0.7578125=0.213134765625

  注意: 在 数 字 信 号 处 理 系 统 中, 在 设 计 者 的 眼 中, 二 进 制 点 是 存 在 的, 然 而 却 没 有 实际 的 连 接 或 连 线。 这 只 是 使 得 跟 踪 字 长 增 长, 以 及 通 过 扔 掉 小 数 位 来 截 断 变 得 更 加 容易。 当 然 如 果 更 愿 意 使 用 整 数 并 且 跟 踪 定 标 等 , 也 可 以 这 样 做。 得 到 的 答 案 是 相 同 的 ,硬 件 开 销 也 是 相 同 的。

2.4 小数部分截断
  二进制中, 截断是简单地将位去除的过程。 通常使用这种强制的方法来将大的二进制字长变小, 通常需要截掉最低有效位 (LSB),该操作的影响是降低了准确度。
  考虑将十进制数 7.8 9 9 2 截 断 到 3 个 有 效 位 7.89。 当然, 可以截断最低有效位 , 其结果是损失了精度( 分辨率) , 但它仍是最初 5 位数的代表。 如果截断最高有效位 992 ( 或0.0992), 其结果将不是所希望的, 而且也失去了意义。
  在二进制中, 最髙有效位截断的概念是很少使用的, 在十进制的例子中, 最高有效位截断通常是灾难性的。 然而, 在某些极少情况下, 一系列的操作将导致整个数值的范围减小。 所以移除 MSB 也是有好处的。
  截断 MSB 通常发生在要截断的位为空的时候。 当使用有符号的值时, 由于丟失了符号位, 截断 MSB 将会带来问题。
  舍入是一种更准确的方法, 但同时也是更复杂的技术。 该技术需要进行一个加法操作, 然后再直接截断,该过程等价于十进制的四舍五人, 即通过在 7 . 8 9 上 加 0 . 0 5 然 后 再 截 断 到 7.9 来 舍人到一个小数位。 因此简单的舍人需要一个加法操作。

2.5 一种不同的方法 Trounding
  Trounding 是截断 truncation )和 舍 人( rounding )之 间 的 一 种 折中方 法, 其 特 点如下。
  ① 和舍人一样, Trcnmding 保留了 LSB 以上的信息。
  ② 它和舍人不同, 它不影响新的 LSB 以上的任何位。
  其具体实现方法在 XtremDSP 中进行了详细的介绍, 具体可以参看这部分相关内容。 Trounding 的好处是它不需要全加器, 而且可以通过或门得到比截断更好的性能。尽管是一个很小的优点, 但这种成本上的节省以及性能的改善还是有价值的。

三、 浮点数定义及表示
3.1 标 准 浮 点 数 表 述
  浮点数可以在更大的动态范围内提供更高的分辨率, 通常当定点数由于受其精度和动态范围所限不能胜任时, 浮点数能提供解决方案。 当然, 也在速度和复杂度方面带来了损失 , 大多数的浮点数都遵循单精度或双精度的 IEEE 浮点标准。 标准浮点数字长由一个符号位 S,指数 e 和无符号( 小数) 的规格化尾数m构成, 其格式如下:

浮点数可以用下式描述:

指数 e=1…2 是为∞准备的。 而 e=0 是 为 0 预 备 的。 表 2.3 给 出 了 IEEE 的单精度和双精度格式的参数。

在浮点乘法中, 尾数部分可以像定点数一样相乘, 而把指数部分相加。 浮点数减法复杂一些,因为首先将尾数归一化, 就是将两个数都调整到较大的指数, 然后将两个尾数相加。 对于加法和乘法混合运算来说, 最终的归一化, 就是将结果尾数再统一乘小数1.m 形式的表达式, 这是非常必要的。

  一些浮点编码的范例 ( 单精度浮点 32 位, 注意这些运算都是基于二进制的计算)。如下:

注意小数点之前的 1 没有被编码( 那里一直有个 1, 因而不需要显式表示)。

3.2 浮点数的短指数表示
  简化浮点硬件的一种方法是创建一种使用短指数的数据格式。 这种情况下有一个 4位的指数和一个 11 位的尾数。 因此可以表示-7~ 8 的范围内的指数。 其结果在动态范围内显著地增加, 代价只是精度轻微降低。 表 2.4 给出了定点数和短指数的比较。

3.3 浮点数的应用
  浮点在许多具有专用浮点单元( FPU ) 的 DSP 处理器中被广泛使用。 不在 FPGA中使用浮点的原因如下。
  ① 运算速度慢: FPU 是一个复杂的单元, 设计中的每个代数运算将共用该单元。
  ② 低效的芯片面积: 使用 FPGA 实现 FPU 需要很大的硬件空间。
  然而, 某些情况下 FPU 也许是必不可少的, 例如在需要一个巨大的动态范围的应用场合, 使用浮点可能使得设计更加简单 , 这是因为在定点设计中, 需要最好地利用可用的动态范围, 但是在浮点设计中, 动态范围的限制不是一个需要考虑的问题。
---------------------
作者:碎碎思
来源:CSDN
原文:https://blog.csdn.net/Pieces_thinking/article/details/84029520

最新文章