verilog FFT Vivado IP核实现

1、首先用matlab产生16bit二进制正弦信号数据,存入rom:

%设置参数
fi=5000;
L=1024;
N=16;
fs=20000;

%产生信号
t=0:1/fs:(L-1)/fs;
theta=rand()*2*pi;
si=sin(2*pi*fi*t+theta);

f_s=si/max(abs(si));
Q_s=round(f_s*(2^(N-1)-1));

fid=fopen('C:\Users\HLPC\Desktop\Sin.txt','w');
for k=1:length(Q_s)
    B_s=dec2bin(Q_s(k)+(Q_s(k)<0)*2^N,N);
    for j=1:N
        if B_s(j)=='1'
            tb=1;
        else
            tb=0;
        end
        fprintf(fid,'%d',tb);
    end
    fprintf(fid,'\r\n');
end
fprintf(fid,';');
fclose(fid);

2、将数据存入rom ip核中
rom核的应用见:https://blog.csdn.net/qq_39005414/article/details/109552835
在这里插入图片描述
3、FFT ip核配置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`timescale 1ns / 1ps
module rom_fft(
    input sys_clk_n,
    input sys_clk_p,
    input rst_n,
    output [9:0] a,
    output reg [15:0]data_i,
    output m_axis_data_tvalid,  
    output [63:0] data_o,
    output reg [26:0]fft_re,
    output reg [26:0]fft_im,
    output reg [54:0]fft_amp
    );
wire clk;    
wire [15:0]spo;
reg s_axis_config_tvalid;   
wire s_axis_config_tready; 
reg s_axis_data_tvalid;
reg s_axis_data_tlast;
wire m_axis_data_tlast;
wire s_axis_data_tready;
wire [63:0] m_axis_data_tdata;
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;
reg cnt_flag;
reg [10:0]cnt;
wire [53:0] xkre_square, xkim_square;
assign data_o =  m_axis_data_tdata;   
IBUFDS CLK(
    .I(sys_clk_n),
    .IB(sys_clk_p),
    .O(clk)   
);

xfft_0 your_instance_name (
  .aclk(clk),                                                // input wire aclk
  .aresetn(rst_n),
  .s_axis_config_tdata(8'd1),                  // input wire [15 : 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({16'd0,data_i}),                      // 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_tvalid(m_axis_data_tvalid),                    // output wire m_axis_data_tvalid
  .m_axis_data_tready(1'b1),                    // input wire m_axis_data_tready
  .m_axis_data_tlast(m_axis_data_tlast),                      // output wire m_axis_data_tlast
  .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_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
); 

reg [9:0] cnt1;
always @(posedge clk)begin
    if(~rst_n)
        cnt1 <= 1'b0;
    else if(cnt1 < 10'd200)
        cnt1 <= cnt1 + 1'b1;
end

always @(posedge clk)begin
    if(~rst_n)
        cnt_flag <= 1'b0;
    else if(s_axis_config_tvalid)
        cnt_flag <= 1'b1;
end

always @(posedge clk)begin
    if(~rst_n)
        s_axis_config_tvalid <= 1'b0;
    else if(cnt1 < 10'd200)
        s_axis_config_tvalid <= 1'b1;  
    else
        s_axis_config_tvalid <= 1'b0;  
end

always @(posedge clk)begin
    if(~rst_n)
        cnt <= 11'd0;
    else if(cnt_flag  )
        if(cnt <= 11'd1023)
            cnt <= 11'd1 + cnt;
        else
            cnt <= cnt;
    else
        cnt <= 11'd0;        
end

always @(posedge clk)begin
    if(~rst_n)
        s_axis_data_tvalid <= 1'b0;
    else if(cnt_flag && cnt <= 11'd1023)
        s_axis_data_tvalid <= 1'b1;
    else  
        s_axis_data_tvalid <= 1'b0;   
end

always @(posedge clk)begin
    if(~rst_n)
        s_axis_data_tlast <= 1'b0;
    else if(cnt == 11'd1023)
        s_axis_data_tlast <= 1'b1;
    else  
        s_axis_data_tlast <= 1'b0;   
end

always @(posedge clk)begin
    if(~rst_n)
        fft_im <= 27'd0;    
    else  
        fft_im <= data_o[58:32];   
end
always @(posedge clk)begin
    if(~rst_n)
        fft_re <= 27'd0;    
    else  
        fft_re <= data_o[26:0];   
end

mult_gen_0 your_instance_name3 (
  .CLK(clk),  // input wire CLK
  .A(fft_re),       // input wire [26 : 0] A
  .B(fft_re),       // input wire [26 : 0] B
  .P(xkre_square)  // output wire [53 : 0] P
);

mult_gen_0 your_instance_name4 (
  .CLK(clk),  // input wire CLK
  .A(fft_im),       // input wire [26 : 0] A
  .B(fft_im),       // input wire [26 : 0] B
  .P(xkim_square)  // output wire [53 : 0] P
);

always @(posedge clk)
   if(~rst_n)
      fft_amp <= 55'd0;
   else
      fft_amp <= xkre_square + xkim_square;

dist_mem_gen_0 your_instance_name1 (
  .a(a),                // input wire [9 : 0] a
  .clk(clk),            // input wire clk
  .qspo_rst(~rst_n),  // input wire qspo_rst
  .qspo(spo)          // output wire [15 : 0] qspo
);  

assign a = cnt;        
 always@(posedge clk or negedge rst_n)begin
    if(~rst_n )
        data_i <=  16'd0;
    else if(a <= 10'd1023)
        data_i <= spo; 
    end

endmodule

testbench仿真

module vtf_test(

    );
    
wire sys_clk_n;      
reg sys_clk_p; 
reg rst_n;
wire [15:0] data_i;
wire  [63:0] data_o;
wire  [26:0] fft_re;
wire  [26:0] fft_im;
wire  [54:0] fft_amp;
wire [9:0] a;
wire clk;
wire m_axis_data_tvalid;

rom_fft u_rom_fft(
    .sys_clk_n(sys_clk_n),
    .sys_clk_p(sys_clk_p),
    .rst_n(rst_n),
    .a(a),
    .data_i(data_i),
    .m_axis_data_tvalid(m_axis_data_tvalid),
   .data_o(data_o),
   .fft_re(fft_re),
   .fft_im(fft_im),
   .fft_amp(fft_amp)
    );
    
  
initial begin
    rst_n = 0;
    sys_clk_p = 0;
    #20;
    rst_n = 1;
    #2000000;
end

IBUFDS CLK(
    .I(sys_clk_n),
    .IB(sys_clk_p),
    .O(clk)   
);

integer file_out;
initial 
begin
   //文件放置在"工程目录\simulation\modelsim"路径下                                                  
	file_out = $fopen("out.txt");
	if(!file_out)
		begin
			$display("could not open file!");
			$finish;
		end
end
always @(posedge clk)begin    
    if(m_axis_data_tvalid)
	   $fdisplay(file_out,"%d",fft_amp);
end

integer file_out1;
initial 
begin
   //文件放置在"工程目录\simulation\modelsim"路径下                                                  
	file_out1 = $fopen("out1.txt");
	if(!file_out)
		begin
			$display("could not open file!");
			$finish;
		end
end
always @(posedge clk)begin
    if((a>0) && (a<10'd1023))
	   $fdisplay(file_out1,"%d",data_i);
end

always #5 sys_clk_p=~sys_clk_p;  
assign  sys_clk_n=~sys_clk_p; 

endmodule

仿真结果
在这里插入图片描述
4、将结果输出和matlab fft后的结果对比:

subplot(2,1,1)
cstr = textread('D:\fpga_test\rom_fft\rom_fft.sim\sim_1\behav\xsim\out.txt','%d');
plot(cstr)
subplot(2,1,2)
cstr1 = textread('C:\Users\HLPC\Desktop\Sin.txt','%d');
plot(abs(fft(cstr1)))

在这里插入图片描述

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值