FIR调用DSP48E_05
作者:桂。
时间:2018-02-06 17:52:38
链接:http://www.cnblogs.com/xingshansi/p/8423457.html
前言
到目前为止,本文没有对滤波器实现进行梳理,FIR仿真验证的平台(基于FPGA实现)包括HLS、Systemgenerator,至于*.v 与*.sv可通过程序(如python实现)完成转化,FIR的零散记录到本篇告一段落,本文重点记录DSP48E的使用
一、DSP48E
A-基本结构
主要参考UG479.pdf,DSP48E1结构:
可以看出主要功能为:P = (A±D)×B±C。具体功能可参考IP核:
slice结构及位宽关系:
DSP48E在Xilinx内部的布局:
常用器件DSP48E资源:
B-原语调用
原语类似C语言的汇编,直接关联器件的底层结构,因此通常时序可以做的更好。
DSP48E支持原语调用,记录两个例子:
Ex1:
`timescale 1ns / 1ps// m = b * (a + d) // p = c+m or p+m module dsp48_wrap_f(input clock,input ce1,input ce2,input cem,input cep,input signed [24:0] a,input signed [17:0] b,input signed [47:0] c,input signed [24:0] d, // this has two fewer pipe stages// X+Y is usually the multiplier output (M)// Z is either P, PCIN or C// bit 1:0: 0: Z+X+Y 3:Z-(X+Y) 1: -Z + (X+Y) 2: -1*(Z+X+Y+1)// bits 3:2, 0: Z=0, 1: Z=PCIN, 2: Z=P, 3: Z = C// bit 4: sub in pre addinput [4:0] mode,input signed [47:0] pcin,output signed [47:0] pcout,output signed [47-S:0] p);parameter S = 0;parameter USE_DPORT = "FALSE"; // enabling adds 1 reg to A pathparameter AREG = 1;parameter BREG = 1; // 0 - 2wire signed [47:0] dsp_p;assign p = dsp_p[47:S];DSP48E1#(.A_INPUT("DIRECT"), // "DIRECT" "CASCADE".B_INPUT("DIRECT"), // "DIRECT" "CASCADE".USE_DPORT(USE_DPORT),.USE_MULT("MULTIPLY"),// "MULTIPLY" "DYNAMIC" "NONE".USE_SIMD("ONE48"), // "ONE48" "TWO24" "FOUR12"// pattern detector - not used.AUTORESET_PATDET("NO_RESET"), .MASK(48'h3fffffffffff),.PATTERN(48'h000000000000), .SEL_MASK("MASK"),.SEL_PATTERN("PATTERN"), .USE_PATTERN_DETECT("NO_PATDET"),// register enables.ACASCREG(1), // pipeline stages between A/ACIN and ACOUT (0, 1 or 2).ADREG(1), // pipeline stages for pre-adder (0 or 1).ALUMODEREG(1), // pipeline stages for ALUMODE (0 or 1).AREG(AREG), // pipeline stages for A (0, 1 or 2).BCASCREG(1), // pipeline stages between B/BCIN and BCOUT (0, 1 or 2).BREG(BREG), // pipeline stages for B (0, 1 or 2).CARRYINREG(1), // this and below are 0 or 1.CARRYINSELREG(1),.CREG(1),.DREG(1),.INMODEREG(1),.MREG(1),.OPMODEREG(1),.PREG(1))dsp48_i(// status.OVERFLOW(),.PATTERNDETECT(), .PATTERNBDETECT(),.UNDERFLOW(),// outs.CARRYOUT(),.P(dsp_p),// control.ALUMODE({2'd0, mode[1:0]}),.CARRYINSEL(3'd0),.CLK(clock),.INMODE({1'b0,mode[4],3'b100}),.OPMODE({1'b0,mode[3:2],4'b0101}),// signal inputs.A({5'd0,a}), // 30.B(b), // 18.C(c), // 48.CARRYIN(1'b0),.D(d), // 25// cascade ports.ACOUT(),.BCOUT(),.CARRYCASCOUT(),.MULTSIGNOUT(),.PCOUT(pcout),.ACIN(30'h0),.BCIN(18'h0),.CARRYCASCIN(1'b0),.MULTSIGNIN(1'b0),.PCIN(pcin),// clock enables.CEA1(ce1), .CEA2(ce2),.CEAD(1'b1),.CEALUMODE(1'b1),.CEB1(ce1), .CEB2(ce2),.CEC(1'b1),.CECARRYIN(1'b1),.CECTRL(1'b1), // opmode.CED(1'b1),.CEINMODE(1'b1),.CEM(cem), .CEP(cep),.RSTA(1'b0),.RSTALLCARRYIN(1'b0),.RSTALUMODE(1'b0),.RSTB(1'b0),.RSTC(1'b0),.RSTCTRL(1'b0),.RSTD(1'b0),.RSTINMODE(1'b0),.RSTM(1'b0),.RSTP(1'b0));endmodule // dsp48_wrap_f
Ex2:
// p = c + b * a 3 cycles if r else p = p + b * a module macc(input clock,input [2:0] ce, // bit 0 = a, 1 = b , 2 = cinput r, // reset accumulator to c + a*binput signed [24:0] a,input signed [17:0] b,input signed [47:0] c,output signed [47-S:0] p);parameter S = 0;parameter AREG = 1; // 0 - 2parameter BREG = 1; // 0 - 2wire signed [47:0] dsp_p;assign p = dsp_p[47:S];// X+Y is usually the multiplier output (M)// Z is either P, PCIN or C// bit 1:0: 0: Z+X+Y 3:Z-(X+Y) 1: -Z + (X+Y) 2: -1*(Z+X+Y+1)// bits 3:2, 0: Z=0, 1: Z=PCIN, 2: Z=P, 3: Z = C// bit 4: sub in pre addwire [4:0] mode = {1'b0, r ? 2'b11 : 2'b10, 2'b00};DSP48E1#(.A_INPUT("DIRECT"), // "DIRECT" "CASCADE".B_INPUT("DIRECT"), // "DIRECT" "CASCADE".USE_DPORT("FALSE"),.USE_MULT("MULTIPLY"),// "MULTIPLY" "DYNAMIC" "NONE".USE_SIMD("ONE48"), // "ONE48" "TWO24" "FOUR12"// pattern detector - not used.AUTORESET_PATDET("NO_RESET"), .MASK(48'h3fffffffffff),.PATTERN(48'h000000000000), .SEL_MASK("MASK"),.SEL_PATTERN("PATTERN"), .USE_PATTERN_DETECT("NO_PATDET"),// register enables.ACASCREG(1), // pipeline stages between A/ACIN and ACOUT (0, 1 or 2).ADREG(1), // pipeline stages for pre-adder (0 or 1).ALUMODEREG(1), // pipeline stages for ALUMODE (0 or 1).AREG(AREG), // pipeline stages for A (0, 1 or 2).BCASCREG(1), // pipeline stages between B/BCIN and BCOUT (0, 1 or 2).BREG(BREG), // pipeline stages for B (0, 1 or 2).CARRYINREG(1), // this and below are 0 or 1.CARRYINSELREG(1),.CREG(1),.DREG(1),.INMODEREG(1),.MREG(1),.OPMODEREG(1),.PREG(1))dsp48_i(// status.OVERFLOW(),.PATTERNDETECT(), .PATTERNBDETECT(),.UNDERFLOW(),// outs.CARRYOUT(),.P(dsp_p),// control.ALUMODE({2'd0, mode[1:0]}),.CARRYINSEL(3'd0),.CLK(clock),.INMODE({1'b0,mode[4],3'b100}),.OPMODE({1'b0,mode[3:2],4'b0101}),// signal inputs.A({5'd0,a}), // 30.B(b), // 18.C(c), // 48.CARRYIN(1'b0),.D(25'd0), // 25// cascade ports.ACOUT(),.BCOUT(),.CARRYCASCOUT(),.MULTSIGNOUT(),.PCOUT(),.ACIN(30'h0),.BCIN(18'h0),.CARRYCASCIN(1'b0),.MULTSIGNIN(1'b0),.PCIN(48'h0),// clock enables.CEA1(1'b1), .CEA2(ce[0]),.CEAD(1'b1),.CEALUMODE(1'b1),.CEB1(1'b1), .CEB2(ce[1]),.CEC(ce[2]),.CECARRYIN(1'b1),.CECTRL(1'b1), // opmode.CED(1'b1),.CEINMODE(1'b1),.CEM(1'b1), .CEP(1'b1),.RSTA(1'b0),.RSTALLCARRYIN(1'b0),.RSTALUMODE(1'b0),.RSTB(1'b0),.RSTC(1'b0),.RSTCTRL(1'b0),.RSTD(1'b0),.RSTINMODE(1'b0),.RSTM(1'b0),.RSTP(1'b0));endmodule
二、FIR实现思路
考虑到调用DSP48E,首先分析DSP48E乘法/乘加的时序特性:
可以看出输出相比输入,延迟4拍,仿真3*5,结果与理论一致:
以N-1(不失一般性,N=6)阶FIR为例,由于乘法可支持25*18,假设数据18(bit),滤波器系数25(bit)。滤波器系数个数为6:
因此可得FIR实现的基本流程:
- Step1:对于t时刻,输入数据与滤波器系数相乘,得到y(t)[N-1:0]
- Step2:更新数据流:data_chain(t) = y(t)[N-1:0] + [data_chain(t-1) [N-2:0],0]
- Step3:输出滤波结果:output = data_chain(t) [N-1]
根据算法流程,设计FPGA数据流:
1)参数位宽定义
- 输入数据:parameter indatwidth = 18;
- 滤波器系数:parameter coefwidth = 25;
- DSP48核输出位宽:localparam multoutwidth = coefwidth + indatwidth;
- 输出数据(自定义):parameter outdatwidth = 18;
- 数据流(截断位宽自定义):这里 localparam chainwidth 用multoutwidth替代;
2)数据运算拆解
结合上文Step2的特性,细节上:a)可针对coef0单独用乘法运算、其他coef利用乘加运算,b)也可以对datachain补零,这里采用后一种思路。
- 输入输出
input [indatwidth-1:0] datin;
input [5:0][coefwidth-1:0] coef;
input clk,rst;
output signed [outdatwidth-1:0] datout;
- DSP48的乘加操作
genvar ii;
generate
for(ii = 0; ii < N; ii++)
begin
multiplus mpu(
.CLK(clk),
.A(coef[ii]),
.B(datin),
.C(dti[ii]),
.P(mres[ii])
);
end
endgenerate
- 关于截位
对数据进行截位,例如对x截位,通常不是直接舍去其他位数,而是对x进行4舍5入,转化到FPGA就是:
x1 <= x[起始位置 -: 有效位数] + 1;
result <= (x1>>>1);
这里仅论证实现思路,截位的细节操作不再添加。
- 乘法器的延拍
genvar ii;
generate
for(ii = 1; ii < N; ii++)
begin
always @(posedge clk) begin
dtchain[ii][fixdelay-1:1] <= dtchain[ii][fixdelay-2:0];
dtchain[ii][0] <= mres[ii-1][multoutwidth-1:0];
end
end
endgenerate
三、仿真验证
首先MATLAB仿真验证上述步骤的有效性:
%FIR功能验证 clc;clear all;close all; coef = [-15,19,123,123,19,-15]; datin = [3,13,17,21,24,28,31]; %main %不考虑延拍,datachain不必引入 N = 6; mres = zeros(1,N); dto = zeros(1,N); result = []; for i = 1:length(datin)dto(2:N) = mres(1:N-1);mres = datin(i)*coef + dto;result = [result,mres(N)]; end %compare conv_res = conv(datin,coef); [result;conv_res(1:length(datin))]
算法运算结果与理论一致:
编写测试模块及testbench:
winfilter.sv
`timescale 1ns / 1ps module winfilter(coef, datin, clk, rst, datout); //parameter parameter indatwidth = 18; parameter outdatwidth = 18; parameter coefwidth = 25; localparam multoutwidth = coefwidth + indatwidth; localparam N = 6; localparam fixdelay = 4;//smultplus delay //port input [indatwidth-1:0] datin; input [N-1:0][coefwidth-1:0] coef; input clk,rst; output [outdatwidth-1:0] datout; //define reg signed [outdatwidth-1:0] datout; reg [N-1:0][fixdelay-1:0][multoutwidth-1:0] dtchain; wire [N-1:0][multoutwidth:0] mres; //initial initial begindtchain <= 0;datout <= 0; end //main genvar ii; generatefor(ii = 1; ii < N; ii++)beginalways @(posedge clk) begindtchain[ii][fixdelay-1:1] <= dtchain[ii][fixdelay-2:0];dtchain[ii][0] <= mres[ii-1][multoutwidth-1:0];endend endgenerate generatefor(ii = 0; ii < N; ii++)beginmultiplus multp_inst(.CLK(clk),.A(coef[ii]),.B(datin),.C(dtchain[ii][fixdelay-1]),.P(mres[ii]));end endgenerate //output always @(posedge clk) beginif(rst)begindatout <= 0;endelsebegindatout <= mres[N-1][multoutwidth-19 -: outdatwidth];//datout <= mres[N-1][multoutwidth-2 -: outdatwidth];end end endmodule
tb
`timescale 1ns / 1ps module tb(); logic [17:0] datin; logic clk,rst; logic [5:0][24:0] coef; logic [17:0] datout;//-------------------------------------// parameter data_num = 32'd1024; reg [17:0] data_men[1:data_num]; initial begin$readmemb("D:/PRJ/vivado/simulation_ding/009_lpf6tap/matlab/sin_data.txt",data_men); end integer i = 1; always @(posedge clk) begindatin <= data_men[i];i <= i + 8'd1; endinitial beginclk <= 0;rst <= 0;datin <= 0;coef <= 0; #4 coef <= {-25'd15,25'd19,25'd123,25'd123,25'd19,-25'd15}; #6000 $stop; endalways #2 clk = ~clk;winfilter wininst( .coef(coef), .datin(datin), .clk(clk), .rst(rst), .datout(datout) ); endmodule
其中dsp48参数设置:
仿真结果:
转载于:https://www.cnblogs.com/xingshansi/p/8423457.html
FIR调用DSP48E_05相关推荐
- FIR特性及仿真实现_01
作者:桂. 时间:2018-02-05 19:01:21 链接:http://www.cnblogs.com/xingshansi/p/8419007.html 前言 本文主要记录FIR(finit ...
- 基础004_V7-DSP Slice
主要参考ug479.pdf.之前的文章:FIR调用DSP48E_05.本文主要记录基本用法. 一.DSP48核 A-参数说明 instrctions,多个功能,通过sel选用 目前没发现C勾选与否,有 ...
- Xilinx 常用模块汇总(verilog)【03】
作者:桂. 时间:2018-05-10 2018-05-10 21:03:44 链接:http://www.cnblogs.com/xingshansi/p/9021919.html 前言 主要记 ...
- FPGA(五):Quartus II 调用Fir IP核使用说明
这几天在忙着写通信原理的项目,其中用到了fir滤波器的部分,从最初的一脸懵逼到初步理解了该怎么去调用ip核以及参数设置,这其中的过程着实不易.这篇博客主要是为了记录自己的学习过程以便日后也可以回想起来 ...
- matlab低通滤波器库函数代码_利用Matlab filterDesigner 工具生成FIR滤波器函数,并调用实现低通滤波...
本文使用的开发环境为:Win10 Matlab2018a 版本. 在matlab命令窗口输入:filterDesigner命令,即可打开filterDesigner设计工具. 按照下图调整FIR低通滤 ...
- fir.im Weekly - iOS 保持界面流畅的技巧
2019独角兽企业重金招聘Python工程师标准>>> 生命不息,coding 不止.本期 fir.im Weekly 收集了微博上的热转资源,包含 Android.iOS 开发工具 ...
- (多图) 基于Verilog HDL的FIR数字滤波器设计与仿真
引言:数字滤波器是语音与图像处理.模式识别.雷达信号处理.频谱分析等应用中的一种基本的处理部件,它能满足波器对幅度和相位特性的严格要求,避免模拟滤波器所无法克服的电压漂移.温度漂移和噪声等问题.有限冲 ...
- 基于FPGA的IP核RAM的设计和调用
介绍IP核: IP(知识产权)核将一些在数字电路中常用但比较复杂的功能块,如FIR滤波器,SDRAM控制器,PCI接口等做成一个"黑盒"或者可修改参数的模块,供设计者使用.IP核包 ...
- 关于xilinx fir use reloadable coefficient的用法
最近用到系数可以重新配置的fir滤波器,调用xilinx提供的ip core,使用了use reloadable coefficient功能,但有以下几点疑问,哪位有用过的大虾能否指点迷津下 1.使用 ...
最新文章
- STM32如何查找hardfault原因
- html导航去下划线,纯CSS实现导航栏下划线跟随的示例代码
- 我的Linux系统入坑之路!!!!
- 【若依(ruoyi)】shiro 内置的过滤器(filter)
- 证明randomized quicksort的平均running time为nlgn 的数学过程
- 寒假集训日志(二)——最小生成树,拓扑排序,欧拉回路,连通路
- 计算机网络(一)——一些概念
- 06002_Redis概述
- Unity-中英对照汉化
- HyperLynx(三)传输线类型及相关设置
- php 同比增长率上期未0,同比增长率计算时,上期值为0怎么计算?
- 微信小程序引入iconfont阿里字体
- 电源 PFC(功率因数校正)电路拓扑,共计100多份,内含A PFC,连续断续,交错,维也纳,各功率段的PFC电路
- MongoDB—Mac M1的安装
- 动手打造N合1操作系统安装光盘
- QT菜单栏颜色与背景颜色设置
- PS改变图片颜色的方法
- ubuntu设置共享文件夹成功后却不显示找不到
- 28.EOS的共识机制与区块生成
- win7的远程桌面连接在哪
热门文章
- python加载项向导_什么是 Python 加载项?
- oracle9i用expdp导出全库,Linux下Oracle 11g数据库全库自动备份(EXPDP)
- C语言 | 基于MPU605(六轴传感器)的I2C实现LCD1602显示(代码类)
- html预览不出效果是怎么回事,为何HTML文件直接双击打不开 要用浏览器才能打开 之前双击还能打开显示效果的...
- 如何用SendMessage模拟某一按钮的点击事件
- java正则表示过滤汉字,Java正则表达式过滤汉字
- python中怎么比较两个列表的大小_Python:找到两个列表中存在的给定长度的公共子列表...
- C语言实现离散余弦变换(DCT)并用MATLAB和Python验证
- 为什么读博士的人越来越多?博士毕业难度不是越来越大吗?
- 【NLP】好资源!近 20 万本 txt 书籍的语料库,可用于 GPT 模型训练和语义分析...