一、前言

  FPGA以擅长高速并行数据处理而闻名,从有线/无线通信到图像处理中各种DSP算法,再到现今火爆的AI应用,都离不开卷积、滤波、变换等基本的数学运算。但由于FPGA的硬件结构和开发特性使得其对很多算法不友好,之前本人零散地总结和转载了些基本的数学运算在FPGA中的实现方式,今天做一个系统的总结归纳。

二、FPGA中的加减乘除

1.硬件资源

  Xilinx 7系列的FPGA中有DSP Slice ,叫做“DSP48E1”这一专用硬件资源,这是一个功能强大的计算单元,单就用于基本运算的部分有加减单元和乘法器。详见参考文献1.

  因此可以直接用HDL语言中的加、减、乘符号实现变量与常量间运算操作以及变量与变量间操作。而四则运算中的除法没有基本的逻辑计算单元可以对应,因此计算除法需要调用除法器IP核。

2.确认数据的表示范围

  有符号数:(补码)-2^(N-1) ~ 2^(N-1)-1 如N = 8,则表示范围是:-128 ~ 127.

    无符号数:0~2^N-1 如N = 8,则表示范围是:0~255.

  定点数:2Q13 范围是:-4~4-2^(-13) 精度是:2^(-13)

3.结果有效位宽

  首先讨论结果位宽问题。在FPGA中往往采用定点运算替代浮点运算来降低硬件资源占用率和计算延迟,其中的精髓就是精度与资源的权衡。若按照保留计算结果的全部精度,N bit数与Mbit数相加结果需要N+1bit(N>M)。N bit数与M bit数相乘之积需要N+M bit。而减法可以转化为加法,除法则转换为乘法和加减法的组合。如果操作数是定点小数,则在满足以上准则的前提下,A与B相加(A小数点位数>B小数点位数),结果小数点位数与A相同;A与B相乘(小数点位数分别为p和q),结果小数点位数是p+q。

4.定点运算步骤

  然而(话锋一转),在大多数场合下,不需要以上这么多位来保留计算结果,因为我们在进行数学运算时,已经知道输入数据的大致范围,一个数除以1000和除以1结果数据所需最小位宽能一样么?加减运算的操作步骤是先对齐小数点位数,后加减。而乘法是先计算后取小数点。这实际上与十进制运算一致,我们看看具体的计算步骤:

整数之间加减以及乘法的统一步骤:预估结果位宽N --> 按照结果位宽扩展操作数符号位以防止溢出 --> 运算取低N位。

定点小数加减运算步骤:预估结果位宽N --> 得到结果小数点后位数 --> 对齐操作数整数位和小数位,确定扩展位宽M(M≥N) --> 加减运算取低M位。

定点小数乘法运算步骤:预估结果位宽N --> 得到结果小数点后位数 --> 扩展操作数位宽 --> 相乘取低N位

5. 变量与常量运算化简

  以上讨论的均是两变量之间的运算规则,当然结果位宽及格式准则是适用的。变量与常量的运算的优势在于,可以将乘除法转换成加减以及移位运算实现,从而降低计算复杂度和延迟。当常数项C为2的整数次幂(C = 2^p),则乘C等于变量左移p位,除以C等于变量右移p位。几个在书中看到的几个简单示例:A*16 = A <<4  A*20 = A<<4 + A<<2.  A除以2 = A >>1  A除以3 = A*(0.25+0.0625+0.0156) = A>>2+A>>4+A>>6  A除以5 = A*(0.125+0.0625+0.0156) = A>>3 + A>>4 + A>>6.其中乘法完全等价对应的移位相加操作,而除法的移位代替会损失精度。

三、如何计算特殊函数

  FPGA内部的DSP Slice可以直接进行最基本的加法和乘法运算,但是对于其他比如对数、指数、三角函数、开根号等特殊函数就无能为力了。这时需要借助算法对这些特殊函数进行变换和简化。FPGA实现复杂函数的常用手段一个是级数展开,再一个就是CORDIC算法。关于CORDIC的理论知识和具体内容详见参考文献2,这里主要阐述CORDIC的IP核调用以及应用示例。CORDIC算法就是通过一定的手段,将很多复杂的特殊函数变为相加移位运算,这一点对于硬件芯片实现来说非常友好。CORDIC分为旋转模式和矢量模式,配合圆周坐标、线性坐标和双曲线坐标会有六种组合,具体见下表:

  从表中发现,基本的乘除法、三角函数、反三角函数、双曲函数、反双曲函数、开根号都能够直接求得,那其他函数怎么办?

  常见的函数计算需求基本都能满足,虽上述变换式对自变量定义域有限制,但同样可以分析输入数据的取值范围并利用简单的数学变换得到想要的结果。Xilinx同时提供了浮点IP核以及CORDIC IP核,前者调用简单但占用资源大,延迟高,因此利用CORDIC算法计算函数是个较好的选择。

