您现在的位置是:首页 >技术教程 >Vivdao FFT IP核调试记录网站首页技术教程

Vivdao FFT IP核调试记录

yundanfengqing_nuc 2023-05-24 04:00:02
简介Vivdao FFT IP核调试记录

       最近一时兴起,看了下Vivado版本下的FFT  IP核,发现和ISE版本下的FFT IP核有一些差别,貌似还不小。做了个简单的仿真,Vivado仿真结果竟然和Matlab仿真结果对不上,废了九牛二虎之力研究datasheet、做仿真,终于使两个仿真结果对上了!着实花费了我不少脑细胞,也再一次证明了我不适合做算法(虽然总想证明一下自己可以的),还是老老实实做好我的FPGA工程师吧!至于算法的事情还是交给那些脑细胞发达的同仁们。

         最开始我也是在网上找了不少例程,自己照着做的仿真,无一例外,Vivado仿真结果和Matlab仿真结果都对不上。然后各种怀疑,各种看时序,翻看信号与系统的书本,都没找到答案。但是我真的很想知道为什么,在求知欲的催促下最后还舔着脸皮问了几个朋友,有的现在不做算法了所以没有时间和精力专门帮我看问题,有的没有做过FFT,有的做过了给我讲了一下,也许问题太简单了,他们说的太过于精简,我也听得马马虎虎,最后还是不知道原因。放了几天之后,我就做了一个最简单的8点[0 1 2 3 4 5 6 7]FFT变换,结果竟然和matlab仿真结果对上了。下面给出FFT IP核配置以及相关代码。

       一开始怀疑config接口配置完成后,会不会有个生效时间,所以还特意在代码里做了处理,后来证实根本没有影响,这个问题也在pg109的pg58页找到了答案,只要给好s_axis_data_tlast       信号就OK。

module top(
    input I_clk,
    input I_rst,
    output O_valid,
    output [23:0] O_re,
    output [23:0] O_im

);


wire [7 : 0]  s_axis_config_tdata        ;
reg           s_axis_config_tvalid       ;
wire          s_axis_config_tready       ;
wire [31 : 0] s_axis_data_tdata          ;
reg           s_axis_data_tvalid         ;
wire          s_axis_data_tready         ;
wire          s_axis_data_tlast             ;
wire [47 : 0] m_axis_data_tdata          ;
wire [7 : 0]  m_axis_data_tuser             ;
wire          m_axis_data_tvalid         ;
wire          m_axis_data_tready         ;
wire          m_axis_data_tlast             ;
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;    
assign        m_axis_data_tready = 1;

reg  [7:0]    S_cnt;
reg           s_axis_config_tvalid_d1;
reg           S_flag;
    
always @ (posedge I_clk)    
begin
    if(I_rst)
        s_axis_config_tvalid <= 1'b0;
    else if(s_axis_config_tready)
        s_axis_config_tvalid <= 1'b1;
    else 
        s_axis_config_tvalid <= 1'b0;
end

assign s_axis_config_tdata = 8'd1;


always @ (posedge I_clk)    
begin
    if(I_rst)
        s_axis_config_tvalid_d1 <= 1'b0; 
    else 
        s_axis_config_tvalid_d1 <= s_axis_config_tvalid;
end

always @ (posedge I_clk)    
begin
    if(I_rst)
        S_flag <= 1'b0;
    else if({s_axis_config_tvalid_d1,s_axis_config_tvalid} == 2'b10)
        S_flag <= 1'b1;
end


always @ (posedge I_clk)    
begin
    if(I_rst)
        s_axis_data_tvalid <= 1'b0;
    else if(s_axis_data_tready&&S_flag)
        s_axis_data_tvalid <= 1'b1;
    else 
        s_axis_data_tvalid <= 1'b0;
end

always @ (posedge I_clk)    
begin
    if(I_rst)
        S_cnt <= 'd0;
    else if(s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==7))
        S_cnt <= 'd0;
    else if(s_axis_data_tready&&s_axis_data_tvalid)
        S_cnt <= S_cnt + 1;
end

assign s_axis_data_tlast = (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==7))?1'b1:1'b0;
assign s_axis_data_tdata = (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==0))?0:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==1))?1:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==2))?2:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==3))?3:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==4))?4:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==5))?5:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==6))?6:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==7))?7:0;
    
xfft_0 xfft_0_inst (
  .aclk                       (I_clk                        ),                                                // input wire aclk
  .aresetn                    (!I_rst                       ), 
  .s_axis_config_tdata        (s_axis_config_tdata          ), // input  wire [7 : 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          (s_axis_data_tdata            ), // 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 [47 : 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        (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
);
    

assign O_valid = (m_axis_data_tvalid&&m_axis_data_tready)?1'b1:1'b0;
assign O_re = m_axis_data_tdata[23:0];
assign O_im = m_axis_data_tdata[47:24];
    
endmodule

仿真结果如下所示,和matlab结果一致。

 

至此,得出如下结论:

(1)首先要确保送给IP核进行傅里叶变换的数是正确的(正整数好像没啥区别,负整数的时候需要做补码转换,如果转换错误则输入给IP核的数据区别好大)。

(2)其次控制好s_axis_data_tlast信号,在仿真过程中 

event_tlast_unexpected信号和 event_tlast_missing信号一直为低电平。 

(3)event_frame_started信号为一个时钟周期的脉冲信号,它并没有和每一帧数据的第一个数对齐,和输入数据没有任何对齐关系。           

后面我又将[0 1 2 3 4 5 6 7]这组数据换成了[0 -1 -2 -3 -4 -5 -6 -7]做了fft变换。Vivado仿真结果都和matlab仿真结果一致。具体代码如下所示。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。