verilog实现8点FFT运算

IP核设定

使用复数乘法IP核,参数设定如下:
verilog实现8点FFT运算_第1张图片
verilog实现8点FFT运算_第2张图片

verilog代码以及testbench

fft_8.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/07/16 11:15:56
// Design Name: 
// Module Name: fft_8
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module fft_8(
	// input ena
input clk, 
input reset,

// input data
input din_ena,
input signed [9:0] din_re0,
input signed [9:0] din_im0,
input signed [9:0] din_re1,
input signed [9:0] din_im1,
input signed [9:0] din_re2,
input signed [9:0] din_im2,
input signed [9:0] din_re3,
input signed [9:0] din_im3,
input signed [9:0] din_re4,
input signed [9:0] din_im4,
input signed [9:0] din_re5,
input signed [9:0] din_im5,
input signed [9:0] din_re6,
input signed [9:0] din_im6,
input signed [9:0] din_re7,
input signed [9:0] din_im7,


// output data
output dout_ena,
output signed [12:0] dout_re0,
output signed [12:0] dout_im0,
output signed [12:0] dout_re1,
output signed [12:0] dout_im1,
output signed [12:0] dout_re2,
output signed [12:0] dout_im2,
output signed [12:0] dout_re3,
output signed [12:0] dout_im3,
output signed [12:0] dout_re4,
output signed [12:0] dout_im4,
output signed [12:0] dout_re5,
output signed [12:0] dout_im5,
output signed [12:0] dout_re6,
output signed [12:0] dout_im6,
output signed [12:0] dout_re7,
output signed [12:0] dout_im7

    );
    
    //  FFT_1
    reg fft1_ena;
        reg signed [10:0] fft1_re0;
    reg signed [10:0] fft1_im0;
    		reg signed [10:0] fft1_re1;
    reg signed [10:0] fft1_im1;
        reg signed [10:0] fft1_re2;
    reg signed [10:0] fft1_im2;
        reg signed [10:0] fft1_re3;
    reg signed [10:0] fft1_im3;
        reg signed [10:0] fft1_re4;
    reg signed [10:0] fft1_im4;
        reg signed [10:0] fft1_re5;
    reg signed [10:0] fft1_im5;
        reg signed [10:0] fft1_re6;
    reg signed [10:0] fft1_im6;
        reg signed [10:0] fft1_re7;
    reg signed [10:0] fft1_im7;