四、CORDIC计算e^x Demo

1. 算法仿真分析

  要计算e^x数值需要让CORDIC工作在双曲坐标的旋转模式下,通过e^x = sinhx+coshx关系式间接求得。首先看下sinh和cosh函数的曲线,有个直观认识。

                                                   

  我们用MATLAB毫不费力地验证一下公式正确性:

  在设计后也同样要借助MATLAB进行仿真验证。

2. CORDIC IP核

  现在通过查看user guide得知CORDIC IP核的接口及主要特性。

  接口包括输入笛卡尔数据输入通道、相位输入通道、全局信号以及数据输出通道。该IP核有两种结构:串行和并行,可根据数据吞吐量需求选择,并行结构可以每个时钟输出一个计算结果。如果计算sinh和cosh,要向phase通道输入相位信息,X_OUT是cosh(phase),Y_OUT是sinh(phase).输入phase必须满足数据范围,否则出现不可预计结果。输出帧结构及数据范围如下:

  其中输入数据格式为2QN,输出则是1QN。由于均是有符号数,也就是输入整数部分3bit,输出整数部分2bit。接下来对IP核进行配置,重点是第一页,此处将其配置为计算sinh和cosh模式,采用并行优化的流水线结构。相位以角度为单位,输入输出位宽设置成16bit。

 3.HDL代码设计及仿真验证

设计代码:

 `timescale 1ns / 1ps

 module cordic_ex#(parameter DIN_W = ,
DOUT_W = )
(
input clk,
input [DIN_W-:] din,//2Q13
input din_vld, output reg [DOUT_W+-:] dout = ,//2Q14
output reg dout_vld =
); wire [DOUT_W*- : ] m_axis_dout_tdata;
wire m_axis_dout_tvalid;
wire signed [DOUT_W-:] sinh,cosh; // ex = sinhx + coshx <1Q14+1Q14 = 2Q14>
always @(posedge clk)begin
dout <= sinh + cosh;
end assign sinh = m_axis_dout_tdata[DOUT_W*- -:DOUT_W];
assign cosh = m_axis_dout_tdata[DOUT_W- -:DOUT_W]; always @(posedge clk)begin
if(m_axis_dout_tvalid)begin
dout_vld <= 'b1;
end
else
dout_vld <= ;
end cordic_0 cordic_cosh_sinh (
.aclk(clk), // input wire aclk
.s_axis_phase_tvalid(din_vld), // input wire s_axis_phase_tvalid
.s_axis_phase_tdata(din), // input wire [15 : 0] s_axis_phase_tdata
.m_axis_dout_tvalid(m_axis_dout_tvalid), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(m_axis_dout_tdata) // output wire [31 : 0] m_axis_dout_tdata
); endmodule

cordic_ex

  用MATLAB产生两组数据,并将角度值定点化后作为设计模块数据激励:

testbench:

 `timescale 1ns / 1ps

 module cordic_ex_tb();

 parameter CYC = ;

 reg clk;
reg [-:] din;
reg din_vld; wire signed [-:] dout;
wire dout_vld; cordic_ex#(.DIN_W(),
.DOUT_W())
uut(
.clk (clk) ,
.din (din) ,//2Q13
.din_vld (din_vld) ,
.dout (dout) ,//2Q14
.dout_vld (dout_vld)
); initial begin
clk = ;
forever #(CYC/) clk = ~clk;
end initial begin
#;
din = ;
din_vld = ;
#(CYC*); din_vld = ;
din = 'b0001010000011011;//pi * 1/5
#(CYC*);
din = 'b1110011011011110;//-pi * 1/4
#;
$stop;
end endmodule

cordic_ex_tb

仿真结果:

  仿真波形表明,计算结果与MATLAB浮点运算相近,满足一般计算需求。若想提高精度,可以增加CORDIC输出数据位宽。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

参考文献:

1 ug479 7 Series DSP48E1 Slice User Guide.

2 Xilinx CORDIC算法(非常经典)_图文_百度文库 https://wenku.baidu.com/view/6c623aa8910ef12d2bf9e732.html

