Farrow结构的三阶拉格朗日插值matlab及FPGA实现

说明:本文为学习笔记,错误不可避免,全当交流。

以单频点信号为例,说明三阶拉格朗日插值的实现方法。

实现结构

假设输入序列为:X(n)=[…,x(-1),x(0),x(1),x(2)]

以一个x(1)…x(10)的序列为例,说明x的计算与插值过程。

X的计算如图所示,计算出x按照上述结构即可实现插值。

matlab实现

% farrow结构三阶拉格朗日插值的算法
%  y(k)=((c0*uk+c1)*uk+c2)*uk+c3;
% 其中uk为分数间隔,C为滤波结果,非常适合用fpga实现。
% 可用于任意倍率(插值或抽取)的采样率变换。
 close all; clear all;

fs = 1.5e3;
fc = 1e2;
t = 0:1/fs:1/fc;
x = cos(2*pi*fc*t);
% 系数
v0=[-1/6  1/2   -1/2  1/6];
v1=[1/2   -1    1/2    0 ];
v2=[-1/3  -1/2   1   -1/6];
v3=[0      1     0     0 ];

 
I=3; % 插值因子
D=2; % 抽取因子
step_factor=D/I;% 步进因子
k=1;%由第二个点开始,第一个点相等
lengthx=length(x);
xbuf=zeros(4,1);
ukbuf=zeros(1,round(length(x)*I/D));

yy4_1buf=zeros(1,round(I/D*lengthx+4));
yy4_2buf=zeros(1,round(I/D*lengthx+4));
yy4_3buf=zeros(1,round(I/D*lengthx+4));
yy4_4buf=zeros(1,round(I/D*lengthx+4));

yy3_1buf=zeros(1,round(I/D*lengthx+4));
yy3_2buf=zeros(1,round(I/D*lengthx+4));
yy3_3buf=zeros(1,round(I/D*lengthx+4));
pha=0;
x=[x 0 0];%补充0
for i=1:1:length(x)  %输入序列
    %--序列移位
    xbuf(4)=xbuf(3);
    xbuf(3)=xbuf(2);
    xbuf(2)=xbuf(1);
    xbuf(1)=x(i);
    
    %--滤波
    c0=xbuf(1)*v0(1)+xbuf(2)*v0(2)+xbuf(3)*v0(3)+xbuf(4)*v0(4);
    c1=xbuf(1)*v1(1)+xbuf(2)*v1(2)+xbuf(3)*v1(3)+xbuf(4)*v1(4);
    c2=xbuf(1)*v2(1)+xbuf(2)*v2(2)+xbuf(3)*v2(3)+xbuf(4)*v2(4);
    c3=xbuf(1)*v3(1)+xbuf(2)*v3(2)+xbuf(3)*v3(3)+xbuf(4)*v3(4);
    %起始点重合
    if(i==2)   
        y(1)=x(1);
    end
    %进去两个数据后开始插值第一个点
    if(i>2)
    pha = pha + 1;
    while pha >= step_factor
            
            pha = pha - step_factor; % 更新输出采样点后的相位
            uk =pha ;
        ukbuf(k)=uk;

        yy4_1=(c0*uk);%1
        yy4_1buf(k)=yy4_1;
        yy4_2=(yy4_1);
        yy4_2buf(k)=yy4_2;
        yy4_3=(yy4_2+c1);%2
        yy4_3buf(k)=yy4_3;
        yy4_4=(yy4_3);
        yy4_4buf(k)=yy4_4;
        yy4=yy4_4;
        

        yy3_1=(yy4*uk);%3
        yy3_1buf(k)=yy3_1;
        yy3_2=(yy3_1);
        yy3_2buf(k)=yy3_2;
        yy3_3=(yy3_2+c2);%4
        yy3_3buf(k)=yy3_3;
        yy3_4=(yy3_3);
        yy3=yy3_4;
        
        yy2=((yy3*uk+c3));%5
        k = k + 1; % 更新输出索引
        y(k)=yy2;
        m=y(k);
        
        
    end
    end
