最近这个项目是要通过SRIO将图像解析数据送到XILINX FPGA通过FFT处理再用SRIO传回主控,我准备用FIFO来做一个数据的缓冲池,然后按行做FFT运算,中间结果按行存入RAM中,之后按列进行FFT运算,再存入RAM,最后传入FIFO,经过SRIO传回主控。
昨天算是对FIFO有了一定了解(因为光一个fifo文档就300多页,我想一个看似简单的IP核其实想用好还真的不容易),对于本项目也够用了。今天把FIFO和FFT连在一起用了一下,各个模块搭好后,进行仿真测试,在这一过程中问题还是很多的,对于FFT参数的控制和激励一定要非常仔细,必须要一点点仿真一点点把握各个模块之间的时序关系。
接触FPGA也有半年多,其实这半年来FPGA用的也不是很多,一直断断续续的,这样真的不好。因为自己是计算机学院的学生,所以周围的师兄师姐都没有做FPGA的,基本都是自己一个人摸索吧,有些时候一个简单的问题都会让我困扰很久,也许这时候只需要一个稍微懂一点FPGA的给我一点拨也就通了,但是我想有时候只有在遇到困难才能让人真正的提高,这种提高不仅仅是知识上的,我想很多东西是说不清的。项目要一点点推进,每个环节都需要严格的仿真才能继续进行,加油,我想这个项目完成以后我一定会收获不少!
废话不多,下面把今天的一点工作进展进行下记录。这面两个模块一个是主模块,一个是地址与控制信号生成模块。这里按各个状态来描述:
1. S_IDLE状态--向FIFO传输1-256个数据(实部是1-256,虚部都是0):这里通过判断fifo_recv_full来进行状态跳转,当fifo_recv_full为高时说明256个数据已经传输完毕,跳转到S_FFT_START状态
2. S_FFT_START状态--拉高fft_start信号,以及使能FIFO的读信号fifo_rd_en信号,具体变化请看图1。这里一个关键问题就是,什么时候拉低fft_start信号,这里考虑fifo_data_count信号,我的方法是当前时钟周期fifo_data_count=2时,状态跳转到S_FFT_START_OVER,并传送倒数第二个数据;下一时钟周期s_state=S_FFT_START_OVER,并拉低fft_start,并传送最后一个数据;再下一个时候周期检测到fft_start为低,不再接收数据。具体参见图4.
最后通过MATLAB仿真结果完全正确。后面将继续实现对按行进行FFT后的数据的按列FFT。有问题的同学请留言~
主模块
module fft2d_16_top( input clk, input rst_n, input fifo_wr_en, input [63:0] srio_wr_data, output [36:0] srio_rd_data_re, output [36:0] srio_rd_data_im, output [31:0] test_re, output [31:0] test_im, output test_fft_rfd, output test_fft_dv, output [4:0] test_state ); parameter S_IDLE = 5‘h0, S_FFT_START = 5‘h1, S_FFT_START_OVER = 5‘h2; wire [4:0] s_state; /*FFT 参数*/ reg fft_start;//input reg fft_fwd_inv; reg fft_fwd_inv_we; wire fft_rfd;//output wire fft_dv; wire [3:0] fft_xn_index; wire [31:0] fft_xn_re; wire [31:0] fft_xn_im; wire [3:0] fft_xk_index; wire [31:0] fft_xk_re; wire [31:0] fft_xk_im; wire [4:0] fft_xk_re_ex; wire [4:0] fft_xk_im_ex; /*fifo recv*/ reg fifo_rd_en; wire fifo_recv_full; wire [7:0] fifo_data_count; AddrConGen addrConGen ( .clk(clk), .rst_n(rst_n), .fifo_recv_full(fifo_recv_full), .fifo_data_count(fifo_data_count), .s_state(s_state) ); fifo_i64_o64 recv_fifo ( .clk(clk), // input clk .rst(~rst_n), // input rst .din(srio_wr_data), // input [63 : 0] din .wr_en(fifo_wr_en), // input wr_en .rd_en(fifo_rd_en), // input rd_en .dout({fft_xn_re,fft_xn_im}), // output [63 : 0] dout .full(fifo_recv_full), // output full .almost_full(), // output almost_full .empty(), // output empty .almost_empty(), // output almost_empty .data_count(fifo_data_count) // output [7 : 0] data_count ); fft16 xfft16 ( .clk(clk), // input clk .start(fft_start), // input start .xn_re(fft_xn_re), // input [31 : 0] xn_re .xn_im(fft_xn_im), // input [31 : 0] xn_im .fwd_inv(fft_fwd_inv), // input fwd_inv .fwd_inv_we(fft_fwd_inv_we), // input fwd_inv_we .rfd(fft_rfd), // output rfd .xn_index(fft_xn_index), // output [3 : 0] xn_index .busy(), // output busy .edone(), // output edone .done(), // output done .dv(fft_dv), // output dv .xk_index(fft_xk_index), // output [3 : 0] xk_index .xk_re(srio_rd_data_re), // output [36 : 0] xk_re .xk_im(srio_rd_data_im) // output [36 : 0] xk_im ); always @(posedge clk) begin if(~rst_n) begin fft_start <= 0; fft_fwd_inv <= 0; fft_fwd_inv_we <= 0; fifo_rd_en <= 0; end else case(s_state) S_IDLE: begin end S_FFT_START:begin fft_start <= 1; fft_fwd_inv <= 1; fft_fwd_inv_we <= 1; fifo_rd_en <= 1; end S_FFT_START_OVER: begin fft_start <= 0; fft_fwd_inv <= 0; fft_fwd_inv_we <= 0; fifo_rd_en <= 1; end endcase end assign test_state = s_state; //assign srio_rd_data_re = fft_xk_re; //assign srio_rd_data_re = fft_xk_im; assign test_re = fft_xn_re; assign test_im = fft_xn_im; assign test_fft_rfd = fft_rfd; assign test_fft_dv = fft_dv; endmodule
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 20:40:06 02/14/2014 // Design Name: // Module Name: AddrConGen // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module AddrConGen( input clk, input rst_n, input fifo_recv_full, input [7:0] fifo_data_count, output reg [4:0] s_state ); reg [4:0] c_state; parameter S_IDLE = 5‘h0, S_FFT_START = 5‘h1, S_FFT_START_OVER = 5‘h2; parameter C_IDLE = 5‘h0, C_FFT_START = 5‘h1, C_FFT_START_OVER = 5‘h2, C_FFT_DV = 5‘h3; always @(posedge clk) begin if(~rst_n) begin s_state <= S_IDLE; c_state <= C_IDLE; end else case(c_state) C_IDLE: begin s_state <= S_IDLE; c_state <= C_FFT_START; end C_FFT_START:begin if(fifo_recv_full) begin s_state <= S_FFT_START; c_state <= C_FFT_START_OVER; end end C_FFT_START_OVER: begin if(fifo_data_count==2) begin s_state <= S_FFT_START_OVER; c_state <= C_FFT_DV; end end endcase end endmodule
仿真图:
原文:http://blog.csdn.net/taoqick/article/details/19246441