关于FPGA的浮点数处理 III

2024-06-23 12:36
文章标签 浮点数 fpga iii 处理

本文主要是介绍关于FPGA的浮点数处理 III,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于FPGA的浮点数处理 III

语言 :System Verilg
EDA工具:ISE、Vivado、Quartus II

      • 关于FPGA的浮点数处理 III
      • 一、引言
      • 二、单精度浮点数运算的FPGA实现
        • 1. 单精度浮点数的加法FPGA实现
          • (1)实现代码(FpAdd模块)
          • (2)代码分析
        • 2. 单精度浮点数的乘法FPGA实现
          • (1)实现代码(FpMul模块)
          • (2)代码分析
        • 三、结尾

  • 关键词: 调用,浮点数处理,floating point、单精度浮点数的乘、加、开方、绝对值操作

一、引言

在FPGA中实现浮点运算是一个复杂但有用的过程,因为浮点运算在许多应用中都是必需的,如数字信号处理、图像处理和科学计算等,上篇博客中介绍了在FPGA中使用浮点数运算的背景以及实现方式,传送链接:0315 FPGA的浮点数处理 I,以及浮点数在FPGA和有符号整数之间的转换关于FPGA的浮点数处理 II。 本篇博客注重描述单精度浮点数在FPGA中乘、加、开方、绝对值等操作

二、单精度浮点数运算的FPGA实现

1. 单精度浮点数的加法FPGA实现
(1)实现代码(FpAdd模块)
module FpAdd (input             iCLK,input      [26:0] iA,input      [26:0] iB,output reg [26:0] oSum
);// Extract fields of A and B.wire        A_s;wire [7:0]  A_e;wire [17:0] A_f;wire        B_s;wire [7:0]  B_e;wire [17:0] B_f;assign A_s = iA[26];assign A_e = iA[25:18];assign A_f = {1'b1, iA[17:1]};assign B_s = iB[26];assign B_e = iB[25:18];assign B_f = {1'b1, iB[17:1]};wire A_larger;// Shift fractions of A and B so that they align.wire [7:0]  exp_diff_A;wire [7:0]  exp_diff_B;wire [7:0]  larger_exp;wire [36:0] A_f_shifted;wire [36:0] B_f_shifted;assign exp_diff_A = B_e - A_e; // if B biggerassign exp_diff_B = A_e - B_e; // if A biggerassign larger_exp = (B_e > A_e) ? B_e : A_e;assign A_f_shifted = A_larger             ? {1'b0,  A_f, 18'b0} :(exp_diff_A > 9'd35) ? 37'b0 :({1'b0, A_f, 18'b0} >> exp_diff_A);assign B_f_shifted = ~A_larger            ? {1'b0,  B_f, 18'b0} :(exp_diff_B > 9'd35) ? 37'b0 :({1'b0, B_f, 18'b0} >> exp_diff_B);// Determine which of A, B is largerassign A_larger =    (A_e > B_e)                   ? 1'b1  :((A_e == B_e) && (A_f > B_f)) ? 1'b1  :1'b0;// Calculate sum or difference of shifted fractions.wire [36:0] pre_sum;assign pre_sum = ((A_s^B_s) &  A_larger) ? A_f_shifted - B_f_shifted :((A_s^B_s) & ~A_larger) ? B_f_shifted - A_f_shifted :A_f_shifted + B_f_shifted;// buffer midway resultsreg  [36:0] buf_pre_sum;reg  [7:0]  buf_larger_exp;reg         buf_A_e_zero;reg         buf_B_e_zero;reg  [26:0] buf_A;reg  [26:0] buf_B;reg         buf_oSum_s;always @(posedge iCLK) beginbuf_pre_sum    <= pre_sum;buf_larger_exp <= larger_exp;buf_A_e_zero   <= (A_e == 8'b0);buf_B_e_zero   <= (B_e == 8'b0);buf_A          <= iA;buf_B          <= iB;buf_oSum_s     <= A_larger ? A_s : B_s;end// Convert to positive fraction and a sign bit.wire [36:0] pre_frac;assign pre_frac = buf_pre_sum;// Determine output fraction and exponent change with position of first 1.wire [17:0] oSum_f;wire [7:0]  shft_amt;assign shft_amt = pre_frac[36] ? 8'd0  : pre_frac[35] ? 8'd1  :pre_frac[34] ? 8'd2  : pre_frac[33] ? 8'd3  :pre_frac[32] ? 8'd4  : pre_frac[31] ? 8'd5  :pre_frac[30] ? 8'd6  : pre_frac[29] ? 8'd7  :pre_frac[28] ? 8'd8  : pre_frac[27] ? 8'd9  :pre_frac[26] ? 8'd10 : pre_frac[25] ? 8'd11 :pre_frac[24] ? 8'd12 : pre_frac[23] ? 8'd13 :pre_frac[22] ? 8'd14 : pre_frac[21] ? 8'd15 :pre_frac[20] ? 8'd16 : pre_frac[19] ? 8'd17 :pre_frac[18] ? 8'd18 : pre_frac[17] ? 8'd19 :pre_frac[16] ? 8'd20 : pre_frac[15] ? 8'd21 :pre_frac[14] ? 8'd22 : pre_frac[13] ? 8'd23 :pre_frac[12] ? 8'd24 : pre_frac[11] ? 8'd25 :pre_frac[10] ? 8'd26 : pre_frac[9]  ? 8'd27 :pre_frac[8]  ? 8'd28 : pre_frac[7]  ? 8'd29 :pre_frac[6]  ? 8'd30 : pre_frac[5]  ? 8'd31 :pre_frac[4]  ? 8'd32 : pre_frac[3]  ? 8'd33 :pre_frac[2]  ? 8'd34 : pre_frac[1]  ? 8'd35 :pre_frac[0]  ? 8'd36 : 8'd37;wire [53:0] pre_frac_shft, uflow_shift;// the shift +1 is because high order bit is not stored, but impliedassign pre_frac_shft = {pre_frac, 17'b0} << (shft_amt+1); //? shft_amt+1assign uflow_shift = {pre_frac, 17'b0} << (shft_amt); //? shft_amt for overflowassign oSum_f = pre_frac_shft[53:36];wire [7:0] oSum_e;assign oSum_e = buf_larger_exp - shft_amt + 8'b1;// Detect underflowwire underflow;// this incorrectly sets uflow for 10-10.1//assign underflow = ~oSum_e[7] && buf_larger_exp[7] && (shft_amt != 8'b0);// if top bit of matissa is not set, then denormassign underflow = ~uflow_shift[53]; always @(posedge iCLK) beginoSum <= (buf_A_e_zero && buf_B_e_zero)    ? 27'b0 :buf_A_e_zero                     ? buf_B :buf_B_e_zero                     ? buf_A :underflow                        ? 27'b0 :(pre_frac == 0)                  ? 27'b0 :{buf_oSum_s, oSum_e, oSum_f};end //output update
endmodule
(2)代码分析