end


y=y(1:k-1);
t1=(0:length(y)-1)/(fs*I/D);
t = 0:1/fs:(1/fs)*17;
plot(t,x,'--*',t1,y,'--o');


figure(2);
subplot(211);%(x=行,列,计数)
NFFT=length(x);
FS=48*10^3;
signal_I_window =x'.*hamming(NFFT);
signal_I_window_FFT = fft(signal_I_window,NFFT)/NFFT;
plot((-0.5:1/NFFT:0.5-1/NFFT)*(FS),20*log10(fftshift(abs(signal_I_window_FFT(1:NFFT)))));
title('ContData  ');

subplot(212);%(x=行,列,计数)
NFFT=length(y);
FS=48*10^3*I/D;
signal_I_window =y'.*hamming(NFFT);
signal_I_window_FFT = fft(signal_I_window,NFFT)/NFFT;
plot((-0.5:1/NFFT:0.5-1/NFFT)*(FS),20*log10(fftshift(abs(signal_I_window_FFT(1:NFFT)))));
title('ContData  ');

执行结果

FPGA实现

实现结构与matlab相同,fir_core实现滤波器,mult_parallel实现uk的乘加。

C0滤波器的实现

`timescale 1ns / 1ps

//

// Company:

// Engineer:

//

// Create Date: 2023/06/25 08:45:58

// Design Name:

// Module Name: fir4_core

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//


 

module fir4_core#(

parameter                   WIDTH   = 16

)(

input i_sys_clk,

input i_reset_h,

input       [2*WIDTH-1:0]   din,//sfix16_en13  IQ·

output      [2*WIDTH-1:0]   dout


 

    );

   


 

wire        [15:0]              Fn_mem      [3 : 0];//sfix16_14

// assign       Fn_mem[0]           =   16'H1555;

// assign       Fn_mem[1]           =   16'HC000;

// assign       Fn_mem[2]           =   16'H4000;

// assign       Fn_mem[3]           =   16'HEAAB;

assign      Fn_mem[0]           =   16'HEAAB;

assign      Fn_mem[1]           =   16'H4000;

assign      Fn_mem[2]           =   16'HC000;

assign      Fn_mem[3]           =   16'H1555;

reg signed      [2*WIDTH-1:0]       Xn_mem          [3 : 0];

wire    signed      [31:0]              Mult_i_mem      [3 : 0];//sfix32_en27

wire    signed      [31:0]              Mult_q_mem      [3 : 0];//sfix16_en13 MULTI sfix16_en14

wire    signed  [33:0]          Sumi_mem1           ; //sfix34_en27


 

wire    signed  [33:0]          Sumq_mem1           ;

// assign       Xn_mem[0]           =   i_reset_h ? 32'd0 : din;

// genvar   n;

// generate

    // for (n=0; n < 6; n=n+1)begin: delayN

        // shift_ram_N

            // inst1_shift_ram_N(

            // .A                   (0          ),

            // .D                   ({Xn_mem[2],Xn_mem[1],Xn_mem[0]}),

            // .SCLR                (i_reset_h          ),

            // .CLK                (i_sys_clk            ),

            // .Q                   ({Xn_mem[3],Xn_mem[2],Xn_mem[1]})

            // );

always @(posedge i_sys_clk) begin

if(i_reset_h)begin

    Xn_mem[0] <= 0 ;

    Xn_mem[1] <= 0 ;

    Xn_mem[2] <= 0 ;

    Xn_mem[3] <= 0 ;

end

else begin

    Xn_mem[0] <= din;

    Xn_mem[1] <= Xn_mem[0] ;

    Xn_mem[2] <= Xn_mem[1] ;

    Xn_mem[3] <= Xn_mem[2] ;

end


 

end

    // end

// endgenerate

genvar  n1;

generate

    for (n1=0; n1 <= 3; n1=n1+1)begin: mult_gen

        mult_gen_16_16

            insti_mult_gen_16_16(

            .CLK                (i_sys_clk            ),

            .A                  (Xn_mem[n1][15:0]), //(15 DOWNTO 0)                                                                                                        

            .B                  (Fn_mem[n1]     ),  //(15 DOWNTO 0)                                                                                                        

            .P                  (Mult_i_mem[n1] )   //(31 DOWNTO 0)                                                                                                        

            );

        mult_gen_16_16

            instq_mult_gen_16_16(

            .CLK                (i_sys_clk            ),

            .A                  (Xn_mem[n1][31:16]),//(15 DOWNTO 0)                                                                                                        

            .B                  (Fn_mem[n1]     ),  //(15 DOWNTO 0)                                                                                                        

            .P                  (Mult_q_mem[n1] )   //(31 DOWNTO 0)                                                                                                        

            );

    end

endgenerate

wire    j1;

assign   j1=0;

        Sum_4Data#(

            .WIDTH              (32                 )

            )

            insti_Sum_4Data(

            .clk                (i_sys_clk                  ),

            .rst                (i_reset_h                  ),

            .din_1              (Mult_i_mem[0]  ),//32bit

            .din_2              (Mult_i_mem[0+1]    ),

            .din_3              (Mult_i_mem[0+2]    ),

            .din_4              (Mult_i_mem[0+3]    ),

            .dout               (Sumi_mem1      ) //34bit

        );

        Sum_4Data#(

            .WIDTH              (32                 )

            )

            instq_Sum_4Data(

            .clk                (i_sys_clk                  ),

            .rst                (i_reset_h                  ),

            .din_1              (Mult_q_mem[0]  ),//32bit

            .din_2              (Mult_q_mem[0+1]    ),

            .din_3              (Mult_q_mem[0+2]    ),

            .din_4              (Mult_q_mem[0+3]    ),

            .dout               (Sumq_mem1      ) //34bit

        );

       

assign      dout[15:0]          =   Sumi_mem1[30 :15];  //sfix16_en13

assign      dout[31:16]         =   Sumq_mem1[30: 15];  

endmodule

mult_parallel模块的实现

`timescale 1ns / 1ps

