搜索
bottom↓
回复: 89

换一种心态来发一篇关于用FPGA实现FFT的帖子

[复制链接]

出0入0汤圆

发表于 2011-8-4 20:37:37 | 显示全部楼层 |阅读模式
最近在学习用FFT实现FPGA变化,看了user guide,也看了很多网上各家朋友的资料,在这个过程我,我发现我们论坛在这方面内容不是很多,而由一种现象就是,很多帖子都是很多新手在遇到问题时发的求救贴,大呼什么跪求什么资料啊,跪等高手解决之类的,以前我呀发过这种贴,但是后来我发现这种贴最终一般自己收获的东西也很少,浏览帖子的人收获的也很少,所以今天我想换一种心态来发一篇帖子,这不是求救贴,而是希望为论坛里的人,有经验的也会,菜鸟也罢,提供一个交流得窝,再说了,哪个高手不是从菜鸟变来的,所以这里没有蔑视,没有对错,只有交流!!!

    自己接触FPGA也零零散散差不多半年了,当初只是为了做一个PSD四象限光斑位置探测系统,里面要用到FPGA去控制AD转换芯片和USB接口芯片,所以就学习了FPGA,因为我不是电子类专业的,所以周围基本没有搞FPGA得,说实话,一个人摸索,从前面的运算电路设计,到AD转换,到FPGA,到EZ-USB传输,到MFC编程,半年前,我真的有些闻所未闻,有些只在书上见过,到现在自己差不多完成了这个系统,真的够艰苦的。哪怕,就像个Quartus软件,我想要是有个会用的人指点一下,一两个周就会用了,但是我自己一点一点啃,靠得是坚持。从VHDL(Verilog)到NIOS,反正自己的信念就是趁年轻的时候多学点东西,以希望下面的这个话题,经验之士不吝赐教,不懂之人洗耳恭听,大家一起的目的就是交流,就是让论坛真的成为一个五湖四海的兄弟姐妹们学习的圣地。

    结束那个PSD系统之后,又有一个新想法,就是想用FPGA做图像处理,实现一些较复杂的算法,FFT(快速傅里叶变换)就是其中很重要的一种,于是自己开始去学习了一段时间,现在把自己的过程和想法罗列在下面:

一、当今在电子系统中实现FFT算法的途径大致有:
   1、DSP芯片:其实,到目前为止,DSP芯片仍然是最重要的实现复杂算法的芯片,但是其电路复杂,而且速度问题一直是它致命的瓶颈,当然,FFT对于DSP来说,已经比较成熟了,所以也正因为这样,我想用FPGA来挑战一下自己。
   2、FPGA芯片:近好几年,FPGA真正崛起了,尤其Xlinx和ALTERA公司的FPGA也能实现一些复杂的算法,它的特点就是速度比DSP快很多,由于我接触的是Atera公司的产品,所以我主要谈论它。用Atera公司的FPGA芯片实现FFT也有两个途径:
    (1)用NIOS软核,自己构架一个FFT系统,分模块用C语言编程实现。
    (2)直接使用Atera公司的FFT IP核,这是一个高效的FFT变换模块。

二、我想用FPGA来实现FFT,所以当然要嘛就是用NIOS软核,用C编程,要嘛就是用FFT IP核,关于如何选择,这里我还想请教大家:
         NIOS软核实现较直接用现成的IP核当然要复杂许多,但是我想知道的关键是NIOS软核实现的速度会不会比FFT IP核的速度慢很多,因为我做这个FFT的首要目标就是快速,但是这个疑惑我至今都不是很清楚。

三、这几天,研究了下FFT IP核,但一直没有仿真成功,这个学习的过程我大致给大家说一下:
       1、看了FFT的user guide,了解FFT IP的工作时序。
       2、学习了NIOS系统,由于之前我的PSD系统才刚接触FPGA,而且那个要用到的都是简单的VHDL语言编写的整个程序,没有涉及NIOS系统,所以自己决定学习它,什么不会就学什么,为以后做准备,学习的是《NIOS 那些事》。
       3、开始仿真FFT IPcore,前面已经基本知道了它的工作时序,由于它工作时需要激励的,所以要涉及Modelsim仿真,以前也只是用一下Quartus自带的仿真,所以又为此下载破_解Modelsim SE 6.5g,一副准备要大干一场的气势,准备把这个FFT IPCore仿真出来。
       4、后来又知道,Modelsim仿真Quartus工程,有两种方法,一是在Quartus里面调用Modelsim,二是把Quartus编译生成的一些文件拷贝到Modelsim工程目录下,然后编译仿真库,进行仿真。关于这两种仿真我分别找到了两篇网上的文章:
       一是关于Modelsim里面仿真的:http://blog.ednchina.com/liuchang5772/283677/message.aspx
       一是在Quartus里面调用Modelsim的:点击此处下载 ourdev_664257NY4PEN.rar(文件大小:292K) (原文件名:Quartus中fft_ip_core的使用.rar)
         5、当然,网上还有很多这些文章,但是都是他们做成功了,但是留下来的却是新手们没法直接使用的经验,就像4里我讲的简单的过程,我没仿真成功,但我也能说出这个实现的过程。这两篇相对好点。
         6、话说,我就照着这两篇帖子去做了,两个仿真都试了,都没成:
          (1)第一个网站里面的内容,着重于去讲过程,而实现的细节忽略了,他把看文章的人都当成了高手,呵呵,比如里面的编译库就折腾了我老半天,当这些问题都解决了之后,最后还是仿真得一塌糊涂,得不到结果。我把工程附在下面:
            点击此处下载 ourdev_664263BX0STT.rar(文件大小:3.71M) (原文件名:Modelsim.rar)
           (2)第二种方式,我也看懂了,他有三个vhdl文件,一个是为fft ip核(fft_burst)提供控制信号的模块,即ctrl_fft,主要是通过一个clk时钟和reset_n复位信号以及fft_burst产生的应答信号sink_ready,从而产生sink_sop,sink_eop,sink_valid时序。顶层模块是fft256,它主要是例化ctrl_fft和fft_burst模块成一个顶层模块,即fft256模块,封装好后的输入信号有clk,reset_n,sink_real,输出信号有sink_valid,sink_sop,sink_eop,sink_real,sink_ready,source_error,source_sop,source_eop,source_valid,source_exp,source_real,source_imag。而还有一个fft256_vhd_tst.vhd文件,这个文件是供Modelsim仿真用的,它的作用是给fft256模块三个输入信号产生激励,clk为10MHZ时钟,reset_n为复位信号,sink_real是一个128个时钟周期改变一次的供转换的数据的实部。
            然而篇文档,讲到仿真就戛然而止了,貌似认为就成功了,然后对于想对modelsim还不熟练的人来说,其实还离成功差点距离。每次仿真都有如下警告: ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
