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)))