//

// Company:

// Engineer:

//

// Create Date: 2023/06/26 15:17:47

// Design Name:

// Module Name: mult_parallel

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//


 

module mult_parallel(

input i_sys_clk,

input i_reset_h,

input signed [15:0]  i_fir_c0,

input signed [15:0]  i_fir_c1,

input signed [15:0]  i_fir_c2,

input signed [15:0]  i_fir_c3,

input signed [15:0]  i_uk    ,

output signed [15:0] o_mult_parallel,

output               o_uk_valid      

    );

wire signed [31 : 0] w_mult_P_c0;

wire signed [15 : 0] w_mult_P16_c0;

wire signed [31 : 0] w_mult_P_c1;

wire signed [15 : 0] w_mult_P16_c1;

wire signed [31 : 0] w_mult_P_c2;

wire signed [15 : 0] w_mult_P16_c2;

wire signed [16 : 0] r_add_y1;

wire signed [16 : 0] r_add_y2;

wire signed [16 : 0] r_add_y3;


 

wire signed [15:0]  r_fir_c1_d4;

wire signed [15:0]  r_fir_c2_d9;

wire signed [15:0]  r_fir_c3_d14;

wire signed [15:0]  r_uk_d5;

wire signed [15:0]  r_uk_d10;

assign    w_mult_P16_c0 = w_mult_P_c0[29:14];

assign    w_mult_P16_c1 = w_mult_P_c1[29:14];

assign    w_mult_P16_c2 = w_mult_P_c2[29:14];