FpAdd模块的作用是实现浮点数的加法运算。浮点数的表示通常由三个部分组成:符号位(sign bit)、指数(exponent)和尾数(fraction)。这个模块将两个浮点数相加,并将结果存储在输出寄存器oSum中。

对代码分析:

1、输入输出定义:
iCLK:时钟信号。
iA和iB:输入的两个浮点数,每个数27位,包括1位符号位、8位指数位和17位尾数位。
oSum:输出的浮点数结果,也是27位。

2、提取输入浮点数的各部分:
A_s和B_s:分别表示iA和iB的符号位。
A_e和B_e:分别表示iA和iB的指数位。
A_f和B_f:分别表示iA和iB的尾数位,其中最高位隐含为1。

3、对齐尾数:
计算两个指数的差值,确定哪个指数更大。
根据差值,将尾数右移或左移,使它们对齐。

4、确定哪个数更大:
通过比较指数和尾数来确定A和B中哪个数更大,并赋值给A_larger。

5、计算求和或差:
根据符号位和A_larger的值,计算两个浮点数的和或差。

6、缓冲中间结果:
使用always块在时钟上升沿更新中间结果。

7、处理结果的尾数和指数:
根据预处理的尾数pre_frac,确定输出尾数oSum_f和输出指数oSum_e。

8、检测下溢:
检查是否发生下溢,并在必要时将结果设置为0。

9、输出结果:
在时钟上升沿更新输出寄存器oSum,根据条件设置结果。

