环境
Vivado
Modelsim 仿真
层次结构

ROM matlab产生波形,保存到coe文件中,加载到rom中
dds 控制输入信号的频率
dds的输出信号给到fft IP核
仿真

左边为input,右边为output
输入信号的范围为0-255,包含直流分量,频率为单频
实现
HDL
顶层文件
module ip_fft(
input clk,
input rst
);
wire [7:0] Out;
wire [10:0] addr;
//=============================
wire [31:0] fft_s_axis_data_tdata;
reg fft_s_axis_data_tvalid;
wire fft_s_axis_data_tready;
reg fft_s_axis_data_tlast;
wire [63:0] m_axis_data_tdata;
wire [7:0] m_axis_data_tuser;
wire m_axis_data_tvalid;
wire m_axis_data_tlast;
wire m_axis_data_tready;
reg [7:0] counter;
reg fft_flag;
//
assign fft_s_axis_data_tdata = {24'b0, Out};
// assign fft_s_axis_data_tvalid = 1'b1;
// assign fft_s_axis_data_tlast = (addr==11'b1)?1'b1:1'b0;
assign m_axis_data_tready = 1'b1;
always @(posedge clk ) begin
if (!rst) begin
counter <= 8'b0;
end
else if(fft_s_axis_data_tready) begin
counter <= counter +1'b1;
end
end
always @(posedge clk ) begin
fft_s_axis_data_tvalid <= fft_s_axis_data_tvalid;
fft_s_axis_data_tlast <= 1'b0 ;
fft_flag <= fft_flag;
if (!rst) begin
fft_flag <= 1'b0;
fft_s_axis_data_tlast <= 1'b0;
fft_s_axis_data_tvalid <= 1'b0;
end
else if(fft_flag == 1'b0) begin
if (counter == 8'hff) begin
fft_flag <= 1'b1;
fft_s_axis_data_tvalid <= 1'b1;
end
end
else if(fft_flag == 1'b1) begin
if (counter == 8'hff) begin
fft_s_axis_data_tvalid <= 1'b0;
fft_s_axis_data_tlast <= 1'b1;
end
end
else begin
fft_s_axis_data_tvalid <= fft_s_axis_data_tvalid;
fft_s_axis_data_tlast <= fft_s_axis_data_tlast ;
end
end
// output
wire [24:0] realp;
wire [24:0] imagp;
wire [50:0] fft_abs;
assign realp = m_axis_data_tdata[56:32];
assign imagp = m_axis_data_tdata[24:0];
assign fft_abs = $signed(realp)* $signed(realp)+ $signed(imagp)* $signed(imagp);
xfft_0 u_xfft_0 (
.aclk (clk), // input wire aclk
.aresetn (rst), // input wire aresetn
.s_axis_config_tdata (8'b1), // input wire [7 : 0] s_axis_config_tdata
.s_axis_config_tvalid (1'b1), // input wire s_axis_config_tvalid
.s_axis_config_tready (), // output wire s_axis_config_tready
.s_axis_data_tdata (fft_s_axis_data_tdata), // input wire [xx : 0] s_axis_data_tdata
.s_axis_data_tvalid (fft_s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready (fft_s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tlast (fft_s_axis_data_tlast), // input wire s_axis_data_tlast
.m_axis_data_tdata (m_axis_data_tdata), // output wire [xx : 0] m_axis_data_tdata
.m_axis_data_tuser (m_axis_data_tuser), // output wire [7 : 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
.event_frame_started ( ), // output wire event_frame_started
.event_tlast_unexpected ( ), // output wire event_tlast_unexpected
.event_tlast_missing ( ), // output wire event_tlast_missing
.event_status_channel_halt ( ), // output wire event_status_channel_halt
.event_data_in_channel_halt ( ), // output wire event_data_in_channel_halt
.event_data_out_channel_halt( ) // output wire event_data_out_channel_halt
);
dds u_dds (
.clk ( clk ),
.rst ( rst ),
.Fword ( 32'h800_0000 ),
.Pword ( 11'b0 ),
.Out ( Out ),
.addr ( addr )
);
endmodule
仿真文件
module tb_ip_fft;
// ip_fft Parameters
parameter PERIOD = 10;
// ip_fft Inputs
reg clk = 0 ;
reg rst = 0 ;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
initial
begin
#(PERIOD*4) rst = 1;
end
ip_fft u_ip_fft (
.clk ( clk ),
.rst ( rst )
);
endmodule
dds文件
module dds(
input clk,
input rst,
input [31:0]Fword,
input [10:0]Pword,
output [7:0]Out,
output [10:0] addr
);
reg [31:0] r_Fword;
reg [10:0] r_Pword;
reg [31:0] cnt;
// wire [10:0] addr;
always @(posedge clk ) begin
r_Fword = Fword;
r_Pword = Pword;
end
always @(posedge clk or negedge rst) begin
if(!rst)
cnt <= 0;
else
cnt <= cnt+r_Fword;
end
assign addr = cnt[31:21]+r_Pword;
blk_mem_gen_0 u_blk_mem_gen_0 (
.clka (clk), // input wire clka
.ena (1'b1), // input wire ena
.addra (addr), // input wire [10 : 0] addra
.douta (Out) // output wire [7 : 0] douta
);
endmodule
IP配置
FFT



ROM




COE文件生成
matlab 代码,产生coe文件
%%
clc;
t=0:2*pi/(2^11-1):2*pi;
y=0.5*sin(t)+0.5;
figure; subplot(1,3,1); plot(y);
r=ceil(y*(2^8-1)); %将小数转换为整数,ceil是向上取整。
fid = fopen('sin.coe','w+'); %写到sin.coe文件,用来初始化sin_rom
fprintf(fid,'memory_initialization_radix=10;\n');
fprintf(fid,'memory_initialization_vector= \n');
for i = 1:1:2^11
fprintf(fid,'%d',r(i));
if i==2^11
fprintf(fid,'; ');
else
fprintf(fid,', ');
end
% if i%15==0
% fprintf(fid,'\n');
% end
end
fclose(fid);
reference
vivado 基于FPGA的dds学习记录
Vivado中FFT IP核的使用
都看到这儿了,点个赞吧!
该博客介绍了如何在FPGA上实现DDS(直接数字频率合成)和FFT(快速傅里叶变换),并利用Vivado和Modelsim进行联合仿真。首先,通过MATLAB生成COE文件来存储波形数据,然后在DDS模块中读取这些数据并控制信号频率。接着,DDS输出信号被送入FFT IP核进行处理。仿真过程中,输入信号范围是0-255,包含直流分量,频率为单频。最后,文章提供了HDL代码示例,包括顶层文件、DDS模块和仿真文件,以及FFT IP核的配置说明。
768