#    Time: 0 ns  Iteration: 2  Instance: /fft256/u1/n1oiol
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
#    Time: 0 ns  Iteration: 2  Instance: /fft256/u1/n1oilo
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
#    Time: 0 ns  Iteration: 2  Instance: /fft256/u1/n1oilo
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
#    Time: 0 ns  Iteration: 2  Instance: /fft256/u1/n1oioo
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    后来查阅了说是modelsim仿真和quartus仿真不一样,需要为信号赋上初值,我特意为此又冲新分析了一下那三个vhdl程序,理清了他们的关系,把自己认为应该赋初值都赋上了,可反反复复修改很多遍,还是没有仿真成功,这些警告依然存在,仿真也得不到结果。

      最后,我想说的是,我只是想以此引出这个话题,希望大家就这个用FPGA实现FFT的话题,踊跃发言,不要忽略实现过程中的细节,因为来学习的毕竟都是才接触FPGA不久的。
       真心希望这个论坛能更活跃,呵呵。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2011-8-4 20:41:59 | 显示全部楼层
顶 虽然走的是不同方向,也是这么过来的

出0入0汤圆

发表于 2011-8-4 20:50:36 | 显示全部楼层
---

出0入0汤圆

发表于 2011-8-4 20:57:43 | 显示全部楼层
个人觉得在用FPGA实现FFT之前,先复习下数字信号分析基础内容
例如DFT等等的

出0入0汤圆

发表于 2011-8-4 21:13:38 | 显示全部楼层
点击此处下载 ourdev_664278XLOK5M.rar(文件大小:4.70M) (原文件名:fft8_copy.rar)

这是我一年前自己写的一个8点FFT,因为当时时间不是很多,自己从头到尾的进行摸索,主要是理论感觉不是很好理解,然后就找了大把参考书,弄懂了理论之后才去动手写代码,参考网上的一些例子,终于还是给我成功了,虽然弄的是比较简单的,代码也比较不简洁,所有都放在一个文件了,很不好的习惯,但起码也是完成了,之后就没进一步深入研究了,
希望这个小小资料能给需要的人一点点的帮助,哪怕很渺小
module fft8 ( r_in,i_in,r_out,i_out,clk,rst_n );

input [15:0]    r_in,i_in;
input           clk,rst_n;
output [15:0]   r_out,i_out;

reg [15:0]   r_out,i_out;
reg [15:0]   r0_in_reg[7:0],i0_in_reg[7:0];
reg [15:0]   r1_in_reg[7:0],i1_in_reg[7:0];
reg [15:0]   r2_in_reg[7:0],i2_in_reg[7:0];

wire [15:0]   r0_out_reg[7:0],i0_out_reg[7:0];
wire [15:0]   r1_out_reg[7:0],i1_out_reg[7:0];
wire [15:0]   r2_out_reg[7:0],i2_out_reg[7:0];

wire [15:0]   r0_out_reg55,r0_out_reg77;
wire [15:0]   i0_out_reg55,i0_out_reg77;

integer k0,k1,k2;
reg [5:0]   count;
reg [4:0]   count_in;

