1. First use matlab to generate 16-bit binary sinusoidal signal data and store it in rom:
%Set parameters fi=5000; L=1024; N=16; fs=20000; % generate signal 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\\ '); end fprintf(fid,';'); fclose(fid);
2. Store data in rom ip core
For the application of ROM core, see: https://blog.csdn.net/qq_39005414/article/details/109552835
3. FFT ip core configuration
`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 & amp; & amp; 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 simulation
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 //The file is placed in the "project directory\simulation\modelsim" path 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 //The file is placed in the "project directory\simulation\modelsim" path file_out1 = $fopen("out1.txt"); if(!file_out) begin $display("could not open file!"); $finish; end end always @(posedge clk)begin if((a>0) & amp; & amp; (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
Simulation results
4. Compare the result output with the result after 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)))