基5FFT的verilog代码实现及仿真
FPGA自学笔记分享 2023-03-27

本文使用verilog实现25点基5FFT的代码。

根据算法推导,基5FFT的verilog代码整体结构为:

verilog代码实现首先进行5点FFT的实现,代码主要做:

O0=D0+D1+D2+D3+D4O1=(D0+D1*W15+D2*W25+D3*W35+D4*W45O2=(D0+D1*W25+D2*W45+D3*W15+D4*W35O3=(D0+D1*W35+D2*W15+D3*W45+D4*W25)O4=(D0+D1*W45+D2*W35+D3*W25+D4*W15)

代码内容如下,因为代码较长下面代码删除了数据和start信号的打拍,代码中S_data_add_real_p0/p1p2/p3/p4对应上边式子中的O0/O1/O2/O3/O4.

// ============================================================// File Name: cm_fft5_N5// VERSION  : V1.0// DATA     : 2023/1/1// Author   : FPGA干货分享// ============================================================// 功能:基5FFT N=5的数据处理// delay : 11clk// ============================================================  `timescale 1ns/100psmodule cm_fft5_N5 #( parameter C_DATA_WITH     = 16  )( input wire                     I_sys_clk       , /// 工作时钟 100M input wire                     I_data_start    , /// 数据开始进入标志,与第一个数据对齐输入 input wire [C_DATA_WITH-1:0]   I_data_in_real  , /// 数据输入,从start开始连续输入 input wire [C_DATA_WITH-1:0]   I_data_in_imag  , /// 数据输入,从start开始连续输入 output wire                     O_data_start    , /// 数据开始输出标志与第一个数据对齐输出 output reg  [C_DATA_WITH+2:0]   O_data_out_real , /// 数据输出,从start开始连续输出 output reg  [C_DATA_WITH+2:0]   O_data_out_imag   /// 数据输出,从start开始连续输出); // ============================================================// 内部参数// ============================================================/// W05=1/// W15=0.30901699437494745-0.9510565162951535j /// W25=-0.8090169943749473-0.5877852522924732j /// W35=-0.8090169943749475+0.587785252292473j /// W45=0.30901699437494723+0.9510565162951536j  /// W15 = (0.30901699437494745-0.9510565162951535j)*1024 = 316 - 974j/// W25 = (-0.8090169943749473-0.5877852522924732j)*1024 = -828- 602j/// W35 = (-0.8090169943749473+0.5877852522924732j)*1024 = -828+ 602j/// W45 = (0.30901699437494745+0.9510565162951535j)*1024 = 316 + 974j  always @(posedge I_sys_clk) if(S_data_start_d5) begin S_data_add_real_p0 <= {{3{S_data_in_real_d5[C_DATA_WITH-1]}},S_data_in_real_d5}; S_data_add_imag_p0 <= {{3{S_data_in_imag_d5[C_DATA_WITH-1]}},S_data_in_imag_d5}; end else begin S_data_add_real_p0 <= S_data_add_real_p0 + {{3{S_data_in_real_d5[C_DATA_WITH-1]}},S_data_in_real_d5}; S_data_add_imag_p0 <= S_data_add_imag_p0 + {{3{S_data_in_imag_d5[C_DATA_WITH-1]}},S_data_in_imag_d5}; end   /// W15 =  316 - 974j/// W25 =  -828- 602j/// W35 =  -828+ 602j/// W45 =  316 + 974jalways @(*) if(S_data_start_d1) begin S_Wn5_real_p1 = 12'd316   ; S_Wn5_imag_p1 = -12'd974  ; end else if(S_data_start_d2) begin S_Wn5_real_p1 = -12'd828   ; S_Wn5_imag_p1 = -12'd602   ; end else if(S_data_start_d3) begin S_Wn5_real_p1 = -12'd828   ; S_Wn5_imag_p1 = 12'd602   ; end else begin S_Wn5_real_p1 = 12'd316   ; S_Wn5_imag_p1 = 12'd974   ; end /// 调用复乘 delay 6clkcmult # (.AWIDTH    (C_DATA_WITH        ) , .BWIDTH (12                 ) )u0_cmult_p1 ( .clk (I_sys_clk          ) , .ar (I_data_in_real     ) , .ai (I_data_in_imag     ) , .br (S_Wn5_real_p1      ) , .bi (S_Wn5_imag_p1      ) , .pr (S_data_multp1_real  ) , .pi (S_data_multp1_imag  )  ); always @(posedge I_sys_clk) if(S_data_start_d6) begin S_data_add_real_p1 <= {{3{S_data_in_real_d6[C_DATA_WITH-1]}},S_data_in_real_d6}; S_data_add_imag_p1 <= {{3{S_data_in_imag_d6[C_DATA_WITH-1]}},S_data_in_imag_d6}; end else begin S_data_add_real_p1 <= S_data_add_real_p1 + S_data_multp1_real[(C_DATA_WITH+12):10] + S_data_multp1_real[9]; S_data_add_imag_p1 <= S_data_add_imag_p1 + S_data_multp1_imag[(C_DATA_WITH+12):10] + S_data_multp1_imag[9]; end  /// W25 =  -828- 602j/// W45 =  316 + 974j/// W15 =  316 - 974j/// W35 =  -828+ 602jalways @(*) if(S_data_start_d2) begin S_Wn5_real_p2 = -12'd828   ; S_Wn5_imag_p2 = -12'd602   ; end else if(S_data_start_d3) begin S_Wn5_real_p2 = 12'd316   ; S_Wn5_imag_p2 = 12'd974  ; end else if(S_data_start_d4) begin S_Wn5_real_p2 = 12'd316   ; S_Wn5_imag_p2 = -12'd974  ; end else begin S_Wn5_real_p2 = -12'd828   ; S_Wn5_imag_p2 = 12'd602   ; end /// 调用复乘 delay 6clkcmult # (.AWIDTH    (C_DATA_WITH        ) , .BWIDTH (12                 ) )u0_cmult_p2 ( .clk (I_sys_clk          ) , .ar (S_data_in_real_d1  ) , .ai (S_data_in_imag_d1  ) , .br (S_Wn5_real_p2      ) , .bi (S_Wn5_imag_p2      ) , .pr (S_data_multp2_real  ) , .pi (S_data_multp2_imag  )  ); always @(posedge I_sys_clk) if(S_data_start_d7) begin S_data_add_real_p2 <= {{3{S_data_in_real_d7[C_DATA_WITH-1]}},S_data_in_real_d7}; S_data_add_imag_p2 <= {{3{S_data_in_imag_d7[C_DATA_WITH-1]}},S_data_in_imag_d7}; end else begin S_data_add_real_p2 <= S_data_add_real_p2 + S_data_multp2_real[(C_DATA_WITH+12):10] + S_data_multp2_real[9]; S_data_add_imag_p2 <= S_data_add_imag_p2 + S_data_multp2_imag[(C_DATA_WITH+12):10] + S_data_multp2_imag[9]; end   /// W35 =  -828+ 602j/// W15 =  316 - 974j/// W45 =  316 + 974j/// W25 =  -828- 602jalways @(*) if(S_data_start_d3) begin S_Wn5_real_p3 = -12'd828   ; S_Wn5_imag_p3 = 12'd602   ; end else if(S_data_start_d4) begin S_Wn5_real_p3 = 12'd316   ; S_Wn5_imag_p3 = -12'd974  ; end else if(S_data_start_d5) begin S_Wn5_real_p3 = 12'd316   ; S_Wn5_imag_p3 = 12'd974  ; end else begin S_Wn5_real_p3 = -12'd828   ; S_Wn5_imag_p3 = -12'd602   ; end /// 调用复乘 delay 6clkcmult # (.AWIDTH    (C_DATA_WITH        ) , .BWIDTH (12                 ) )u0_cmult_p3 ( .clk (I_sys_clk          ) , .ar (S_data_in_real_d2  ) , .ai (S_data_in_imag_d2  ) , .br (S_Wn5_real_p3      ) , .bi (S_Wn5_imag_p3      ) , .pr (S_data_multp3_real  ) , .pi (S_data_multp3_imag  )  ); always @(posedge I_sys_clk) if(S_data_start_d8) begin S_data_add_real_p3 <= {{3{S_data_in_real_d8[C_DATA_WITH-1]}},S_data_in_real_d8}; S_data_add_imag_p3 <= {{3{S_data_in_imag_d8[C_DATA_WITH-1]}},S_data_in_imag_d8}; end else begin S_data_add_real_p3 <= S_data_add_real_p3 + S_data_multp3_real[(C_DATA_WITH+12):10] + S_data_multp3_real[9]; S_data_add_imag_p3 <= S_data_add_imag_p3 + S_data_multp3_imag[(C_DATA_WITH+12):10] + S_data_multp3_imag[9]; end   /// W45 =  316 + 974j/// W35 =  -828+ 602j/// W25 =  -828- 602j/// W15 =  316 - 974jalways @(*) if(S_data_start_d4) begin S_Wn5_real_p4 = 12'd316  ; S_Wn5_imag_p4 = 12'd974  ; end else if(S_data_start_d5) begin S_Wn5_real_p4 = -12'd828   ; S_Wn5_imag_p4 = 12'd602   ; end else if(S_data_start_d6) begin S_Wn5_real_p4 = -12'd828   ; S_Wn5_imag_p4 = -12'd602   ; end else if(S_data_start_d7) begin S_Wn5_real_p4 = 12'd316   ; S_Wn5_imag_p4 = -12'd974  ; end /// 调用复乘 delay 6clkcmult # (.AWIDTH    (C_DATA_WITH        ) , .BWIDTH (12                 ) )u0_cmult_p4 ( .clk (I_sys_clk          ) , .ar (S_data_in_real_d3  ) , .ai (S_data_in_imag_d3  ) , .br (S_Wn5_real_p4      ) , .bi (S_Wn5_imag_p4      ) , .pr (S_data_multp4_real  ) , .pi (S_data_multp4_imag  )  );  always @(posedge I_sys_clk) if(S_data_start_d9) begin S_data_add_real_p4 <= {{3{S_data_in_real_d9[C_DATA_WITH-1]}},S_data_in_real_d9}; S_data_add_imag_p4 <= {{3{S_data_in_imag_d9[C_DATA_WITH-1]}},S_data_in_imag_d9}; end else begin S_data_add_real_p4 <= S_data_add_real_p4 + S_data_multp4_real[(C_DATA_WITH+12):10] + S_data_multp4_real[9]; S_data_add_imag_p4 <= S_data_add_imag_p4 + S_data_multp4_imag[(C_DATA_WITH+12):10] + S_data_multp4_imag[9]; end   always @(posedge I_sys_clk) if(S_data_start_d10) begin O_data_out_real <= S_data_add_real_p0 ; O_data_out_imag <= S_data_add_imag_p0 ; end else if(S_data_start_d11) begin O_data_out_real <= S_data_add_real_p1 ; O_data_out_imag <= S_data_add_imag_p1 ; end else if(S_data_start_d12) begin O_data_out_real <= S_data_add_real_p2 ; O_data_out_imag <= S_data_add_imag_p2 ; end else if(S_data_start_d13) begin O_data_out_real <= S_data_add_real_p3 ; O_data_out_imag <= S_data_add_imag_p3 ; end else if(S_data_start_d14) begin O_data_out_real <= S_data_add_real_p4 ; O_data_out_imag <= S_data_add_imag_p4 ; end else begin O_data_out_real <= 'd0 ; O_data_out_imag <= 'd0 ; end  assign O_data_start = S_data_start_d11 ;   endmodule


随后进行25点FFT代码的实现,代码主要计算

O0-4=D0+D1+D2+D3+D4O5-9=(D0+D1*W15+D2*W25+D3*W35+D4*W45)*{Wn(25)}O10-14=(D0+D1*W25+D2*W45+D3*W15+D4*W35)*{W2n(25)}O15-19=(D0+D1*W35+D2*W15+D3*W45+D4*W25)*{W3n(25)}O20-24=(D0+D1*W45+D2*W35+D3*W25+D4*W15)*{W4n(25)}

代码如下,显然25点的FFT要缓存的数据量是非常大的,使用功打拍的方法是不合适的,这里使用分布式ram建立缓存空间,直接使用功5块ram缓存相应的数据:











































































































































































































































































































































// ============================================================// File Name: cm_fft5_N25// VERSION  : V1.0// DATA     : 2023/2/20// Author   : FPGA干货分享// ============================================================// 功能:基5FFT N=25的数据处理// delay : 42clk// ============================================================  `timescale 1ns/100psmodule cm_fft5_N25 #( parameter                       C_DATA_WIDTH    = 16 )( input  wire                     I_sys_clk       , /// 工作时钟 100M input  wire                     I_data_start    , /// 数据开始进入标志,与第一个数据对齐输入 input  wire [C_DATA_WIDTH-1:0]  I_data_in_real  , /// 数据输入,从start开始连续输入 input  wire [C_DATA_WIDTH-1:0]  I_data_in_imag  , /// 数据输入,从start开始连续输入 output reg                      O_data_start    , /// 数据开始输出标志与第一个数据对齐输出 output wire [C_DATA_WIDTH+5:0]  O_data_out_real , /// 数据输出,从start开始连续输出 output wire [C_DATA_WIDTH+5:0]  O_data_out_imag /// 数据输出,从start开始连续输出); // ============================================================// 内部参数// ============================================================///  W05=1///  W15=0.30901699437494745-0.9510565162951535j ///  W25=-0.8090169943749473-0.5877852522924732j ///  W35=-0.8090169943749475+0.587785252292473j ///  W45=0.30901699437494723+0.9510565162951536j  ///  W15 = (0.30901699437494745-0.9510565162951535j)*1024 = 316 - 974j///  W25 = (-0.8090169943749473-0.5877852522924732j)*1024 = -828- 602j///  W35 = (-0.8090169943749473+0.5877852522924732j)*1024 = -828+ 602j///  W45 = (0.30901699437494745+0.9510565162951535j)*1024 = 316 + 974j// ============================================================// 变量// ============================================================reg  [2:0]                  S_data_cnt5                 ;reg  [2:0]                  S_cnt5_rd                   ;reg  [4:0]                  S_wr_en                     ;reg  [C_DATA_WIDTH*2-1:0]   S_data_in                   ;reg                         S_pingpang_flag             ;reg  [3:0]                  S_rd_addr                   ;wire [C_DATA_WIDTH-1:0]     S_ram_out_i[4:0]            ;wire [C_DATA_WIDTH-1:0]     S_ram_out_q[4:0]            ;reg  [11:0]                 S_Wn5_real[4:1]             ;reg  [11:0]                 S_Wn5_imag[4:1]             ;wire [C_DATA_WIDTH+12:0]    S_data_multp_real[4:1]      ;wire [C_DATA_WIDTH+12:0]    S_data_multp_imag[4:1]      ;reg  [C_DATA_WIDTH-1:0]     S_ram_out_i0_d              ;reg  [C_DATA_WIDTH-1:0]     S_ram_out_q0_d              ;  reg  [C_DATA_WIDTH+2:0]     S_data_add_real_p0          ; reg  [C_DATA_WIDTH+2:0]     S_data_add_imag_p0          ;reg  [C_DATA_WIDTH+2:0]     S_data_add_real_p0_d1       ; reg  [C_DATA_WIDTH+2:0]     S_data_add_imag_p0_d1       ;reg  [C_DATA_WIDTH+2:0]     S_data_add_real_p0_d2       ; reg  [C_DATA_WIDTH+2:0]     S_data_add_imag_p0_d2       ; reg  [C_DATA_WIDTH+2:0]     S_data_add_real_p2          ; reg  [C_DATA_WIDTH+2:0]     S_data_add_imag_p2          ; reg  [4:0]                  s_data_w25_cnt              ;reg  [11:0]                 S_Wn25_real                 ;reg  [11:0]                 S_Wn25_imag                 ;wire [C_DATA_WIDTH+15:0]    S_data_multw25_real         ;wire [C_DATA_WIDTH+15:0]    S_data_multw25_imag         ;reg  [C_DATA_WIDTH+2:0]     S_data_out_real             ;reg  [C_DATA_WIDTH+2:0]     S_data_out_imag             ;reg                         S_data_start_5              ;// ============================================================// main code// ============================================================always @(posedge I_sys_clk) if(I_data_start) S_pingpang_flag <= ~S_pingpang_flag; else S_pingpang_flag <= S_pingpang_flag ; always @(posedge I_sys_clk) S_data_in <={I_data_in_real,I_data_in_imag} ; always @(posedge I_sys_clk) if(I_data_start) S_data_cnt5 <= 3'd0; else if(S_data_cnt5 == 3'd4) S_data_cnt5 <= 3'd0; else  S_data_cnt5 <= S_data_cnt5 + 'd1; always @(posedge I_sys_clk) if(I_data_start) S_wr_en <= 5'b00001; else if(S_data_cnt5 == 3'd4) S_wr_en <= {S_wr_en[3:0],1'b0}; else S_wr_en <= S_wr_en ; genvar j;generate for (j=0;j<5;j=j+1) begin  cm_dis_sdp_ram #( .C_DATA_WIDTH           ( C_DATA_WIDTH*2            ) , // Specify RAM data width .C_ADDR_WIDTH           ( 4              ) , // Specify RAM depth 2**C_ADDR_WIDTH .C_DELAY_NUM            ( 1                         ) , // delay .INIT_FILE              ( ""                        ) ) // Specify name/location of RAM initialization file if using one (leave blank if not) u0_cm_dis_sdp_ram( .I_addra                ({S_pingpang_flag,S_data_cnt5} ) , // Write address bus, width determined from RAM_DEPTH .I_addrb                (S_rd_addr                  ) , // Read address bus, width determined from RAM_DEPTH .I_dina                 (S_data_in                  ) , // RAM input data .I_clka                 (I_sys_clk                  ) , // Write clock .I_clkb                 (I_sys_clk                  ) , // Read clock .I_wea                  (S_wr_en[j]                 ) , // Write enable .O_doutb                ({S_ram_out_i[j],S_ram_out_q[j]}         )   // RAM output data );  if(j != 0) begin /// 调用复乘 delay 6clk cmult # (.AWIDTH    (C_DATA_WIDTH                ) , .BWIDTH    (12                         ) ) u0_cmult_p1 ( .clk       (I_sys_clk                  ) , .ar        (S_ram_out_i[j]             ) , .ai        (S_ram_out_q[j]             ) , .br        (S_Wn5_real[j]              ) , .bi        (S_Wn5_imag[j]              ) , .pr        (S_data_multp_real[j]       ) , .pi        (S_data_multp_imag[j]       )  ); end  endendgenerate always @(posedge I_sys_clk) if(S_wr_en[4]&(S_data_cnt5==0)) S_rd_addr[3] <= S_pingpang_flag; else S_rd_addr[3] <= S_rd_addr[3] ; always @(posedge I_sys_clk) if(S_wr_en[4]&(S_data_cnt5==0)) S_cnt5_rd <= 3'd0; else if((S_data_cnt5==0)) if(S_cnt5_rd == 3'd5) S_cnt5_rd <= S_cnt5_rd; else S_cnt5_rd <= S_cnt5_rd + 'd1; else S_cnt5_rd <= S_cnt5_rd ; always @(posedge I_sys_clk) if((S_data_cnt5==0)) S_rd_addr[2:0] <= 3'd0; else S_rd_addr[2:0] <= S_rd_addr[2:0] + 'd1; always @(posedge I_sys_clk) case(S_cnt5_rd) 3'd0: begin S_Wn5_real[1] <= 12'd316 ; S_Wn5_imag[1] <= -12'd974; S_Wn5_real[2] <= -12'd828 ; S_Wn5_imag[2] <= -12'd602 ; S_Wn5_real[3] <= -12'd828 ; S_Wn5_imag[3] <= 12'd602 ; S_Wn5_real[4] <= 12'd316 ; S_Wn5_imag[4] <= 12'd974; end 3'd1: begin S_Wn5_real[1] <= -12'd828 ; S_Wn5_imag[1] <= -12'd602 ; S_Wn5_real[2] <= 12'd316 ; S_Wn5_imag[2] <= 12'd974; S_Wn5_real[3] <= 12'd316 ; S_Wn5_imag[3] <= -12'd974; S_Wn5_real[4] <= -12'd828 ; S_Wn5_imag[4] <= 12'd602 ; end 3'd2: begin S_Wn5_real[1] <= -12'd828 ; S_Wn5_imag[1] <= 12'd602 ; S_Wn5_real[2] <= 12'd316 ; S_Wn5_imag[2] <= -12'd974; S_Wn5_real[3] <= 12'd316 ; S_Wn5_imag[3] <= 12'd974; S_Wn5_real[4] <= -12'd828 ; S_Wn5_imag[4] <= -12'd602 ; end default: begin S_Wn5_real[1] <= 12'd316 ; S_Wn5_imag[1] <= 12'd974; S_Wn5_real[2] <= -12'd828 ; S_Wn5_imag[2] <= 12'd602 ; S_Wn5_real[3] <= -12'd828 ; S_Wn5_imag[3] <= -12'd602 ; S_Wn5_real[4] <= 12'd316 ; S_Wn5_imag[4] <= -12'd974; end endcase always @(posedge I_sys_clk) begin S_data_add_real_p0 <= {{3{S_ram_out_i[0][C_DATA_WIDTH-1]}},S_ram_out_i[0]} + {{3{S_ram_out_i[1][C_DATA_WIDTH-1]}},S_ram_out_i[1]} + {{3{S_ram_out_i[2][C_DATA_WIDTH-1]}},S_ram_out_i[2]} + {{3{S_ram_out_i[3][C_DATA_WIDTH-1]}},S_ram_out_i[3]} + {{3{S_ram_out_i[4][C_DATA_WIDTH-1]}},S_ram_out_i[4]}  ; S_data_add_imag_p0 <= {{3{S_ram_out_q[0][C_DATA_WIDTH-1]}},S_ram_out_q[0]} + {{3{S_ram_out_q[1][C_DATA_WIDTH-1]}},S_ram_out_q[1]} + {{3{S_ram_out_q[2][C_DATA_WIDTH-1]}},S_ram_out_q[2]} + {{3{S_ram_out_q[3][C_DATA_WIDTH-1]}},S_ram_out_q[3]} + {{3{S_ram_out_q[4][C_DATA_WIDTH-1]}},S_ram_out_q[4]}  ; S_data_add_real_p0_d1 <= S_data_add_real_p0 ; S_data_add_imag_p0_d1 <= S_data_add_imag_p0 ; S_data_add_real_p0_d2 <= S_data_add_imag_p0_d1 ; S_data_add_imag_p0_d2 <= S_data_add_imag_p0_d1 ; end always @(posedge I_sys_clk) begin S_ram_out_i0_d <= S_ram_out_i[0] ; S_ram_out_q0_d <= S_ram_out_q[0] ; end always @(posedge I_sys_clk) begin S_data_add_real_p2 <= {{3{S_ram_out_i0_d[C_DATA_WIDTH-1]}},S_ram_out_i0_d} + S_data_multp_real[1][(C_DATA_WIDTH+12):10] + S_data_multp_real[1][9] + S_data_multp_real[2][(C_DATA_WIDTH+12):10] + S_data_multp_real[2][9] + S_data_multp_real[3][(C_DATA_WIDTH+12):10] + S_data_multp_real[3][9] + S_data_multp_real[4][(C_DATA_WIDTH+12):10] + S_data_multp_real[4][9] ; S_data_add_imag_p2 <= {{3{S_ram_out_q0_d[C_DATA_WIDTH-1]}},S_ram_out_q0_d} + S_data_multp_imag[1][(C_DATA_WIDTH+12):10] + S_data_multp_imag[1][9] + S_data_multp_imag[2][(C_DATA_WIDTH+12):10] + S_data_multp_imag[2][9] + S_data_multp_imag[3][(C_DATA_WIDTH+12):10] + S_data_multp_imag[3][9] + S_data_multp_imag[4][(C_DATA_WIDTH+12):10] + S_data_multp_imag[4][9] ; end always @(posedge I_sys_clk) if((S_rd_addr[2:0] == 3'd1)&(S_cnt5_rd==1)) s_data_w25_cnt <= 5'd0; else if(&s_data_w25_cnt) s_data_w25_cnt <= s_data_w25_cnt; else s_data_w25_cnt <= s_data_w25_cnt + 'd1 ;  always @(posedge I_sys_clk) case(s_data_w25_cnt) 5'd0  : begin    S_Wn25_real <= 12'd1024;    S_Wn25_imag <= 12'd0   ; end  /// W0  25 5'd1  : begin    S_Wn25_real <= 12'd992 ;    S_Wn25_imag <=-12'd255 ; end /// W1  25 5'd2  : begin    S_Wn25_real <= 12'd897 ;    S_Wn25_imag <=-12'd493 ; end  /// W2  25 5'd3  : begin    S_Wn25_real <= 12'd946 ;    S_Wn25_imag <=-12'd701 ; end /// W3  25 5'd4  : begin    S_Wn25_real <= 12'd549 ;    S_Wn25_imag <=-12'd865 ; end  /// W4  25  5'd5  : begin    S_Wn25_real <= 12'd1024;    S_Wn25_imag <= 12'd0   ; end /// W0  25 5'd6  : begin    S_Wn25_real <= 12'd897 ;    S_Wn25_imag <=-12'd493 ; end  /// W2  25 5'd7  : begin    S_Wn25_real <= 12'd549 ;    S_Wn25_imag <=-12'd865 ; end /// W4  25 5'd8  : begin    S_Wn25_real <= 12'd64  ;    S_Wn25_imag <=-12'd1022; end  /// W6  25 5'd9  : begin    S_Wn25_real <=-12'd436 ;    S_Wn25_imag <=-12'd927 ; end /// W8  25  5'd10 : begin    S_Wn25_real <= 12'd1024;    S_Wn25_imag <= 12'd0   ; end  /// W0  25 5'd11 : begin    S_Wn25_real <= 12'd746 ;    S_Wn25_imag <=-12'd701 ; end /// W3  25 5'd12 : begin    S_Wn25_real <= 12'd64  ;    S_Wn25_imag <=-12'd1022; end  /// W6  25 5'd13 : begin    S_Wn25_real <=-12'd653 ;    S_Wn25_imag <=-12'd789 ; end /// W9  25 5'd14 : begin    S_Wn25_real <=-12'd1016;    S_Wn25_imag <=-12'd128 ; end  /// W12 25   5'd15 : begin    S_Wn25_real <= 12'd1024;    S_Wn25_imag <= 12'd0   ; end /// W0  25 5'd16 : begin    S_Wn25_real <= 12'd549 ;    S_Wn25_imag <=-12'd865 ; end  /// W4  25 5'd17 : begin    S_Wn25_real <=-12'd436 ;    S_Wn25_imag <=-12'd927 ; end /// W8  25 5'd18 : begin    S_Wn25_real <=-12'd1016;    S_Wn25_imag <=-12'd128 ; end  /// W12 25 5'd19 : begin    S_Wn25_real <=-12'd653 ;    S_Wn25_imag <= 12'd786 ; end /// W16 25 default:begin    S_Wn25_real <= 12'd1024;    S_Wn25_imag <= 12'd0   ; end /// W0  25 endcase  /// 调用复乘 delay 6clkcmult # (.AWIDTH    (C_DATA_WIDTH+3        ) , .BWIDTH    (12 ) )u1_cmult_ ( .clk       (I_sys_clk            ) , .ar        (S_data_add_real_p2   ) , .ai        (S_data_add_imag_p2   ) , .br        (S_Wn25_real          ) , .bi        (S_Wn25_imag          ) , .pr        (S_data_multw25_real  ) , .pi        (S_data_multw25_imag  )  ); always @(posedge I_sys_clk) if((s_data_w25_cnt > 5'd1) &&(s_data_w25_cnt < 5'd7)) begin S_data_out_real <= S_data_add_real_p0_d2 ; S_data_out_imag <= S_data_add_imag_p0_d2 ; end else begin S_data_out_real <= S_data_multw25_real[(C_DATA_WIDTH+12):10] + S_data_multw25_real[9];  S_data_out_imag <= S_data_multw25_imag[(C_DATA_WIDTH+12):10] + S_data_multw25_imag[9];  end  always @(posedge I_sys_clk) S_data_start_5 <= (s_data_w25_cnt == 2) || (s_data_w25_cnt == 7) || (s_data_w25_cnt == 12) || (s_data_w25_cnt == 17) || (s_data_w25_cnt == 22) ; ///delay clkcm_fft5_N5 #( .C_DATA_WITH        (C_DATA_WIDTH+3 ) )u0_cm_fft5_N5( .I_sys_clk          (I_sys_clk                          ) , /// 工作时钟 100M .I_data_start       (S_data_start_5                     ) , /// 数据开始进入标志,与第一个数据对齐输入 .I_data_in_real     (S_data_out_real                    ) , /// 数据输入,从start开始连续输入 .I_data_in_imag     (S_data_out_imag                    ) , /// 数据输入,从start开始连续输入 .O_data_start       (                                   ) , /// 数据开始输出标志与第一个数据对齐输出 .O_data_out_real    (O_data_out_real                    ) , /// 数据输出,从start开始连续输出 .O_data_out_imag    (O_data_out_imag                    ) /// 数据输出,从start开始连续输出); always @(posedge I_sys_clk) O_data_start <= (s_data_w25_cnt == 13) ;  endmodule

最后是5点FFT的倒序,输出倒序模块主要是用来实现下图中的地址转换,代码使用分布式RAM的乒乓操作,缓存两组数据信息,然后使用计数器的bit翻转达到输出倒序的目的,倒序代码和基3fft的倒序代码进本一样,这里就不再展示代码了(参考基3FFT的verilog代码实现及仿真)。

仿真TB和基2FFT(基2FFT的verilog代码实现及仿真)实现中的仿真类似同样使用python生成激励源和结果与verilog的结果做对比,得到最终输出。



声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • FPGA
  • 可编程
  • PLC
  • verilog
下载排行榜
更多
评测报告
更多
广告