2. 单精度浮点数的乘法FPGA实现
(1)实现代码(FpMul模块)
module FpMul (input      [26:0] iA,    // First inputinput      [26:0] iB,    // Second inputoutput     [26:0] oProd  // Product
);// Extract fields of A and B.wire        A_s;wire [7:0]  A_e;wire [17:0] A_f;wire        B_s;wire [7:0]  B_e;wire [17:0] B_f;assign A_s = iA[26];assign A_e = iA[25:18];assign A_f = {1'b1, iA[17:1]};assign B_s = iB[26];assign B_e = iB[25:18];assign B_f = {1'b1, iB[17:1]};// XOR sign bits to determine product sign.wire        oProd_s;assign oProd_s = A_s ^ B_s;// Multiply the fractions of A and Bwire [35:0] pre_prod_frac;assign pre_prod_frac = A_f * B_f;// Add exponents of A and Bwire [8:0]  pre_prod_exp;assign pre_prod_exp = A_e + B_e;// If top bit of product frac is 0, shift left onewire [7:0]  oProd_e;wire [17:0] oProd_f;assign oProd_e = pre_prod_frac[35] ? (pre_prod_exp-9'd126) : (pre_prod_exp - 9'd127);assign oProd_f = pre_prod_frac[35] ? pre_prod_frac[34:17] : pre_prod_frac[33:16];// Detect underflowwire        underflow;assign underflow = pre_prod_exp < 9'h80;// Detect zero conditions (either product frac doesn't start with 1, or underflow)assign oProd = underflow        ? 27'b0 :(B_e == 8'd0)    ? 27'b0 :(A_e == 8'd0)    ? 27'b0 :{oProd_s, oProd_e, oProd_f};endmodule
(2)代码分析

FpMul的模块,它的作用是实现了两个浮点数的乘法运算。代码的目的是将两个27位的浮点数相乘,并将结果存储在输出oProd中。以下是对代码的详细解释:

1、模块输入输出:

(1)iA和iB:分别是乘法操作的两个输入浮点数,每个数27位,包括1位符号位、8位指数位和17位尾数位。
(2)oProd:乘法操作的结果,也是27位。

2、提取浮点数的各个字段:
(1)A_s和B_s:分别表示iA和iB的符号位。
(2)A_e和B_e:分别表示iA和iB的指数位。
(3)A_f和B_f:分别表示iA和iB的尾数位,其中最高位隐含为1。

3、确定乘积的符号:
使用异或操作A_s ^ B_s来确定乘积的符号位oProd_s。

4、相乘尾数:

(1)将A_f和B_f相乘,得到36位的中间结果pre_prod_frac。
相加指数:

(2)将A_e和B_e相加,得到9位的中间结果pre_prod_exp。

5、调整指数和尾数:
如果pre_prod_frac的最高位为0,说明乘积需要左移一位,指数减去126(而不是127),否则直接使用减去127的指数。
根据最高位是否为1,选择正确的尾数部分。

6、处理下溢:

如果pre_prod_exp小于9’h80(即小于十进制的128),则认为发生了下溢,此时输出结果为0。

7、处理零条件:

如果B_e或A_e为0,表示其中一个输入数为0,乘积也为0。
如果没有发生下溢,且两个输入数的指数都不为0,将计算得到的符号位、指数和尾数组合成最终的乘积oProd。

代码中有几个需要注意的地方:
尾数相乘的结果pre_prod_frac是36位,这意味着乘法结果可能会超出浮点数尾数的表示范围,需要进行舍入和规范化处理。
指数调整时,如果乘积的尾数需要左移(即pre_prod_frac[35]为0),则指数减去127,否则减去126。这是为了将尾数规范化,使其最高位为1。
下溢条件的检测使用了pre_prod_exp < 9’h80,这个条件可能需要根据具体的实现和标准进行调整。

三、结尾

本篇博客注重描述单精度浮点数在FPGA中乘、加操作。上述两段verilog代码分别实现了浮点数的加法和乘法操作。浮点加法模块FpAdd通过提取输入浮点数的符号位、指数和尾数,对齐尾数,计算和或差,并考虑了下溢情况来生成结果。浮点乘法模块FpMul则通过提取输入浮点数的相应字段,计算尾数的乘积和指数的和,处理可能的下溢,并根据结果的规范化要求调整指数和尾数。两个模块都考虑了符号位的处理,确保了结果的符号正确,并在输出时组合了符号位、指数和尾数来形成最终的浮点数结果。

