fpga实现距离压缩

本文介绍了如何使用Verilog实现对线性调频信号进行距离压缩,包括补零模块、FFT、复数乘法器以及IFFT的详细设计,以及Matlab仿真的应用,重点讨论了时序和精度问题。FFT和IFFT操作耗时300us,结果显示存在精度损失。
摘要由CSDN通过智能技术生成

1 、要求

对线性调频信号,采样率100M,带宽80M,脉宽10us,进行距离压缩,精度为16

2、Matlab仿真

3、verilog实现

3.1 补零模块

module zero_fill #(
    parameter WIDTH = 'd16,
    parameter LENGTH='d2048
)(
    input clk,
    input rstn,
    input signed [WIDTH-1:0] x_re,
    input signed [WIDTH-1:0] x_im,
    output signed [WIDTH-1:0] y_re,
    output signed [WIDTH-1:0] y_im,
    output                    working
    );
    reg signed [WIDTH-1:0] temp_re;
    reg signed [WIDTH-1:0] temp_im;
    reg [11:0] cnt;
    reg ena;
    reg flag;
always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        temp_re<='d0;
        temp_im<='d0;
    end
    else if(ena==1'b1)begin
        if(flag==1)begin
            temp_im<=0;
            temp_re<=0;
        end
        else begin
            temp_im<=x_im;
            temp_re<=x_re;
        end
    end
    else begin
        temp_re<='d0;
        temp_im<='d0;
    end
end
always @(posedge clk,negedge rstn) begin//2048计数器
    if(!rstn)begin
        cnt<='d0;
    end
    else if(cnt<(LENGTH+1))begin//cnt范围0~2049
        cnt<=cnt+1'b1;
    end
    else begin
        cnt<=LENGTH+1;
    end
end
always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        ena<=1'b0;
    end
    else if(cnt<(LENGTH+1))begin
        ena<=1'b1;
    end
    else if(cnt==(LENGTH+1))begin
        ena<=1'b0;
    end
end

always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        flag<='d0;
    end
    else if(cnt==1000)begin
        flag<=1'b1;
    end
    else if(cnt==(LENGTH+1))begin
        flag<=1'b0;
    end
end
assign y_im=temp_im;
assign y_re=temp_re;

assign working=ena;
endmodule

3.2 fft模块

module func_fft(
    input                           aclk,
    input                           aresetn,
    input   wire    [23 : 0]         s_axis_config_tdata,
    input   wire                    s_axis_config_tvalid,
    output  wire                    s_axis_config_tready,
    input   wire    [31 : 0]        s_axis_data_tdata,
    input   wire                    s_axis_data_tvalid,
    output  wire                    s_axis_data_tready,
    input   wire                    s_axis_data_tlast,
    output  wire    [31 : 0]        m_axis_data_tdata,
    output  wire    [23 : 0]        m_axis_data_tuser,
    output  wire                    m_axis_data_tvalid,
    input   wire                    m_axis_data_tready,
    output  wire                    m_axis_data_tlast,
    input   wire                    m_axis_status_tready,
    output  wire                    event_fft_overflow

    );
    wire                            event_frame_started;
    wire                            event_tlast_unexpected;
    wire                            event_tlast_missing;
    wire                            event_status_channel_halt;
    wire                            event_data_in_channel_halt;
    wire                            event_data_out_channel_halt;
    wire [7 : 0]                    m_axis_status_tdata;
fft fft2048 (
  .aclk(aclk),                                                // input wire aclk
  .aresetn(aresetn),                                          // input wire aresetn
  .s_axis_config_tdata(s_axis_config_tdata),                  // input wire [23 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(s_axis_config_tvalid),                // input wire s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready),                // output wire s_axis_config_tready
  .s_axis_data_tdata(s_axis_data_tdata),                      // input wire [31 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid),                    // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready),                    // output wire s_axis_data_tready
  .s_axis_data_tlast(s_axis_data_tlast),                      // input wire s_axis_data_tlast
  .m_axis_data_tdata(m_axis_data_tdata),                      // output wire [31 : 0] m_axis_data_tdata
  .m_axis_data_tuser(m_axis_data_tuser),                      // output wire [23 : 0] m_axis_data_tuser
  .m_axis_data_tvalid(m_axis_data_tvalid),                    // output wire m_axis_data_tvalid
  .m_axis_data_tready(m_axis_data_tready),                    // input wire m_axis_data_tready
  .m_axis_data_tlast(m_axis_data_tlast),                      // output wire m_axis_data_tlast
  .m_axis_status_tdata(m_axis_status_tdata),                  // output wire [7 : 0] m_axis_status_tdata
  .m_axis_status_tvalid(m_axis_status_tvalid),                // output wire m_axis_status_tvalid
  .m_axis_status_tready(m_axis_status_tready),                // input wire m_axis_status_tready
  .event_frame_started(event_frame_started),                  // output wire event_frame_started
  .event_tlast_unexpected(event_tlast_unexpected),            // output wire event_tlast_unexpected
  .event_tlast_missing(event_tlast_missing),                  // output wire event_tlast_missing
  .event_fft_overflow(event_fft_overflow),                    // output wire event_fft_overflow
  .event_status_channel_halt(event_status_channel_halt),      // output wire event_status_channel_halt
  .event_data_in_channel_halt(event_data_in_channel_halt),    // output wire event_data_in_channel_halt
  .event_data_out_channel_halt(event_data_out_channel_halt)  // output wire event_data_out_channel_halt
);
endmodule

3.3 复数乘法器模块

module multi #(
    parameter WIDTH = 'd32,
    parameter LENGTH = 'd2048
)(
    input                       aclk,
    input                       rstn,
    input                       en,
    input   [31:0]              s_axis_a_tdata,//[31:16]imag   [15:0]real
    input   [31:0]              s_axis_b_tdata,
    output  [79 : 0]            m_axis_dout_tdata//[72:40]imag  [32:0]real
    );