//////////////////////////////////////////////////////////////////////////////////////////////////STATE0
lpm_add_sub0 r0_0(.add_sub(1'b1),.dataa(r0_in_reg[0]),.datab(r0_in_reg[4]),.result(r0_out_reg[0]));
lpm_add_sub0 r0_1(.add_sub(1'b1),.dataa(r0_in_reg[1]),.datab(r0_in_reg[5]),.result(r0_out_reg[1]));
lpm_add_sub0 r0_2(.add_sub(1'b1),.dataa(r0_in_reg[2]),.datab(r0_in_reg[6]),.result(r0_out_reg[2]));
lpm_add_sub0 r0_3(.add_sub(1'b1),.dataa(r0_in_reg[3]),.datab(r0_in_reg[7]),.result(r0_out_reg[3]));
lpm_add_sub0 r0_4(.add_sub(1'b0),.dataa(r0_in_reg[0]),.datab(r0_in_reg[4]),.result(r0_out_reg[4]));
lpm_add_sub0 r0_5(.add_sub(1'b0),.dataa(r0_in_reg[1]),.datab(r0_in_reg[5]),.result(r0_out_reg[5]));
lpm_add_sub0 r0_6(.add_sub(1'b0),.dataa(r0_in_reg[2]),.datab(r0_in_reg[6]),.result(r0_out_reg[6]));
lpm_add_sub0 r0_7(.add_sub(1'b0),.dataa(r0_in_reg[3]),.datab(r0_in_reg[7]),.result(r0_out_reg[7]));
lpm_add_sub0 r0_55(.add_sub(1'b1),.dataa(shift07(r0_out_reg[5])),.datab(shift07(i0_out_reg[5])),.result(r0_out_reg55));
lpm_add_sub0 r0_77(.add_sub(1'b0),.dataa(shift07(i0_out_reg[7])),.datab(shift07(r0_out_reg[7])),.result(r0_out_reg77));

lpm_add_sub0 i0_0(.add_sub(1'b1),.dataa(i0_in_reg[0]),.datab(i0_in_reg[4]),.result(i0_out_reg[0]));
lpm_add_sub0 i0_1(.add_sub(1'b1),.dataa(i0_in_reg[1]),.datab(i0_in_reg[5]),.result(i0_out_reg[1]));
lpm_add_sub0 i0_2(.add_sub(1'b1),.dataa(i0_in_reg[2]),.datab(i0_in_reg[6]),.result(i0_out_reg[2]));
lpm_add_sub0 i0_3(.add_sub(1'b1),.dataa(i0_in_reg[3]),.datab(i0_in_reg[7]),.result(i0_out_reg[3]));
lpm_add_sub0 i0_4(.add_sub(1'b0),.dataa(i0_in_reg[0]),.datab(i0_in_reg[4]),.result(i0_out_reg[4]));
lpm_add_sub0 i0_5(.add_sub(1'b0),.dataa(i0_in_reg[1]),.datab(i0_in_reg[5]),.result(i0_out_reg[5]));
lpm_add_sub0 i0_6(.add_sub(1'b0),.dataa(i0_in_reg[2]),.datab(i0_in_reg[6]),.result(i0_out_reg[6]));
lpm_add_sub0 i0_7(.add_sub(1'b0),.dataa(i0_in_reg[3]),.datab(i0_in_reg[7]),.result(i0_out_reg[7]));
lpm_add_sub0 i0_55(.add_sub(1'b0),.dataa(shift07(i0_in_reg[5])),.datab(shift07(r0_in_reg[5])),.result(i0_out_reg55));
lpm_add_sub0 i0_77(.add_sub(1'b1),.dataa(shift07(r0_in_reg[7])),.datab(shift07(i0_in_reg[7])),.result(i0_out_reg77));
/////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////////STATE1
lpm_add_sub0 r1_0(.add_sub(1'b1),.dataa(r1_in_reg[0]),.datab(r1_in_reg[2]),.result(r1_out_reg[0]));
lpm_add_sub0 r1_1(.add_sub(1'b1),.dataa(r1_in_reg[1]),.datab(r1_in_reg[3]),.result(r1_out_reg[1]));
lpm_add_sub0 r1_2(.add_sub(1'b0),.dataa(r1_in_reg[0]),.datab(r1_in_reg[2]),.result(r1_out_reg[2]));
lpm_add_sub0 r1_3(.add_sub(1'b0),.dataa(r1_in_reg[1]),.datab(r1_in_reg[3]),.result(r1_out_reg[3]));
lpm_add_sub0 r1_4(.add_sub(1'b1),.dataa(r1_in_reg[4]),.datab(r1_in_reg[6]),.result(r1_out_reg[4]));
lpm_add_sub0 r1_5(.add_sub(1'b1),.dataa(r1_in_reg[5]),.datab(r1_in_reg[7]),.result(r1_out_reg[5]));
lpm_add_sub0 r1_6(.add_sub(1'b0),.dataa(r1_in_reg[4]),.datab(r1_in_reg[6]),.result(r1_out_reg[6]));
lpm_add_sub0 r1_7(.add_sub(1'b0),.dataa(r1_in_reg[5]),.datab(r1_in_reg[7]),.result(r1_out_reg[7]));

lpm_add_sub0 i1_0(.add_sub(1'b1),.dataa(i1_in_reg[0]),.datab(i1_in_reg[2]),.result(i1_out_reg[0]));
lpm_add_sub0 i1_1(.add_sub(1'b1),.dataa(i1_in_reg[1]),.datab(i1_in_reg[3]),.result(i1_out_reg[1]));
lpm_add_sub0 i1_2(.add_sub(1'b0),.dataa(i1_in_reg[0]),.datab(i1_in_reg[2]),.result(i1_out_reg[2]));
lpm_add_sub0 i1_3(.add_sub(1'b0),.dataa(i1_in_reg[1]),.datab(i1_in_reg[3]),.result(i1_out_reg[3]));
lpm_add_sub0 i1_4(.add_sub(1'b1),.dataa(i1_in_reg[4]),.datab(i1_in_reg[6]),.result(i1_out_reg[4]));
lpm_add_sub0 i1_5(.add_sub(1'b1),.dataa(i1_in_reg[5]),.datab(i1_in_reg[7]),.result(i1_out_reg[5]));
lpm_add_sub0 i1_6(.add_sub(1'b0),.dataa(i1_in_reg[4]),.datab(i1_in_reg[6]),.result(i1_out_reg[6]));
lpm_add_sub0 i1_7(.add_sub(1'b0),.dataa(i1_in_reg[5]),.datab(i1_in_reg[7]),.result(i1_out_reg[7]));
/////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////////STATE2
lpm_add_sub0 r2_0(.add_sub(1'b1),.dataa(r2_in_reg[0]),.datab(r2_in_reg[1]),.result(r2_out_reg[0]));
lpm_add_sub0 r2_1(.add_sub(1'b0),.dataa(r2_in_reg[0]),.datab(r2_in_reg[1]),.result(r2_out_reg[1]));
lpm_add_sub0 r2_2(.add_sub(1'b1),.dataa(r2_in_reg[2]),.datab(r2_in_reg[3]),.result(r2_out_reg[2]));
lpm_add_sub0 r2_3(.add_sub(1'b0),.dataa(r2_in_reg[2]),.datab(r2_in_reg[3]),.result(r2_out_reg[3]));
lpm_add_sub0 r2_4(.add_sub(1'b1),.dataa(r2_in_reg[4]),.datab(r2_in_reg[5]),.result(r2_out_reg[4]));
lpm_add_sub0 r2_5(.add_sub(1'b0),.dataa(r2_in_reg[4]),.datab(r2_in_reg[5]),.result(r2_out_reg[5]));
lpm_add_sub0 r2_6(.add_sub(1'b1),.dataa(r2_in_reg[6]),.datab(r2_in_reg[7]),.result(r2_out_reg[6]));
lpm_add_sub0 r2_7(.add_sub(1'b0),.dataa(r2_in_reg[6]),.datab(r2_in_reg[7]),.result(r2_out_reg[7]));

lpm_add_sub0 i2_0(.add_sub(1'b1),.dataa(i2_in_reg[0]),.datab(i2_in_reg[1]),.result(i2_out_reg[0]));
lpm_add_sub0 i2_1(.add_sub(1'b0),.dataa(i2_in_reg[0]),.datab(i2_in_reg[1]),.result(i2_out_reg[1]));
lpm_add_sub0 i2_2(.add_sub(1'b1),.dataa(i2_in_reg[2]),.datab(i2_in_reg[3]),.result(i2_out_reg[2]));
lpm_add_sub0 i2_3(.add_sub(1'b0),.dataa(i2_in_reg[2]),.datab(i2_in_reg[3]),.result(i2_out_reg[3]));
lpm_add_sub0 i2_4(.add_sub(1'b1),.dataa(i2_in_reg[4]),.datab(i2_in_reg[5]),.result(i2_out_reg[4]));
lpm_add_sub0 i2_5(.add_sub(1'b0),.dataa(i2_in_reg[4]),.datab(i2_in_reg[5]),.result(i2_out_reg[5]));
lpm_add_sub0 i2_6(.add_sub(1'b1),.dataa(i2_in_reg[6]),.datab(i2_in_reg[7]),.result(i2_out_reg[6]));
lpm_add_sub0 i2_7(.add_sub(1'b0),.dataa(i2_in_reg[6]),.datab(i2_in_reg[7]),.result(i2_out_reg[7]));
/////////////////////////////////////////////////////////////////////////////////////////////////////




function[15:0] shift07;//乘以0.7071
input [15:0] xn;
begin
      shift07={xn[15],xn[15:1]}+ {xn[15], xn[15], xn[15],xn[15:3]}
             + {xn[15], xn[15], xn[15], xn[15], xn[15:4]}
             + {xn[15], xn[15], xn[15], xn[15], xn[15], xn[15], xn[15:6]}
             + {xn[15], xn[15], xn[15], xn[15], xn[15], xn[15],
             xn[15], xn[15],xn[15:8]}+{xn[15], xn[15], xn[15], xn[15],
             xn[15], xn[15], xn[15], xn[15], xn[15], xn[15],
             xn[15], xn[15], xn[15], xn[15],xn[15:14]};
end
endfunction


always @ ( posedge clk or negedge rst_n ) begin
   if ( !rst_n )
      count <= 6'b0;
   else if ( count==6'd39 )
      count <= 6'b0;
   else
      count <= count + 1'b1;
   
end

always @ ( posedge clk or negedge rst_n ) begin
   if ( !rst_n )
      count_in <= 5'b0;
   else if ( count_in==5'd31 )
      count_in <= 5'b0;
   else
      count_in <= count_in + 1'b1;
   
end

always @ ( posedge clk or negedge rst_n ) begin    //data_in
   if ( !rst_n )
      for (k0=0;k0<=7;k0=k0+1) begin
          r0_in_reg[k0] <= 16'b0;
          i0_in_reg[k0] <= 16'b0;
          end
   else if(count_in<=7)
      begin
      r0_in_reg[count_in] <= r_in;
      i0_in_reg[count_in] <= i_in;
      end
end




always @ ( posedge clk or negedge rst_n ) begin    //control
   if ( !rst_n ) begin
      r_out <= 0;
      i_out <= 0;
      end
   else
      case ( count )
/////////////////////////////////////////////////////////DATA_IN     
/*     6'd0: begin
         r0_in_reg[0] <= r_in;
         i0_in_reg[0] <= i_in;
         end
      6'd1: begin
         r0_in_reg[1] <= r_in;
         i0_in_reg[1] <= i_in;
         end
      6'd2: begin
         r0_in_reg[2] <= r_in;
         i0_in_reg[2] <= i_in;
         end
      6'd3: begin
         r0_in_reg[3] <= r_in;
         i0_in_reg[3] <= i_in;
         end
      6'd4: begin
         r0_in_reg[4] <= r_in;
         i0_in_reg[4] <= i_in;
         end
      6'd5: begin
         r0_in_reg[5] <= r_in;
         i0_in_reg[5] <= i_in;
         end
      6'd6: begin
         r0_in_reg[6] <= r_in;
         i0_in_reg[6] <= i_in;
         end
      6'd7: begin
         r0_in_reg[7] <= r_in;
         i0_in_reg[7] <= i_in;
         end
*/
//////////////////////////////////////////////////////////STATE0
      6'd8: begin
         r1_in_reg[0] <= r0_out_reg[0];
         i1_in_reg[0] <= i0_out_reg[0];
         end
      6'd9: begin
         r1_in_reg[1] <= r0_out_reg[1];
         i1_in_reg[1] <= i0_out_reg[1];
         end
      6'd10: begin
         r1_in_reg[2] <= r0_out_reg[2];
         i1_in_reg[2] <= i0_out_reg[2];
         end
      6'd11: begin
         r1_in_reg[3] <= r0_out_reg[3];
         i1_in_reg[3] <= i0_out_reg[3];
         end
      6'd12: begin
         r1_in_reg[4] <= r0_out_reg[4];
         i1_in_reg[4] <= i0_out_reg[4];
         end
      6'd13: begin
         r1_in_reg[5] <= r0_out_reg55;
         i1_in_reg[5] <= i0_out_reg55;
         end
      6'd14: begin
         r1_in_reg[6] <= i0_out_reg[6];
         i1_in_reg[6] <= {~r0_out_reg[6]+1};
         end
      6'd15: begin
         r1_in_reg[7] <= r0_out_reg77;
         i1_in_reg[7] <= ~i0_out_reg77;//////////////
         end
//////////////////////////////////////////////////////////////STATE1              
      6'd16: begin
         r2_in_reg[0] <= r1_out_reg[0];
         i2_in_reg[0] <= i1_out_reg[0];
         end
      6'd17: begin
         r2_in_reg[1] <= r1_out_reg[1];
         i2_in_reg[1] <= i1_out_reg[1];
         end
      6'd18: begin
         r2_in_reg[2] <= r1_out_reg[2];
         i2_in_reg[2] <= i1_out_reg[2];
         end
      6'd19: begin
         r2_in_reg[3] <= i1_out_reg[3];
         i2_in_reg[3] <= {~r1_out_reg[3]+1};
         end
      6'd20: begin
         r2_in_reg[4] <= r1_out_reg[4];
         i2_in_reg[4] <= i1_out_reg[4];
         end
      6'd21: begin
         r2_in_reg[5] <= r1_out_reg[5];
         i2_in_reg[5] <= i1_out_reg[5];
         end
      6'd22: begin
         r2_in_reg[6] <= r1_out_reg[6];
         i2_in_reg[6] <= i1_out_reg[6];
         end
      6'd23: begin
         r2_in_reg[7] <= i1_out_reg[7];
         i2_in_reg[7] <= {~r1_out_reg[7]+1};
         end
///////////////////////////////////////////////////////////////////STATE2        
      6'd24: begin
         r_out <= r2_out_reg[0];
         i_out <= i2_out_reg[0];
         end
      6'd25: begin
         r_out <= r2_out_reg[4];
         i_out <= i2_out_reg[4];
         end  
      6'd26: begin
         r_out <= r2_out_reg[2];
         i_out <= i2_out_reg[2];
         end
      6'd27: begin
         r_out <= r2_out_reg[6];
         i_out <= i2_out_reg[6];
         end
      6'd28: begin
         r_out <= r2_out_reg[1];
         i_out <= i2_out_reg[1];
         end
      6'd29: begin
         r_out <= r2_out_reg[5];
         i_out <= i2_out_reg[5];
         end
      6'd30: begin
         r_out <= r2_out_reg[3];
         i_out <= i2_out_reg[3];
         end
      6'd31: begin
         r_out <= r2_out_reg[7];
         i_out <= i2_out_reg[7];
         end           
      default: begin
         r_out <= 16'b0;
         i_out <= 16'b0;
         end
        
   endcase
end
endmodule

出0入0汤圆

 楼主| 发表于 2011-8-4 21:29:28 | 显示全部楼层
回复【3楼】qwerttt
-----------------------------------------------------------------------

呵呵,楼上说得是,我刚学了这些课程,呵呵

出0入0汤圆

 楼主| 发表于 2011-8-4 21:32:07 | 显示全部楼层
回复【4楼】maqingbiao
-----------------------------------------------------------------------

谢谢这位兄弟了,这么热心,我都说了,呵呵,贵在交流。这个程序你是在什么芯片里面实现的,呵呵,好像没用到NIOS,也没用IP核,呵呵,自己写的,自己动手,丰衣足食,呵呵。

出0入0汤圆

 楼主| 发表于 2011-8-4 21:35:58 | 显示全部楼层
回复【5楼】dltyy
-----------------------------------------------------------------------

不过确实,搞这些首先要点FFT方面的专业知识,这个才是实,而这些工程都是把理论转化成实践,只有理论弄懂了,实践才有意义。

出0入0汤圆

发表于 2011-8-4 21:52:30 | 显示全部楼层
回复【6楼】dltyy
-----------------------------------------------------------------------
这是个很简单的实例而已   都是Verilog 完成的啊   单独的FFT实现过程而已  没应用,也没做好接口,就仅仅是完成算法那部分

出0入0汤圆

发表于 2011-8-4 22:16:45 | 显示全部楼层
记号!

出0入0汤圆

 楼主| 发表于 2011-8-4 22:35:10 | 显示全部楼层
回复【8楼】maqingbiao
-----------------------------------------------------------------------

好的,我一定会好好看的。呵呵

出0入0汤圆

发表于 2011-8-4 22:40:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-4 22:53:58 | 显示全部楼层
马克思

出0入0汤圆

发表于 2011-8-4 23:08:53 | 显示全部楼层
mark!

出0入0汤圆

 楼主| 发表于 2011-8-4 23:19:30 | 显示全部楼层
希望明天能有更多的人来交流,提问题的,回答问题的,分享经验与成果的。

出0入0汤圆

 楼主| 发表于 2011-8-5 11:13:46 | 显示全部楼层
我继续发一点:
           昨天着重说的是IP 核的方法,今天说一下NIOS的方法。
1、我昨天问了一个问题,问是不是NIOS的方法比用现成的IPcore慢,我想这是当然的,但是并不意味着NIOS就不好,NIOS也可以通过用户定制指令的办法来将比较耗费时间的FFT变换种的复数乘法,加法等算法用hdl语言在quartus中编写模块来实现,然后定制成指令,在NIOS中调用,就相当于C语言中的子函数一样,既方便,又加快了执行速度。

       我不想这个贴就沉了,希望有经验的人把自己做过的经验给新人们分享分享!

出0入0汤圆

发表于 2011-8-5 12:49:58 | 显示全部楼层
这个帖子,xilinx的片子,硬件FFT,用了MicroBlaze控制,带VGA显示波形与FFT结果的,楼主可以看下。。。
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4934068&bbs_page_no=1&bbs_id=1029

出0入0汤圆

发表于 2011-8-5 12:54:15 | 显示全部楼层
没做过,帮顶。

出0入0汤圆

 楼主| 发表于 2011-8-5 13:52:31 | 显示全部楼层
回复【16楼】sdu1028
-----------------------------------------------------------------------

谢了。

出0入0汤圆

发表于 2011-8-5 14:54:59 | 显示全部楼层
多谢楼主的文章, 学习了。

出0入0汤圆

发表于 2011-8-5 15:09:23 | 显示全部楼层
IP核我也仿真过,好是好,只是串行的。

出0入0汤圆

 楼主| 发表于 2011-8-5 21:05:05 | 显示全部楼层
回复【20楼】02013063
-----------------------------------------------------------------------

你用的什么仿真,工程还在吗?能不能介绍一下。

出0入0汤圆

发表于 2011-8-5 21:19:29 | 显示全部楼层
jihao

出0入0汤圆

发表于 2011-8-5 22:28:49 | 显示全部楼层
回复【21楼】dltyy
-----------------------------------------------------------------------


那都是好久前的事了。
当时我用Quartus自带的仿真器仿真的,没用modelsim
后来方案改动,用IP核的方案被否定了。
关键是表示开始和结束俩个信号要对准了,应该就没啥问题。

出0入0汤圆

 楼主| 发表于 2011-8-5 22:57:18 | 显示全部楼层
回复【23楼】02013063
-----------------------------------------------------------------------

自带的IP核为什么被否了呢?那后来你们用的什么实现的?

出0入0汤圆

发表于 2011-8-6 09:45:46 | 显示全部楼层
回复【24楼】dltyy
-----------------------------------------------------------------------

IP核对于项目来说,并不适合

1.虽然速度快,但是是串行工作的。
2.N点的FFT核,相邻的两个N点是不重合的,而希望的FFT工作的时候应该相邻的两个N点有N-1个重合

后来用的解决方法是编写符合项目需要的FFT算法。点数少点也可以忍受。

出0入0汤圆

 楼主| 发表于 2011-8-6 10:58:28 | 显示全部楼层
回复【25楼】02013063
-----------------------------------------------------------------------

谢谢楼上的热心分享:
1、我按你说的,又硬着头皮静下心来用Quartus 9.1自带的仿真,最终得到了结果,64点,8位的FFT IP核,把工程(带有仿真文件)与大家分享:
       点击此处下载 ourdev_664951BG7OPG.rar(文件大小:8.27M) (原文件名:FFT_sim.rar)
2、还有个问题想请教楼上:你们最终的算法是用HDL语言实现的还是NIOS 实现的?工程还能找到与大家分享吗?不胜感激!

出0入0汤圆

发表于 2011-8-6 11:46:13 | 显示全部楼层
回复【26楼】dltyy
-----------------------------------------------------------------------
nios速度太慢,最终方案是用语言写的,时间过了好久了,那个工程已经找不到了,抱歉

而且我机子里的quartus好像出问题了,昨天想回味下当年仿过的FFT核,居然仿不了了,奇怪的很

出0入0汤圆

发表于 2011-8-6 12:06:17 | 显示全部楼层
有没有fpga实现的fft的资料呢?

出0入0汤圆

发表于 2011-8-6 13:08:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-7 13:20:41 | 显示全部楼层
回复【26楼】dltyy
--------------------------------------------------------------------
这个工程仿真输入信号好像没设置好吧,没有输出

出0入0汤圆

发表于 2011-8-7 17:05:11 | 显示全部楼层
回复【14楼】dltyy
-----------------------------------------------------------------------

楼主和我好像啊。 我也是闷头研究了3天~ 你分享的那几个 程序我也都找到了~  
基本情况就是  把上边的时序图照搬下来~ 也没有结果~ 很是苦闷~  刚刚看了一下你发表的时间~ 竟然是最近~ 非常让我兴奋~
加我扣扣261153494  我最近 也是做项目 FFT 不得不做明白~ 希望和你一同攻坚

出0入0汤圆

发表于 2011-8-7 17:07:15 | 显示全部楼层
回复【5楼】dltyy
-----------------------------------------------------------------------

为了一个项目 从头学NIOS袄。。代价有点大了吧~

出0入0汤圆

发表于 2011-8-7 17:16:52 | 显示全部楼层
http://littlestone06.blog.163.com/blog/static/510672292008712114850993/ 这个网址也不错

出0入0汤圆

发表于 2011-8-7 17:23:50 | 显示全部楼层
我下一步准备~ 研究IP核的FIR滤波器~ 楼主有没有兴趣一起搞 呵呵

出0入0汤圆

发表于 2011-8-7 17:24:08 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2011-8-7 17:54:42 | 显示全部楼层
回复【30楼】cafppla
-----------------------------------------------------------------------

细看是有的,不要拖动那个滚动条快了……有周期性的输出

出0入0汤圆

发表于 2011-8-7 18:00:10 | 显示全部楼层

(原文件名:QQ截图未命名.png)

楼主。打开工程出现这个 是什么情况?

出0入0汤圆

 楼主| 发表于 2011-8-7 18:01:57 | 显示全部楼层
回复【28楼】brahen 柏
-----------------------------------------------------------------------

点击此处下载 ourdev_665286XW4F5Y.rar(文件大小:38.98M) (原文件名:FFT.rar)

出0入0汤圆

发表于 2011-8-7 21:46:53 | 显示全部楼层
回复【37楼】dltyy  
--------------------------------------------------------
为什么我的没输出?反而那个错误的引脚有一个输出,能否将你的仿真时序图贴上?

出0入0汤圆

发表于 2011-8-8 00:13:43 | 显示全部楼层
FFT核使用的时候只需要按照接口时许往里面灌输据就行了,本人用的是Xilinx的器件及IP核,没有问题;
至于搂主说到的Modelsim仿真问题,主要还是软件使用的问题,多看看教程就明白了,如果使用Xilinx的器件,建议在ISE里面调用Modelsim,用户只需准备好激励就OK,其他的工作诸如仿真脚本之类ISE已经自动生成了;

出0入0汤圆

发表于 2011-8-8 08:52:58 | 显示全部楼层
楼主的想法跟我的不谋而合了,最近我也在学习fft,但是基于理论的薄弱,所以我决定先将理论吃透了,再做深入的学习,我也没打算用软核,正如楼主说的,fft追求的是速度,用fpga就是因为看中了他是纯硬件的,处理速度特别快,如果加上软核的话,就和跑程序 类的一样的了,所以要做最好还是纯硬件的比较好。

出0入0汤圆

 楼主| 发表于 2011-8-8 18:23:07 | 显示全部楼层
回复【27楼】02013063
-----------------------------------------------------------------------

我这两天仔细研究了一下算法,4楼哥们贴上来的8点的FFT我也仔细读了,确实感觉到了楼上说的这个问题,串行的接收数据这个问题,你们当时是怎么解决这个问题的?

出0入0汤圆

 楼主| 发表于 2011-8-8 18:24:45 | 显示全部楼层
回复【42楼】cj501813910
-----------------------------------------------------------------------

QQ:983482673.欢迎交流。

出0入0汤圆

 楼主| 发表于 2011-8-8 18:33:17 | 显示全部楼层
回复【40楼】cafppla
-----------------------------------------------------------------------

你说的是错误的source error引脚?我刚试了一下,有输出的,但是我随便给的激励,变换后的值不好,没有4楼兄弟贴上来的自己编的8fft的输出那么好看,

出0入0汤圆

 楼主| 发表于 2011-8-8 18:34:43 | 显示全部楼层
回复【40楼】cafppla
-----------------------------------------------------------------------

这是我刚试过的:
点击此处下载 ourdev_665544ZYKC62.rar(文件大小:8.28M) (原文件名:FFT IP 64.rar)

出0入0汤圆

 楼主| 发表于 2011-8-8 18:36:18 | 显示全部楼层
回复【41楼】philoman
-----------------------------------------------------------------------

呵呵,确实说的有道理,就是新手有些细节自己老是发现不了问题在哪里。

出0入0汤圆

 楼主| 发表于 2011-8-8 18:43:45 | 显示全部楼层
今天想提出点疑惑,希望慷慨为小弟解惑:
1、FFT算法里面,一个问题就是输入输出,只能是串行的吗?有没有什么办法?
2、刚开始我还想一级一级的嵌套模块化,就是先编个8点的模块,然后一个16点的模块(里面封装2个8点的模块),然后一个32点的模块(里面封装2个16点的模块)......这样一级一级的模块化,后来一想,这样光是输入就是个麻烦事,串行,从高一级到第一级还得在高级模块里面串行输入低级模块,这样效率低……有没有什么办法。
3、这里面还有一个问题就是关于有个W_N^k的计算,这个难道只有用2的n次幂的分数和去逼近,就是4楼兄弟*0.7那个通过移位的办法来解决吗?

出0入0汤圆

发表于 2011-8-8 20:21:31 | 显示全部楼层
记得以前实现的事4096点的FFT。然后每一级的蝶形运算中乘法用了4个时钟,然后一轮FFT用时4*4096个CLK。
程序也找不到了。当时是FPGA将10位AD值读完后,开始运算,然后将运算结果通过SPI给单片机显示。

其实只要搞定了蝶形运算的原理就行了。每一次的运算都将他并行就很快。

以上纯属个人灌水

出0入0汤圆

 楼主| 发表于 2011-8-9 09:13:59 | 显示全部楼层
回复【49楼】fjcqv
-----------------------------------------------------------------------

可以解释一下每一次的运算都将它并行是什么意思吗?

出0入0汤圆

 楼主| 发表于 2011-8-9 09:22:02 | 显示全部楼层
呼吁一下,希望更多以前实现过的朋友,把你们的工程上传上来,让我们研究学习一下!!!感激不尽!

出0入0汤圆

发表于 2011-8-9 14:08:42 | 显示全部楼层
回复【46楼】dltyy
-----------------------------------------------------------------------
为什么我把你这个工程编译仿真后波形是这个?我的也是9.1的版本

(原文件名:未命名.jpg)

出0入0汤圆

 楼主| 发表于 2011-8-9 15:18:53 | 显示全部楼层
回复【53楼】cafppla
-----------------------------------------------------------------------

我的是这样:

(原文件名:fft8.jpg)

出0入0汤圆

 楼主| 发表于 2011-8-9 15:38:48 | 显示全部楼层
呵呵,诚心求FFT的HDL语言实现,点数最好多点。

出0入0汤圆

发表于 2011-8-9 22:30:54 | 显示全部楼层
回复【51楼】dltyy
-----------------------------------------------------------------------

找到以前写的了,之前说的还是有点问题。但是如果用于点数比较低的FFT运算来说,例如N=8,则3轮中的乘法并行起来,速度可以达到最快。但是这样占用的资源有点多。

另外,给你我以前的FFT4096。verilog写的。速度可能不快,点击此处下载 ourdev_666014T0NEVR.rar(文件大小:5K) (原文件名:Desktop.rar)

出0入0汤圆

 楼主| 发表于 2011-8-10 01:57:24 | 显示全部楼层
回复【56楼】fjcqv
-----------------------------------------------------------------------

先行谢过楼上了,我研究一下你当时的工程。然后再交流。

出0入0汤圆

发表于 2011-8-10 12:38:31 | 显示全部楼层
回复【54楼】dltyy
-----------------------------------------------------------------------

我下载你的工程,没有第60引脚,而且时序图是这样的,完全没输出

(原文件名:Y25`D[FEQOZ57HR52OB94%W.jpg)

出0入0汤圆

 楼主| 发表于 2011-8-11 20:19:22 | 显示全部楼层
是不是压缩后有问题,这个我也不知道,有没有知道的兄弟……怎么换了电脑就不行了

出0入0汤圆

 楼主| 发表于 2011-8-11 20:21:40 | 显示全部楼层
回复【56楼】fjcqv
-----------------------------------------------------------------------

56楼的兄弟,可否讲一下你这个fft4096个点的思路……我发现和那个4楼那个fft8思路不一样,方法也不一样……比那个看起来困难,有没有研究了这几个代码的,交流一下……

出0入0汤圆

发表于 2011-8-11 22:58:20 | 显示全部楼层
稍微修改了下,出数据了。。。

出0入0汤圆

发表于 2011-8-12 11:36:38 | 显示全部楼层
回复【61楼】cafppla
-----------------------------------------------------------------------

能把你的波形图发出来吗?

出0入0汤圆

发表于 2011-8-12 12:01:24 | 显示全部楼层
mark ,FFT  :)

出0入0汤圆

 楼主| 发表于 2011-8-12 14:16:13 | 显示全部楼层
回复【61楼】cafppla
-----------------------------------------------------------------------

呵呵,要是你有点数多点的FFT算法代码,可要分享哦。

出0入0汤圆

发表于 2011-8-14 11:52:56 | 显示全部楼层
曾经和楼主有相同的困惑。
现在尝试用stm32做fft了,64点的fft,计算时间不到80us,也能接受

出0入0汤圆

发表于 2011-8-21 09:43:19 | 显示全部楼层
回复【61楼】cafppla
-----------------------------------------------------------------------

怎么改的啊,我也是没有

出0入0汤圆

发表于 2011-8-25 00:49:32 | 显示全部楼层
年前准备做FFT频谱分析,苦于找不到资料,又欠缺很多,所以就放弃了,以前也来过这个网站,今天才感觉到这个网站真的很不赖

出0入0汤圆

发表于 2011-8-27 20:02:37 | 显示全部楼层
为今后搞FPGA留着

出0入0汤圆

发表于 2011-8-27 20:39:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-29 13:00:49 | 显示全部楼层
这个我试过opencore上面64点的FFT核在modelsim上面做个仿真。。。楼主你可以去试试,那个调用起来简单,就是资源占得多。

出0入0汤圆

发表于 2011-8-30 10:43:37 | 显示全部楼层
我只能是学习了,FPGA正打算用他做个控制器呢

出0入0汤圆

发表于 2011-11-6 02:43:54 | 显示全部楼层
先Mark,看来还有很长的路要走啊

出0入0汤圆

发表于 2011-11-7 22:05:22 | 显示全部楼层
看了楼主的文章,觉得自己还有好长的路要走啊,加油吧。

出0入0汤圆

发表于 2011-11-8 23:41:40 | 显示全部楼层
orz    mark

出0入0汤圆

发表于 2011-11-16 16:36:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-5-3 22:17:50 | 显示全部楼层
有同感呀!总感觉身边的人好少学习这个,什么东西都要自己研究,好痛苦,但是俗话说的好--痛并快乐着!!

出0入0汤圆

发表于 2012-5-5 16:50:25 | 显示全部楼层
共同学习,加油楼主

出0入0汤圆

发表于 2013-10-8 09:36:27 | 显示全部楼层
最近一直在研究FFT fpga实现,各位莫友真的有帮助

出0入0汤圆

发表于 2013-10-8 09:37:12 | 显示全部楼层
tortoisechan 发表于 2011-8-29 13:00
这个我试过opencore上面64点的FFT核在modelsim上面做个仿真。。。楼主你可以去试试,那个调用起来简单,就 ...

你好我一直没找到,可否分享一下啊

出0入0汤圆

发表于 2013-10-8 10:12:30 | 显示全部楼层
学习中……

出0入0汤圆

发表于 2013-10-17 02:30:53 | 显示全部楼层
本帖最后由 隐姓埋名 于 2013-10-17 02:38 编辑

NIOS软核实现较直接用现成的IP核当然要复杂许多,但是我想知道的关键是NIOS软核实现的速度会不会比FFT IP核的速度慢很多,因为我做这个FFT的首要目标就是快速,但是这个疑惑我至今都不是很清楚。

虽然没做个这个但是个人认为不要用NIOS,你用NIOS为什么不用DSP?原理上一样的,也都是用C来写,而且DSP专用的不比NIOS好么?这样FPGA的优势完全发挥不出来了,试着自己去用逻辑去实现,具体怎么实现更好更快就看你的努力了

出0入0汤圆

发表于 2014-3-28 11:15:31 | 显示全部楼层
之前没怎么接触过FPGA,现在毕设中用到,非常感谢。

出0入0汤圆

发表于 2014-3-28 11:32:23 | 显示全部楼层
mark一下FFT

出0入0汤圆

发表于 2014-5-29 09:56:31 | 显示全部楼层
多谢。。。。。。。。。。。。。。。。。。。。

出0入0汤圆

发表于 2014-9-4 15:27:38 | 显示全部楼层
sdu1028 发表于 2011-8-5 12:49
这个帖子,xilinx的片子,硬件FFT,用了MicroBlaze控制,带VGA显示波形与FFT结果的,楼主可以看下。。。
ht ...

楼主 这个链接貌似打不开了 能否重新 给个??? 谢过了

出0入0汤圆

发表于 2015-4-23 11:36:55 | 显示全部楼层
很不错的资料,谢谢了

出0入0汤圆

发表于 2015-6-8 18:01:56 | 显示全部楼层
谢了,这个对我帮助很大~

出0入0汤圆

发表于 2015-6-10 14:10:27 | 显示全部楼层
写的不错            
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-24 04:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表