这篇关于关于FPGA的浮点数处理 III的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1087172

相关文章

百度OCR识别结构结构化处理视频

https://edu.csdn.net/course/detail/10506

DDS信号的发生器(验证篇)——FPGA学习笔记8

前言:第一部分详细讲解DDS核心框图,还请读者深入阅读第一部分,以便理解DDS核心思想 三刷小梅哥视频总结! 小梅哥https://www.corecourse.com/lander 一、DDS简介         DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有低成本、低功耗、高分辨率、频率转换时间短、相位连续性好等优点,对数字信

如何在Java中处理JSON数据?

如何在Java中处理JSON数据? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨在Java中如何处理JSON数据。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,在现代应用程序中被广泛使用。Java通过多种库和API提供了处理JSON的能力,我们将深入了解其用法和最佳

[FPGA][基础模块]跨时钟域传播脉冲信号

clk_a 周期为10ns clk_b 周期为34ns 代码: module pulse(input clk_a,input clk_b,input signal_a,output reg signal_b);reg [4:0] signal_a_widen_maker = 0;reg signal_a_widen;always @(posedge clk_a)if(signal_a)

LeetCode--220 存在重复元素 III

题目 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 示例 示例 1:输入: nums = [1,2,3,1], k = 3, t = 0输出: true示例 2:输入: nums = [1,0,1,1], k = 1, t = 2输出: true示例

AI学习指南机器学习篇-朴素贝叶斯处理连续特征和离散特征

AI学习指南机器学习篇-朴素贝叶斯处理连续特征和离散特征 在机器学习领域,朴素贝叶斯是一种常用的分类算法,它的简单性和高效性使得它在实际应用中得到了广泛的应用。然而,在使用朴素贝叶斯算法进行分类时,我们通常会面临一个重要的问题,就是如何处理连续特征和离散特征。因为朴素贝叶斯算法基于特征的条件独立性假设,所以对于不同类型的特征,我们需要采取不同的处理方式。 在本篇博客中,我们将探讨如何有效地处理

神经网络第四篇:推理处理之手写数字识别

到目前为止,我们已经介绍完了神经网络的基本结构,现在用一个图像识别示例对前面的知识作整体的总结。本专题知识点如下: MNIST数据集图像数据转图像神经网络的推理处理批处理  MNIST数据集          mnist数据图像 MNIST数据集由0到9的数字图像构成。像素取值在0到255之间。每个图像数据都相应地标有“7”、“2”、“1”等数字标签。MNIST数据集中,

vue怎么处理跨域

Vue.js 本身并不直接解决跨域问题,因为跨域问题主要是浏览器基于同源策略(Same-origin policy)的一种安全限制。然而,在Vue.js项目中,我们可以采取一些策略来绕过或处理跨域问题。 解决跨域问题的常用方法: 代理服务器:在开发环境中,我们可以配置一个代理服务器来转发API请求,从而绕过浏览器的同源策略。Vue CLI 提供了内置的代理功能,可以在 vue.config.j

【机器学习】自然语言处理的新前沿:GPT-4与Beyond

📝个人主页:哈__ 期待您的关注  目录 🔥引言 背景介绍 文章目的 一、GPT-4简介 GPT-4概述 主要特性 局限性和挑战 二、自监督学习的新进展 自监督学习的原理 代表性模型和技术 三、少样本学习和零样本学习 少样本学习的挑战 先进方法 四、跨模态学习 跨模态学习的概念 代表性技术 应用场景 第五部分:可解释性和透明性 AI的可解释

【文末附gpt升级秘笈】腾讯元宝AI搜索解析能力升级:千万字超长文处理的新里程碑

腾讯元宝AI搜索解析能力升级:千万字超长文处理的新里程碑 一、引言 随着人工智能技术的飞速发展,自然语言处理(NLP)和机器学习(ML)在各行各业的应用日益广泛。其中,AI搜索解析能力作为信息检索和知识抽取的核心技术,受到了广泛的关注和研究。腾讯作为互联网行业的领军企业,其在AI领域的探索和创新一直走在前列。近日,腾讯旗下的AI大模型应用——腾讯元宝,迎来了1.1.7版本的升级,新版本在AI搜