wire m_axis_dout_tvalid;
com_mul multiplier (
  .aclk(aclk),                              // input wire aclk
  .s_axis_a_tvalid(en),                     // input wire s_axis_a_tvalid
  .s_axis_a_tdata(s_axis_a_tdata),          // input wire [31 : 0] s_axis_a_tdata
  .s_axis_b_tvalid(en),                     // input wire s_axis_b_tvalid
  .s_axis_b_tdata(s_axis_b_tdata),          // input wire [31 : 0] s_axis_b_tdata
  .m_axis_dout_tvalid(m_axis_dout_tvalid),  // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata(m_axis_dout_tdata)    // output wire [79 : 0] m_axis_dout_tdata
);
endmodule

3.4 ifft模块

module func_ifft(
    input                           aclk,
    input                           aresetn,
    input   wire    [23 : 0]         s_axis_config_tdata,
    input   wire                    s_axis_config_tvalid,
    output  wire                    s_axis_config_tready,
    input   wire    [79 : 0]        s_axis_data_tdata,
    input   wire                    s_axis_data_tvalid,
    output  wire                    s_axis_data_tready,
    input   wire                    s_axis_data_tlast,
    output  wire    [79 : 0]        m_axis_data_tdata,
    output  wire    [23 : 0]        m_axis_data_tuser,
    output  wire                    m_axis_data_tvalid,
    input   wire                    m_axis_data_tready,
    output  wire                    m_axis_data_tlast,
    output  wire                    event_fft_overflow,
    input   wire                    m_axis_status_tready

    );
    wire                            event_frame_started;
    wire                            event_tlast_unexpected;
    wire                            event_tlast_missing;
    wire                            event_status_channel_halt;
    wire                            event_data_in_channel_halt;
    wire                            event_data_out_channel_halt;
    wire [7 : 0]                    m_axis_status_tdata;