always @ (posedge clk)
		if(!reset)
			// reset the device
			begin
				fft1_ena <=0;
				fft1_re0 <=0;
				fft1_im0 <=0;
				fft1_re1 <=0;
				fft1_im1 <=0;
				fft1_re2 <=0;
				fft1_im2 <=0;
				fft1_re3 <=0;
				fft1_im3 <=0;
				fft1_re4 <=0;
				fft1_im4 <=0;
				fft1_re5 <=0;
				fft1_im5 <=0;
				fft1_re6 <=0;
				fft1_im6 <=0;
				fft1_re7 <=0;
				fft1_im7 <=0;
			end
		else if(din_ena)
			begin
				fft1_ena <= 1;
				fft1_re0 <= din_re0 + din_re4;
				fft1_im0 <= din_im0 + din_im4;
				fft1_re1 <= din_re0 - din_re4;
				fft1_im1 <= din_im0 - din_im4;
				fft1_re2 <= din_re2 + din_re6;
				fft1_im2 <= din_im2 + din_im6;
				fft1_re3 <= din_re2 - din_re6;
				fft1_im3 <= din_im2 - din_im6;
				fft1_re4 <= din_re1 + din_re5;
				fft1_im4 <= din_im1 + din_im5;
				fft1_re5 <= din_re1 - din_re5;
				fft1_im5 <= din_im1 - din_im5;
				fft1_re6 <= din_re3 + din_re7;
				fft1_im6 <= din_im3 + din_im7;
				fft1_re7 <= din_re3 - din_re7;
				fft1_im7 <= din_im3 - din_im7;
			end
    else
    	fft1_ena <= 0;
    
    //FFT_2
    wire fft2_ena1_d0;
    wire signed [9:0] fft2_f1im;
    wire signed [10:0] fft2_im3_d0;
    wire signed [2:0] fft2_b1lim;
    wire signed [9:0] fft2_f1re;
    wire signed [10:0] fft2_re3_d0;
    wire signed [2:0] fft2_b1lre;
    cmpy_0 commul22 (
  .aclk(clk),                              // input wire aclk
  .s_axis_a_tvalid(fft1_ena),        // input wire s_axis_a_tvalid
  .s_axis_a_tdata({4'd0,fft1_im3,1'd0,4'd0,fft1_re3,1'd0}),          // input wire [31 : 0] s_axis_a_tdata
  .s_axis_b_tvalid(1'b1),        // input wire s_axis_b_tvalid
  .s_axis_b_tdata({8'b11111111,8'b10000000,8'd0,8'b00000000}),          // input wire [31 : 0] s_axis_b_tdata
  .m_axis_dout_tvalid(fft2_ena1_d0),  // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata({fft2_f1im,fft2_im3_d0,fft2_b1lim,fft2_f1re,fft2_re3_d0,fft2_b1lre})    // output wire [47 : 0] m_axis_dout_tdata
);

    wire fft2_ena2_d0;
    wire signed [9:0] fft2_f2im;
    wire signed [10:0] fft2_im7_d0;
    wire signed [2:0] fft2_b2lim;
    wire signed [9:0] fft2_f2re;
    wire signed [10:0] fft2_re7_d0;
    wire signed [2:0] fft2_b2lre;
    cmpy_0 commul24 (
  .aclk(clk),                              // input wire aclk
  .s_axis_a_tvalid(fft1_ena),        // input wire s_axis_a_tvalid
  .s_axis_a_tdata({4'd0,fft1_im7,1'd0,4'd0,fft1_re7,1'd0}),          // input wire [31 : 0] s_axis_a_tdata
  .s_axis_b_tvalid(1'b1),        // input wire s_axis_b_tvalid
  .s_axis_b_tdata({8'b11111111,8'b10000000,8'd0,8'b00000000}),          // input wire [31 : 0] s_axis_b_tdata
  .m_axis_dout_tvalid(fft2_ena2_d0),  // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata({fft2_f2im,fft2_im7_d0,fft2_b2lim,fft2_f2re,fft2_re7_d0,fft2_b2lre})    // output wire [47 : 0] m_axis_dout_tdata
);
    
        reg fft2_ena;
        reg signed [11:0] fft2_re0;
    reg signed [11:0] fft2_im0;
    		reg signed [11:0] fft2_re1;
    reg signed [11:0] fft2_im1;
        reg signed [11:0] fft2_re2;
    reg signed [11:0] fft2_im2;
        reg signed [11:0] fft2_re3;
    reg signed [11:0] fft2_im3;
        reg signed [11:0] fft2_re4;
    reg signed [11:0] fft2_im4;
        reg signed [11:0] fft2_re5;
    reg signed [11:0] fft2_im5;
        reg signed [11:0] fft2_re6;
    reg signed [11:0] fft2_im6;
        reg signed [11:0] fft2_re7;
    reg signed [11:0] fft2_im7;
    
always @ (posedge clk)
		if(!reset)
			begin
				fft2_ena <= 0;
				fft2_re0 <= 0;
				fft2_im0 <= 0;
				fft2_re1 <= 0;
				fft2_im1 <= 0;
				fft2_re2 <= 0;
				fft2_im2 <= 0;
				fft2_re3 <= 0;
				fft2_im3 <= 0;
				fft2_re4 <= 0;
				fft2_im4 <= 0;
				fft2_re5 <= 0;
				fft2_im5 <= 0;
				fft2_re6 <= 0;
				fft2_im6 <= 0;
				fft2_re7 <= 0;
				fft2_im7 <= 0;
			end
		else if(fft2_ena2_d0&&fft2_ena1_d0)
			begin
				fft2_ena <=1;
				fft2_re0 <= fft1_re0 + fft1_re2;
				fft2_im0 <= fft1_im0 + fft1_im2;
				fft2_re2 <= fft1_re0 - fft1_re2;
				fft2_im2 <= fft1_im0 - fft1_im2;
				
				fft2_re1 <= fft1_re1 + fft2_re3_d0;
				fft2_im1 <= fft1_im1 + fft2_im3_d0;
				fft2_re3 <= fft1_re1 - fft2_re3_d0;
				fft2_im3 <= fft1_im1 - fft2_im3_d0;
				
				fft2_re4 <= fft1_re4 + fft1_re6;
				fft2_im4 <= fft1_im4 + fft1_im6;
				fft2_re6 <= fft1_re4 - fft1_re6;
				fft2_im6 <= fft1_im4 - fft1_im6;
				
				fft2_re5 <= fft1_re5 + fft2_re7_d0;
				fft2_im5 <= fft1_im5 + fft2_im7_d0;
				fft2_re7 <= fft1_re5 - fft2_re7_d0;
				fft2_im7 <= fft1_im5 - fft2_im7_d0;
			end
		else
			fft2_ena <= 0;
		
    // FFT_3
    wire fft3_ena1_d0;
    wire signed [5:0] fft3_f1im;
    wire signed [11:0] fft3_im5_d0;
    wire signed [5:0] fft3_b1lim;
    wire signed [5:0] fft3_f1re;
    wire signed [11:0] fft3_re5_d0;
    wire signed [5:0] fft3_b1lre;
    cmpy_0 commul32 (
  .aclk(clk),                              // input wire aclk
  .s_axis_a_tvalid(fft2_ena),        // input wire s_axis_a_tvalid
  .s_axis_a_tdata({4'd0,fft2_im5,4'd0,fft2_re5}),          // input wire [31 : 0] s_axis_a_tdata
  .s_axis_b_tvalid(1'b1),        // input wire s_axis_b_tvalid
  .s_axis_b_tdata({4'd0,12'b101001011000,4'd0,12'b010110101000}),          // input wire [31 : 0] s_axis_b_tdata
  .m_axis_dout_tvalid(fft3_ena1_d0),  // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata({fft3_f1im,fft3_im5_d0,fft3_b1lim,fft3_f1re,fft3_re5_d0,fft3_b1lre})    // output wire [47 : 0] m_axis_dout_tdata
);
		wire fft3_ena2_d0;
    wire signed [5:0] fft3_f2im;
    wire signed [11:0] fft3_im6_d0;
    wire signed [5:0] fft3_b2lim;
    wire signed [5:0] fft3_f2re;
    wire signed [11:0] fft3_re6_d0;
    wire signed [5:0] fft3_b2lre;
    cmpy_0 commul33 (
  .aclk(clk),                              // input wire aclk
  .s_axis_a_tvalid(fft2_ena),        // input wire s_axis_a_tvalid
  .s_axis_a_tdata({4'd0,fft2_im6,4'd0,fft2_re6}),          // input wire [31 : 0] s_axis_a_tdata
  .s_axis_b_tvalid(1'b1),        // input wire s_axis_b_tvalid
  .s_axis_b_tdata({4'd0,12'b100000000000,4'd0,12'b000000000000}),          // input wire [31 : 0] s_axis_b_tdata
  .m_axis_dout_tvalid(fft3_ena2_d0),  // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata({fft3_f2im,fft3_im6_d0,fft3_b2lim,fft3_f2re,fft3_re6_d0,fft3_b2lre})    // output wire [47 : 0] m_axis_dout_tdata
);
		wire fft3_ena3_d0;
    wire signed [5:0] fft3_f3im;
    wire signed [11:0] fft3_im7_d0;
    wire signed [5:0] fft3_b3lim;
    wire signed [5:0] fft3_f3re;
    wire signed [11:0] fft3_re7_d0;
    wire signed [5:0] fft3_b3lre;
    cmpy_0 commul34 (
  .aclk(clk),                              // input wire aclk
  .s_axis_a_tvalid(fft2_ena),        // input wire s_axis_a_tvalid
  .s_axis_a_tdata({4'd0,fft2_im7,4'd0,fft2_re7}),          // input wire [31 : 0] s_axis_a_tdata
  .s_axis_b_tvalid(1'b1),        // input wire s_axis_b_tvalid
  .s_axis_b_tdata({4'd0,12'b101001011000,4'd0,12'b101001011000}),          // input wire [31 : 0] s_axis_b_tdata
  .m_axis_dout_tvalid(fft3_ena3_d0),  // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata({fft3_f3im,fft3_im7_d0,fft3_b3lim,fft3_f3re,fft3_re7_d0,fft3_b3lre})    // output wire [47 : 0] m_axis_dout_tdata
);
        reg fft3_ena;
        reg signed [12:0] fft3_re0;
    reg signed [12:0] fft3_im0;
    		reg signed [12:0] fft3_re1;
    reg signed [12:0] fft3_im1;
        reg signed [12:0] fft3_re2;
    reg signed [12:0] fft3_im2;
        reg signed [12:0] fft3_re3;
    reg signed [12:0] fft3_im3;
        reg signed [12:0] fft3_re4;
    reg signed [12:0] fft3_im4;
        reg signed [12:0] fft3_re5;
    reg signed [12:0] fft3_im5;
        reg signed [12:0] fft3_re6;
    reg signed [12:0] fft3_im6;
        reg signed [12:0] fft3_re7;
    reg signed [12:0] fft3_im7;
always @ (posedge clk)
		if(!reset)
			begin
				fft3_ena <= 0;
				fft3_re0 <= 0;
				fft3_im0 <= 0;
				fft3_re1 <= 0;
				fft3_im1 <= 0;
				fft3_re2 <= 0;
				fft3_im2 <= 0;
				fft3_re3 <= 0;
				fft3_im3 <= 0;
				fft3_re4 <= 0;
				fft3_im4 <= 0;
				fft3_re5 <= 0;
				fft3_im5 <= 0;
				fft3_re6 <= 0;
				fft3_im6 <= 0;
				fft3_re7 <= 0;
				fft3_im7 <= 0;
			end
			else if(fft3_ena1_d0&&fft3_ena2_d0&&fft3_ena3_d0)
				begin
					fft3_ena <=1'b1;
					fft3_re0 <= fft2_re0 + fft2_re4;
					fft3_im0 <= fft2_im0 + fft2_im4;
					fft3_re4 <= fft2_re0 - fft2_re4;
					fft3_im4 <= fft2_im0 - fft2_im4;
					
					fft3_re1 <= fft2_re1 + fft3_re5_d0;
					fft3_im1 <= fft2_im1 + fft3_im5_d0;
					fft3_re5 <= fft2_re1 - fft3_re5_d0;
					fft3_im5 <= fft2_im1 - fft3_im5_d0;
					
					fft3_re2 <= fft2_re2 + fft3_re6_d0;
					fft3_im2 <= fft2_im2 + fft3_im6_d0;
					fft3_re6 <= fft2_re2 - fft3_re6_d0;
					fft3_im6 <= fft2_im2 - fft3_im6_d0;
					
					fft3_re3 <= fft2_re3 + fft3_re7_d0;
					fft3_im3 <= fft2_im3 + fft3_im7_d0;
					fft3_re7 <= fft2_re3 - fft3_re7_d0;
					fft3_im7 <= fft2_im3 - fft3_im7_d0;
				end
			else
				fft3_ena <= 0;
assign dout_ena = fft3_ena;
assign dout_re0 = fft3_re0;
assign dout_im0 = fft3_im0;
assign dout_re1 = fft3_re1;
assign dout_im1 = fft3_im1;
assign dout_re2 = fft3_re2;
assign dout_im2 = fft3_im2;
assign dout_re3 = fft3_re3;
assign dout_im3 = fft3_im3;
assign dout_re4 = fft3_re4;
assign dout_im4 = fft3_im4;
assign dout_re5 = fft3_re5;
assign dout_im5 = fft3_im5;
assign dout_re6 = fft3_re6;
assign dout_im6 = fft3_im6;
assign dout_re7 = fft3_re7;
assign dout_im7 = fft3_im7;
endmodule



fft_8_tb.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/07/16 17:56:18
// Design Name: 
// Module Name: fft_8_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module fft_8_tb(

    );
    reg aclk;
    reg rst;
    reg din_ena;
    wire dout_ena;
    reg [9:0] din_re0;
    reg [9:0] din_im0;
    reg [9:0] din_re1;
    reg [9:0] din_im1;
    reg [9:0] din_re2;
    reg [9:0] din_im2;
    reg [9:0] din_re3;
    reg [9:0] din_im3;
    reg [9:0] din_re4;
    reg [9:0] din_im4;
    reg [9:0] din_re5;
    reg [9:0] din_im5;
    reg [9:0] din_re6;
    reg [9:0] din_im6;
    reg [9:0] din_re7;
    reg [9:0] din_im7;
    wire [12:0] dout_re0;
    wire [12:0] dout_im0;
    wire [12:0] dout_re1;
    wire [12:0] dout_im1;
    wire [12:0] dout_re2;
    wire [12:0] dout_im2;
    wire [12:0] dout_re3;
    wire [12:0] dout_im3;
    wire [12:0] dout_re4;
    wire [12:0] dout_im4;
    wire [12:0] dout_re5;
    wire [12:0] dout_im5;
    wire [12:0] dout_re6;
    wire [12:0] dout_im6;
    wire [12:0] dout_re7;
    wire [12:0] dout_im7;
    
    initial
    begin
        #0 aclk = 0;
            rst = 0;
        #10
            rst = 1;
            din_ena = 1;
            din_re0 = 10'b0000000000;
            din_im0 = 10'b0000000000;
            din_re1 = 10'b0000000000;
            din_im1 = 10'b0000000000;
            din_re2 = 10'b0010000000;
            din_im2 = 10'b0000000000;
            din_re3 = 10'b0000000000;
            din_im3 = 10'b0000000000;
            din_re4 = 10'b0100000000;
            din_im4 = 10'b0000000000;
            din_re5 = 10'b0000000000;
            din_im5 = 10'b0000000000;
            din_re6 = 10'b0000000000;
            din_im6 = 10'b0000000000;
            din_re7 = 10'b0000000000;
            din_im7 = 10'b0000000000;
        forever 
         #5 aclk =~aclk;
    end
    
    fft_8 fft81(
        .clk(aclk),
        .reset(rst),
        .din_ena(din_ena),
        .din_re0(din_re0),
        .din_im0(din_im0),
        .din_re1(din_re1),
        .din_im1(din_im1),
        .din_re2(din_re2),
        .din_im2(din_im2),
        .din_re3(din_re3),
        .din_im3(din_im3),
        .din_re4(din_re4),
        .din_im4(din_im4),
        .din_re5(din_re5),
        .din_im5(din_im5),
        .din_re6(din_re6),
        .din_im6(din_im6),
        .din_re7(din_re7),
        .din_im7(din_im7),
        
        .dout_ena(dout_ena),
        .dout_re0(dout_re0),
        .dout_im0(dout_im0),
        .dout_re1(dout_re1),
        .dout_im1(dout_im1),
        .dout_re2(dout_re2),
        .dout_im2(dout_im2),
        .dout_re3(dout_re3),
        .dout_im3(dout_im3),
        .dout_re4(dout_re4),
        .dout_im4(dout_im4),
        .dout_re5(dout_re5),
        .dout_im5(dout_im5),
        .dout_re6(dout_re6),
        .dout_im6(dout_im6),
        .dout_re7(dout_re7),
        .dout_im7(dout_im7)
    );
endmodule

输出结果dout中的数的构成是:
共13位其中5位整数,8位小数。
模拟结果在波形图里应该如下设置:
verilog实现8点FFT运算_第3张图片
verilog实现8点FFT运算_第4张图片
输出结果如下:
verilog实现8点FFT运算_第5张图片
可以看到会有一些误差存在,因为在使用ip核进行计算的时候,直接对小数乘法部分进行了截断处理,会造成误差。
和matlab结果对比:
verilog实现8点FFT运算_第6张图片
verilog实现8点FFT运算_第7张图片

你可能感兴趣的:(verilog,fpga)