当前位置:   article > 正文

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

farrow插值

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

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

实现结构

假设输入序列为: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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/192948
推荐阅读
相关标签
  

闽ICP备14008679号