ifft ifft2048 (
  .aclk(aclk),                                                // input wire aclk
  .aresetn(aresetn),                                          // input wire aresetn
  .s_axis_config_tdata(s_axis_config_tdata),                  // input wire [23 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(s_axis_config_tvalid),                // input wire s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready),                // output wire s_axis_config_tready
  .s_axis_data_tdata(s_axis_data_tdata),                      // input wire [79 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid),                    // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready),                    // output wire s_axis_data_tready
  .s_axis_data_tlast(s_axis_data_tlast),                      // input wire s_axis_data_tlast
  .m_axis_data_tdata(m_axis_data_tdata),                      // output wire [79 : 0] m_axis_data_tdata
  .m_axis_data_tuser(m_axis_data_tuser),                      // output wire [23 : 0] m_axis_data_tuser
  .m_axis_data_tvalid(m_axis_data_tvalid),                    // output wire m_axis_data_tvalid
  .m_axis_data_tready(m_axis_data_tready),                    // input wire m_axis_data_tready
  .m_axis_data_tlast(m_axis_data_tlast),                      // output wire m_axis_data_tlast
  .m_axis_status_tdata(m_axis_status_tdata),                  // output wire [7 : 0] m_axis_status_tdata
  .m_axis_status_tvalid(m_axis_status_tvalid),                // output wire m_axis_status_tvalid
  .m_axis_status_tready(m_axis_status_tready),                // input wire m_axis_status_tready
  .event_frame_started(event_frame_started),                  // output wire event_frame_started
  .event_tlast_unexpected(event_tlast_unexpected),            // output wire event_tlast_unexpected
  .event_tlast_missing(event_tlast_missing),                  // output wire event_tlast_missing
  .event_fft_overflow(event_fft_overflow),                    // output wire event_fft_overflow
  .event_status_channel_halt(event_status_channel_halt),      // output wire event_status_channel_halt
  .event_data_in_channel_halt(event_data_in_channel_halt),    // output wire event_data_in_channel_halt
  .event_data_out_channel_halt(event_data_out_channel_halt)  // output wire event_data_out_channel_halt
);
endmodule

 3.5 tb_top

module tb_top(

    );
    parameter LENGTH='d2048;
    parameter WIDTH='d16;
    parameter PERIORD = 'd10;
    parameter MUL_WIDTH='d32;
    reg clk;
    reg rstn;
    reg aresetn;
    reg [WIDTH-1:0] mem0_re[999:0];
    reg [WIDTH-1:0] mem0_im[999:0];

always #(PERIORD/2) clk=~clk;
/例化补零模块//
initial begin
    $readmemb("D:/vivado_projects/pra3_3/pra3_3.srcs/sources_1/new/input_re.txt",mem0_re);
    $readmemb("D:/vivado_projects/pra3_3/pra3_3.srcs/sources_1/new/input_im.txt",mem0_im);
end
integer i,j,k;
always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        i=-1;
    end
    else begin
        i=i+1;
    end
end
wire [WIDTH-1:0] x_im0;
wire [WIDTH-1:0] x_re0;
wire working;
zero_fill  #(
    .WIDTH(WIDTH),
    .LENGTH(LENGTH)
)u_zero_fill(
    .clk(clk),
    .rstn(rstn),
    .x_re(mem0_re[i]),
    .x_im(mem0_im[i]),
    .y_re(x_re0),
    .y_im(x_im0),
    .working(working)
);
//例化匹配滤波器fft

reg     [23 : 0]         s_axis_config_tdata_h;
reg                     s_axis_config_tvalid_h;
wire                    s_axis_config_tready_h;
reg     [31 : 0]        s_axis_data_tdata_h;
reg                     s_axis_data_tvalid_h;
wire                    s_axis_data_tready_h;
reg                     s_axis_data_tlast_h;
wire    [31 : 0]        m_axis_data_tdata_h;
wire    [23 : 0]        m_axis_data_tuser_h;
wire                    m_axis_data_tvalid_h;
reg                     m_axis_data_tready_h;
wire                    m_axis_data_tlast_h;
reg                     m_axis_status_tready_h;
wire                    event_fft_overflow_h;
//wire [31:0] temp_data={x_im0,x_re0};
reg [31:0]  temp_data;
//因为延迟,从补零模块输出需要延迟一个周期
always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        temp_data<=0;
    end
    else begin
        temp_data<={x_im0,x_re0};
    end
end


