作者:桂。

时间: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相关推荐

  1. FIR特性及仿真实现_01

    作者:桂. 时间:2018-02-05  19:01:21 链接:http://www.cnblogs.com/xingshansi/p/8419007.html 前言 本文主要记录FIR(finit ...

  2. 基础004_V7-DSP Slice

    主要参考ug479.pdf.之前的文章:FIR调用DSP48E_05.本文主要记录基本用法. 一.DSP48核 A-参数说明 instrctions,多个功能,通过sel选用 目前没发现C勾选与否,有 ...

  3. Xilinx 常用模块汇总(verilog)【03】

    作者:桂. 时间:2018-05-10  2018-05-10  21:03:44 链接:http://www.cnblogs.com/xingshansi/p/9021919.html 前言 主要记 ...

  4. FPGA(五):Quartus II 调用Fir IP核使用说明

    这几天在忙着写通信原理的项目,其中用到了fir滤波器的部分,从最初的一脸懵逼到初步理解了该怎么去调用ip核以及参数设置,这其中的过程着实不易.这篇博客主要是为了记录自己的学习过程以便日后也可以回想起来 ...

  5. matlab低通滤波器库函数代码_利用Matlab filterDesigner 工具生成FIR滤波器函数,并调用实现低通滤波...

    本文使用的开发环境为:Win10 Matlab2018a 版本. 在matlab命令窗口输入:filterDesigner命令,即可打开filterDesigner设计工具. 按照下图调整FIR低通滤 ...

  6. fir.im Weekly - iOS 保持界面流畅的技巧

    2019独角兽企业重金招聘Python工程师标准>>> 生命不息,coding 不止.本期 fir.im Weekly 收集了微博上的热转资源,包含 Android.iOS 开发工具 ...

  7. (多图) 基于Verilog HDL的FIR数字滤波器设计与仿真

    引言:数字滤波器是语音与图像处理.模式识别.雷达信号处理.频谱分析等应用中的一种基本的处理部件,它能满足波器对幅度和相位特性的严格要求,避免模拟滤波器所无法克服的电压漂移.温度漂移和噪声等问题.有限冲 ...

  8. 基于FPGA的IP核RAM的设计和调用

    介绍IP核: IP(知识产权)核将一些在数字电路中常用但比较复杂的功能块,如FIR滤波器,SDRAM控制器,PCI接口等做成一个"黑盒"或者可修改参数的模块,供设计者使用.IP核包 ...

  9. 关于xilinx fir use reloadable coefficient的用法

    最近用到系数可以重新配置的fir滤波器,调用xilinx提供的ip core,使用了use reloadable coefficient功能,但有以下几点疑问,哪位有用过的大虾能否指点迷津下 1.使用 ...

最新文章

  1. STM32如何查找hardfault原因
  2. html导航去下划线,纯CSS实现导航栏下划线跟随的示例代码
  3. 我的Linux系统入坑之路!!!!
  4. 【若依(ruoyi)】shiro 内置的过滤器(filter)
  5. 证明randomized quicksort的平均running time为nlgn 的数学过程
  6. 寒假集训日志(二)——最小生成树,拓扑排序,欧拉回路,连通路
  7. 计算机网络(一)——一些概念
  8. 06002_Redis概述
  9. Unity-中英对照汉化
  10. HyperLynx(三)传输线类型及相关设置
  11. php 同比增长率上期未0,同比增长率计算时,上期值为0怎么计算?
  12. 微信小程序引入iconfont阿里字体
  13. 电源 PFC(功率因数校正)电路拓扑,共计100多份,内含A PFC,连续断续,交错,维也纳,各功率段的PFC电路
  14. MongoDB—Mac M1的安装
  15. 动手打造N合1操作系统安装光盘
  16. QT菜单栏颜色与背景颜色设置
  17. PS改变图片颜色的方法
  18. ubuntu设置共享文件夹成功后却不显示找不到
  19. 28.EOS的共识机制与区块生成
  20. win7的远程桌面连接在哪

热门文章

  1. python加载项向导_什么是 Python 加载项?
  2. oracle9i用expdp导出全库,Linux下Oracle 11g数据库全库自动备份(EXPDP)
  3. C语言 | 基于MPU605(六轴传感器)的I2C实现LCD1602显示(代码类)
  4. html预览不出效果是怎么回事,为何HTML文件直接双击打不开 要用浏览器才能打开 之前双击还能打开显示效果的...
  5. 如何用SendMessage模拟某一按钮的点击事件
  6. java正则表示过滤汉字,Java正则表达式过滤汉字
  7. python中怎么比较两个列表的大小_Python:找到两个列表中存在的给定长度的公共子列表...
  8. C语言实现离散余弦变换(DCT)并用MATLAB和Python验证
  9. 为什么读博士的人越来越多?博士毕业难度不是越来越大吗?
  10. 【NLP】好资源!近 20 万本 txt 书籍的语料库,可用于 GPT 模型训练和语义分析...