数字信号处理专题(2)——利用FPGA进行基本运算及特殊函数定点运算的更多相关文章

  1. 数字信号处理专题(1)——DDS函数发生器环路Demo

    一.前言 会FPGA硬件描述语言.设计思想和接口协议,掌握些基本的算法是非常重要的,因此开设本专题探讨些基于AD DA数字信号处理系统的一些简单算法,在数字通信 信号分析与检测等领域都会或多或少有应用 ...

  2. 数字信号处理专题(3)——FFT运算初探

    一.前言 FFT运算是目前最常用的信号频谱分析算法.在本科学习数字信号处理这门课时一直在想:学这些东西有啥用?公式推来推去的,有实用价值么?到了研究生后期才知道,广义上的数字信号处理无处不在:手机等各 ...

  3. 转载--关于FPGA设计数字信号处理电路的心得

    FPGA使用的越来越广泛,除了可用于设计控制电路以为,数字信号处理电路更是FPGA的强项和难点.个人可以说才刚刚入门FPGA设计,也做过一些数字信号处理方面的电路设计,记录下个人心得体会. (一)善用 ...

  4. FPGA与数字信号处理

    过去十几年,通信与多媒体技术的快速发展极大地扩展了数字信号处理(DSP)的应用范围.眼下正在发生的是,以更高的速度和更低的成本实现越来越复杂的算法,这是针对高级信息服更高带宽以及增强的多媒体处理能力等 ...

  5. 数字信号处理MATLAB简单序列

    数字信号处理应用的几个基本序列: 1 单位样本序列 function mainImseq() clc clear disp('生成抽样序列'); y=imseq(,,); %调用样本函数,此时序列下标 ...

  6. 现代数字信号处理——AR模型

    1. AR模型概念观       AR模型是一种线性预测,即已知N个数据,可由模型推出第N点前面或后面的数据(设推出P点),所以其本质类似于插值,其目的都是为了增加有效数据,只是AR模型是由N点递推, ...

  7. 几幅图片弄清DFT、DTFT、DFS的关系 数字信号处理

    原址:http://www.cnblogs.com/BitArt/archive/2012/11/24/2786390.html 很多同学学习了数字信号处理之后,被里面的几个名词搞的晕头转向,比如DF ...

  8. 《数字信号处理》课程实验2 – FIR数字滤波器设计

    一.FIR数字滤波器设计原理  本实验采用窗函数法设计FIR数字低通滤波器.我们希望设计的滤波器系统函数如下: \(H_{d}\left( e^{jw} \right) = \left\{ \begi ...

  9. 《数字信号处理》课程实验1 – FFT的实现

    一.按时间抽选的基-2 FFT实现原理 观察DIT(基2)FFT的流图(N点,N为2的幂次),可以总结出如下规律: (1)共有\(L=\log_2⁡N\)级蝶形运算: (2)输入倒位序,输出自然顺序: ...

随机推荐

  1. x宝23大洋包邮的老式大朝华MP3播放器简单评测

    (纯兴趣测评,非广告) 最近逛X宝,看到了这个古董级MP3播放器居然还在售,于是脑抽+情怀泛滥买了一个. 然后呢,从遥远的深圳跨越好几千公里邮过来了这个玩意: 那节南孚5号电池是我自己的,是为了对比一 ...

  2. jdbc连接数据库,中文出现乱码的问题

    一.使用jdbc连接数据库,插入数据库时,数据里的数据显示乱码,为 " ??? " 两种解决方案: 1.修改服务端的mysql配置文件,编辑my.cnf文件,在[mysqld]下添 ...

  3. 微信小程序 写一个获取验证码 及setInterval 使用基本方法

    <!--index.wxml--> <view class="container"> <view class="container_cont ...

  4. Hadoop系列009-NameNode工作机制

    本人微信公众号,欢迎扫码关注! NameNode工作机制 1 NameNode & SecondaryNameNode工作机制 1.1 第一阶段:namenode启动 1)第一次启动namen ...

  5. 利用 vue-cli 构建一个 Vue 项目

    一.项目初始构建 现在如果要构建一个 Vue 的项目,最方便的方式,莫过于使用官方的 vue-cli . 首先,咱们先来全局安装 vue-cli ,打开命令行工具,输入以下命令: $ npm inst ...

  6. ActivityJump+ActivityManager【Activity之间的跳转和Activity任务栈管理】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 封装Activity跳转的方法以及实现Activity任务栈管理. 效果图   代码分析 ActivityJump:封装Activi ...

  7. Android-PickerView【仿iOS的PickerView控件,并封装了时间选择和选项选择这两种选择器】使用

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本文主要演示Android-PickerView的选项选择器.时间选择器的简单运用.由于每一个版本略有不用,所以实际使用方式以git ...

  8. MaterialCalendarDialog【Material样式的日历对话框】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 Material样式的日历对话框 前提条件:Activity界面必须继承FragmentActivity或者其子类(比如AppCom ...

  9. TabBottomFragmentLayout【自定义底部选项卡区域(搭配Fragment)】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 自定义底部选项卡布局LinearLayout类,然后配合Fragment,实现切换Fragment功能. 缺点: 1.底部选项卡区域 ...

  10. 微信公众号开发C#系列-5、用户和用户组管理-支持同步

    1.概述 眼前时下流行的经济有个叫粉丝经济,粉丝带动收益.一个好运营良好的公众号肯定会有一大批的粉丝团,如何挖掘粉丝来产生效益,是微信营销的关键.微信公众号后台本身提供了粉丝(用户)与用户分组的管理, ...