//assign s_axis_data_tdata_h={x_re0,x_im0};
func_fft fft_h(
    .aclk(clk),
    .aresetn(aresetn),
    .s_axis_config_tdata(s_axis_config_tdata_h),
    .s_axis_config_tvalid(s_axis_config_tvalid_h),
    .s_axis_config_tready(s_axis_config_tready_h),
    .s_axis_data_tdata(s_axis_data_tdata_h),
    .s_axis_data_tvalid(s_axis_data_tvalid_h),
    .s_axis_data_tready(s_axis_data_tready_h),
    .s_axis_data_tlast(s_axis_data_tlast_h),
    .m_axis_data_tdata(m_axis_data_tdata_h),
    .m_axis_data_tuser(m_axis_data_tuser_h),
    .m_axis_data_tvalid(m_axis_data_tvalid_h),
    .m_axis_data_tready(m_axis_data_tready_h),
    .m_axis_data_tlast(m_axis_data_tlast_h),
    .m_axis_status_tready(m_axis_status_tready_h),
    .event_fft_overflow(event_fft_overflow_h)
);


//原信号因fftip核特性,故需要将其虚部取负
wire signed[15:0]fft_im=m_axis_data_tdata_h[31:16];
wire signed[15:0]fft_re=m_axis_data_tdata_h[15:0];
wire signed[15:0]neg_o_x_im=0-fft_im;
integer fft_hand_re;
integer fft_hand_im;
initial begin
    fft_hand_re=$fopen("D:/matlabfiles/fpga/fft_out_re.txt");
    fft_hand_im=$fopen("D:/matlabfiles/fpga/fft_out_im.txt");
end
always @(posedge clk) begin
    if(m_axis_data_tvalid_h==1)begin
        $fdisplay(fft_hand_re,"%b",fft_re);
        $fdisplay(fft_hand_im,"%b",fft_im);
    end
    if(m_axis_data_tlast_h==1)begin
        $fclose(fft_hand_re);
        $fclose(fft_hand_im);
    end
end


//例化复数乘法器
wire en_mul=m_axis_data_tvalid_h;
wire [MUL_WIDTH-1:0] s_axis_a_tdata_o={neg_o_x_im,fft_re};
wire [MUL_WIDTH-1:0] s_axis_b_tdata_h={fft_im,fft_re};
wire [79:0] m_axis_dout_tdata;
multi #(
    .WIDTH(MUL_WIDTH),
    .LENGTH(LENGTH)
)u_mul(
    .aclk(clk),
    .rstn(rstn),
    .en(en_mul),
    .s_axis_a_tdata(s_axis_a_tdata_o),
    .s_axis_b_tdata(s_axis_b_tdata_h),
    .m_axis_dout_tdata(m_axis_dout_tdata)
);
//例化ifft
reg     [23 : 0]         s_axis_config_tdata_i;
reg                    s_axis_config_tvalid_i;
wire                     s_axis_config_tready_i;
wire     [79 : 0]       s_axis_data_tdata_i;
wire                     s_axis_data_tvalid_i;
wire                    s_axis_data_tready_i;
reg                     s_axis_data_tlast_i;
wire    [79 : 0]        m_axis_data_tdata_i;
wire    [23 : 0]        m_axis_data_tuser_i;
wire                    m_axis_data_tvalid_i;
reg                     m_axis_data_tready_i;
wire                    m_axis_data_tlast_i;
reg                     m_axis_status_tready_i;
wire                    event_fft_overflow_i;
func_ifft u_ifft (
  .aclk(clk),                                                   // input wire aclk
  .aresetn(aresetn),                                            // input wire aresetn
  .s_axis_config_tdata(s_axis_config_tdata_i),                  // input wire [7 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(s_axis_config_tvalid_i),                // input wire s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready_i),                // output wire s_axis_config_tready
  .s_axis_data_tdata(s_axis_data_tdata_i),                      // input wire [79 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid_i),                    // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready_i),                    // output wire s_axis_data_tready
  .s_axis_data_tlast(s_axis_data_tlast_i),                      // input wire s_axis_data_tlast
  .m_axis_data_tdata(m_axis_data_tdata_i),                      // output wire [95 : 0] m_axis_data_tdata
  .m_axis_data_tuser(m_axis_data_tuser_i),                      // output wire [15 : 0] m_axis_data_tuser
  .m_axis_data_tvalid(m_axis_data_tvalid_i),                    // output wire m_axis_data_tvalid
  .m_axis_data_tready(m_axis_data_tready_i),                    // input wire m_axis_data_tready
  .m_axis_data_tlast(m_axis_data_tlast_i),                      // output wire m_axis_data_tlast
  .m_axis_status_tready(m_axis_status_tready_i),
  .event_fft_overflow(event_fft_overflow_i)
);
initial begin
    clk=0;
    aresetn=0;
    rstn=0;
    s_axis_config_tdata_h=8'b0;
    s_axis_config_tdata_i=8'b0;

    s_axis_config_tvalid_h=0;
    s_axis_config_tvalid_i=0;

    s_axis_data_tvalid_h=0;
    s_axis_data_tdata_h=0;
    s_axis_data_tlast_h=0;

    m_axis_data_tready_h=0;
    m_axis_data_tready_i=0;

    i=0;
    j=0;
    k=0;
    #40;
    aresetn=1;
    rstn=1;
    m_axis_data_tready_h=1;
    m_axis_data_tready_i=1;

    s_axis_config_tvalid_h=1;
    s_axis_config_tvalid_i=1;

    
    s_axis_config_tdata_h=23'b00_0000_0010_0010_0000_0000_1;
    s_axis_config_tdata_i=23'b00_0000_0010_0010_0000_1000_0;


    m_axis_status_tready_i=1;
    m_axis_status_tready_h=1;

    //#80000;
    //s_axis_config_tvalid_h=0;
    //aresetn=0;
    
    

