日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

FIR调用DSP48E_05

發布時間:2025/3/8 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。