c_shift_ram_0 c_shift_ram_c0_inst (

  .A   (  6'd2              ),      // input wire [5 : 0] A

  .D   (  i_fir_c1       ),      // input wire [15 : 0] D

  .CLK (  i_sys_clk    ),      // input wire CLK

  .CE  (  1'b1 ),    // input wire CE

  .Q   (  r_fir_c1_d4  )       // output wire [15 : 0] Q

);

c_shift_ram_0 c_shift_ram_uk_c0_inst (

  .A   (  6'd3              ),      // input wire [5 : 0] A

  .D   (  i_uk       ),      // input wire [15 : 0] D

  .CLK (  i_sys_clk    ),      // input wire CLK

  .CE  (  1'b1 ),    // input wire CE

  .Q   (  r_uk_d5  )       // output wire [15 : 0] Q

);

c_shift_ram_0 c_shift_ram_c1_inst (

  .A   (  6'd7              ),      // input wire [5 : 0] A

  .D   (  i_fir_c2       ),      // input wire [15 : 0] D

  .CLK (  i_sys_clk    ),      // input wire CLK

  .CE  (  1'b1 ),    // input wire CE

  .Q   (  r_fir_c2_d9  )       // output wire [15 : 0] Q

);

c_shift_ram_0 c_shift_ram_uk_c1_inst (

  .A   (  6'd8              ),      // input wire [5 : 0] A

  .D   (  i_uk       ),      // input wire [15 : 0] D

  .CLK (  i_sys_clk    ),      // input wire CLK

  .CE  (  1'b1 ),    // input wire CE

  .Q   (  r_uk_d10  )       // output wire [15 : 0] Q

);

c_shift_ram_0 c_shift_ram_c2_inst (

  .A   (  6'd12              ),      // input wire [5 : 0] A

  .D   (  i_fir_c3       ),      // input wire [15 : 0] D

  .CLK (  i_sys_clk    ),      // input wire CLK

  .CE  (  1'b1 ),    // input wire CE

  .Q   (  r_fir_c3_d14  )       // output wire [15 : 0] Q

);

// always @(posedge i_sys_clk)

// begin

    // r_fir_c1_d1 <= i_fir_c1   ;

    // r_fir_c1_d2 <= r_fir_c1_d1;

        // r_fir_c1_d3 <= r_fir_c1_d2;

        // r_fir_c1_d4 <= r_fir_c1_d3;

                 

// end

//-----------c0

mult_gen_16_16 mult_gen_c0_inst (

  .CLK(  i_sys_clk      ),  // input wire CLK

  .A  (  i_uk           ),      // input wire [15 : 0] A

  .B  (  i_fir_c0       ),      // input wire [15 : 0] B

  .P  (  w_mult_P_c0    )      // output wire [31 : 0] P

);

c_addsub_16_16 c_addsub_16_16_c0 (

  .A    (  w_mult_P_c0[29:14]    ),      // input wire [15 : 0] A

  .B    (  r_fir_c1_d4    ),      // input wire [15 : 0] B

  .CLK  (  i_sys_clk   ),  // input wire CLK

  .CE   (  1'b1        ),    // input wire CE

  .S    (  r_add_y1    )      // output wire [16 : 0] S

);

//----------c1

mult_gen_16_16 mult_gen_c1_inst (

  .CLK(  i_sys_clk           ),  // input wire CLK

  .A  (  r_uk_d5         ),      // input wire [15 : 0] A

  .B  (  r_add_y1[15:0]      ),      // input wire [15 : 0] B

  .P  (  w_mult_P_c1         )      // output wire [31 : 0] P

);

c_addsub_16_16 c_addsub_16_16_c1 (

  .A    (  w_mult_P_c1[29:14]        ),      // input wire [15 : 0] A

  .B    (  r_fir_c2_d9   ),      // input wire [15 : 0] B

  .CLK  (  i_sys_clk   ),  // input wire CLK

  .CE   (  1'b1        ),    // input wire CE

  .S    (  r_add_y2    )      // output wire [16 : 0] S

);

mult_gen_16_16 mult_gen_c2_inst (

  .CLK(  i_sys_clk  ),  // input wire CLK

  .A  (  r_uk_d10    ),      // input wire [15 : 0] A

  .B  (  r_add_y2[15:0]    ),      // input wire [15 : 0] B

  .P  (  w_mult_P_c2    )      // output wire [31 : 0] P

);

c_addsub_16_16 c_addsub_16_16_c2 (

  .A    (  w_mult_P_c2[29:14]    ),      // input wire [15 : 0] A

  .B    (  r_fir_c3_d14    ),      // input wire [15 : 0] B

  .CLK  (  i_sys_clk   ),  // input wire CLK

  .CE   (  1'b1        ),    // input wire CE

  .S    (  r_add_y3    )      // output wire [16 : 0] S

);

assign   o_mult_parallel = r_add_y3[16:1];

endmodule

  • 36
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 拉格朗日插值法是一种常用的插值方法,在信号处理中常用于数据重构和信号平滑。Farrow结构是一种数字滤波器结构,它可以通过使用多项式函数插值的方法来实现高质量的滤波器系数设计。 在计算Farrow结构滤波器系数时,需要使用拉格朗日插值法来生成插值多项式函数。这个过程中,需要先获取滤波器中心点的位置以及相邻点的有限数据,然后使用拉格朗日插值公式计算插值多项式函数系数。当多项式函数系数计算完成后,这些系数可以用于Farrow结构中的插值单元。 在使用Farrow结构进行滤波时,信号会首先经过一个插值操作,使得信号的采样率变得更高,然后再通过一个滤波器进行滤波。由于Farrow结构的多项式插值算法是高精度的,因此可以得到非常高质量的滤波效果,同时还可以提高滤波器的仿真速度。 总的来说,拉格朗日插值法和Farrow结构是数字信号处理中非常有用的工具,可以实现高精度的数据重构和滤波器设计。这些工具广泛地应用于音频信号处理、视频信号处理和其他数字信号处理领域。 ### 回答2: 拉格朗日插值Farrow结构滤波器系数是指使用拉格朗日插值对信号进行插值,并通过Farrow结构计算滤波器系数的一种算法。具体而言,拉格朗日插值是利用向量函数的特点,在指定点上用非经典的多项式来逼近一个函数,以达到插值或者逼近的目的。而Farrow结构是将插值拆分为多个小的插值块,并通过调整块间系数来获得整体的插值结果。 在拉格朗日插值Farrow结构滤波器系数的计算中,首先需要确定插值块的大小和插值阶数,并通过拉格朗日插值来计算每个块中的系数。接着,根据Farrow结构,将系数拆分为小的块,并通过调整块间系数来得到整体的滤波器系数。根据Farrow结构,每个插值块可以使用CIC(积分累加器器)来实现拉格朗日插值Farrow结构滤波器系数的优点在于其具有高阶的插值精度和低延迟的特点,并可以根据需求进行调整。但是,其缺点在于需要较高的计算复杂度和存储空间,需要根据实际需求进行平衡。 ### 回答3: 拉格朗日插值Farrow结构滤波器的系数计算是指根据输入信号和滤波器参数计算出滤波器的系数,从而实现滤波器的设计。拉格朗日插值Farrow结构是一种高精度、高效的数字滤波器结构,可以用于信号重构、滤波和降噪等应用。 拉格朗日插值Farrow结构的原理是利用拉格朗日插值多项式来估计输入信号的值,然后将多个拉格朗日插值多项式级联起来构成全局滤波器。在每个级联的多项式中,滤波器系数由拉格朗日插值公式计算得到,根据输入信号和输出信号之间的误差来优化滤波器的参数。 计算拉格朗日插值Farrow结构滤波器的系数主要有以下几个步骤:首先根据输入信号的采样率和目标采样率计算出采样率的比值,然后根据比值和滤波器阶数计算出每个插值段的插值次数和系数,最后利用拉格朗日插值公式将各段系数连接起来得到全局滤波器系数。 与传统的数字滤波器相比,拉格朗日插值Farrow结构滤波器的计算效率更高,滤波器响应更加平滑,可以提高信号重构和降噪的效果。因此,它被广泛应用于音频信号处理、图像处理、通信系统等领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值