end
匹配滤波器时序
//working需要打两拍
reg working_delay1;
reg working_delay2;
always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        working_delay1<=0;
        working_delay2<=0;
    end
    else begin
        working_delay1<=working;
        working_delay2<=working_delay1;
    end
end
always @(posedge clk,negedge rstn) begin
    if((s_axis_data_tready_h==1)&&(working_delay2))begin

        s_axis_data_tvalid_h<=1;
        s_axis_data_tdata_h<=temp_data;
        s_axis_data_tlast_h<=0;
        
    end
    else begin

        s_axis_data_tvalid_h<=0;
        s_axis_data_tlast_h<=1;
    end
end


ifft时序
reg en_ifft;
always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        en_ifft<=0;
    end
    else begin
        en_ifft<=en_mul;
    end
    
end
assign s_axis_data_tvalid_i=en_ifft;
always @(posedge clk,negedge rstn) begin
    if(s_axis_data_tready_i&&m_axis_data_tvalid_h)begin
        j=j+1;
        s_axis_data_tlast_i<=0;;
        if(j==2047)begin
            s_axis_data_tlast_i<=1;
        end
    end
    else begin
        j=0;
        s_axis_data_tlast_i<=1;
    end
end

reg [79:0] a;
reg [79:0] b;
wire signed[33:0]temp_i1=m_axis_dout_tdata[72:40];
wire signed[33:0]temp_i2=m_axis_dout_tdata[32:0];


always @(posedge clk,negedge rstn) begin
    if(!rstn)begin
        a<=0;
        b<=0;
    end
    else begin

        a<={7'd0,temp_i1,7'd0,temp_i2};
        b<=a;
    end
end
assign s_axis_data_tdata_i=b;



/存储最终结果
wire signed[32:0] final_re;
wire signed[32:0] final_im;
assign final_re=m_axis_data_tdata_i[32:0];
assign final_im=m_axis_data_tdata_i[72:40];
integer handle_re;
integer handle_im;
initial begin
    handle_re=$fopen("D:/matlabfiles/fpga/output_re.txt");
    handle_im=$fopen("D:/matlabfiles/fpga/output_im.txt");
end
always @(posedge clk) begin
    if(m_axis_data_tvalid_i==1)begin
        $fdisplay(handle_re,"%b",final_re);
        $fdisplay(handle_im,"%b",final_im);
    end
    if(m_axis_data_tlast_i==1)begin
        $fclose(handle_re);
        $fclose(handle_im);
    end
end
endmodule

4、结果输出

仿真采用100MHz时钟,fft加ifft耗时约300us。仿真时将仿真时间设置为350us即可。

 

 上图为fft后输出存储结果,可见精度有损失,当然也跟我输出时候数据设置有些问题。

5、总结

对fft ip核 的一次使用练习,熟悉各个接口和时序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值