ctqvsly 发表于 2013-3-14 18:46:52

FPGA FFT IP使用问题

在使用FFTIP核的时候,输出格式是Natural order ,输入的是8位的AD数据,
参数如截图:(1)(2)
FFT例化的如下:
输入是
reg sink_real;
   reg sink_imag;
FFT_IP输出的是18位
   wire source_real;
   wire source_imag;

输入FFT的AD数据除以2最高位取0,为正数

提问:输出的18位怎么处理得到可以送给下一级处理的数据,
      下面的计算应该是除以128/2得到8位数据,怎样得到那个待除的数字??{:cry:}

yuhang 发表于 2013-3-14 21:33:30

能把河蟹文件共享一下啊

FFT输入的是信号的实部 与 虚部

输出两路 平方和 然后开更号就是 FFT结果的幅度值

ctqvsly 发表于 2013-3-16 10:06:50

本帖最后由 ctqvsly 于 2013-3-16 10:13 编辑

yuhang 发表于 2013-3-14 21:33 static/image/common/back.gif
能把河蟹文件共享一下啊

FFT输入的是信号的实部 与 虚部


能把你的工程分享一下吗?还有结果的位宽能解释一下吗?

只要将我的文件中网卡号,稍加修改即可

jxquer 发表于 2013-3-27 10:43:04

你好!我能请教一下您再做FFT IP核仿真的时候如果用QII自带的仿真软件 这样的话 输入数据要怎么设置。我现在写了一个状态机 控制其他信号输入 但是sink_real信号纠结了不知道怎么输入本想是做完AD采集再输入的 但是现在又急于先做这一块,请指教

loywong 发表于 2013-3-27 13:08:13

stream 的 fft, 输出还有一个exp, 是2的指数,
fft megacore 输出的乘以 2^exp (即帯符号左移(<<<)exp位)得到fft原始定义的输出,
这个输出 要再除以 N(fft长度), 的到幅相谱(有实有虚), 幅度谱是其模, 相位谱是其幅角.
注意,其中除了直流和N/2位置,其它的谱都是有关于N/2位置对称的两个共轭值的,因此它们的幅度谱是两个共轭值的模的和,当然就是某一个的模的两倍.

ctqvsly 发表于 2013-3-27 20:51:19

loywong 发表于 2013-3-27 13:08 static/image/common/back.gif
stream 的 fft, 输出还有一个exp, 是2的指数,
fft megacore 输出的乘以 2^exp (即帯符号左移( ...

没看懂{:cry:} 能举例说明一下吗?
比如AD采样得到8位的数据输入,然后输出的17位怎么转换为十六进制的无符号数?

loywong 发表于 2013-3-29 13:24:55

本帖最后由 loywong 于 2013-3-29 13:26 编辑

你用nios2吗?如果用需要sg-dma和一个stream的wrapper,这个我有做过的现成代码给你参考:
比较久远了,有些参数你自己看看。
先做一个fft,再用这个wrapper调用它:
module fft_avalon_wraper
(
        input clk,
        input reset_n,
       
        input mm_address,
        input mm_read,
        output mm_readdate,
        input mm_write,
        input mm_writedate,
       
        output sink_ready,
        input sink_valid,
        input sink_sop,
        input sink_eop,
        input sink_data,
        input sink_empty,
        input sink_error,
       
        input source_ready,
        output source_valid,
        output source_sop,
        output source_eop,
        output source_data,
        output source_empty,
        output source_error
);

        parameter WIDTH = 16;

    reg inverse;
    reg exponent;
    wire source_exp;
   
    assign mm_readdate = (mm_address == 1'b0) ? {exponent, exponent ,exponent} : {7'b0, inverse};
    assign source_empty = 2'b0;
   
    always@(posedge clk)
    begin
                if(~reset_n)
                begin
                        inverse <= 1'b0;
                        exponent <= 6'b0;
                end
                else
                begin
                        if(mm_write)
                        begin
                                inverse <= mm_writedate;
                        end
                        if(source_sop)
                        begin
                                exponent <= source_exp;
                        end
                end
    end
       
        wire sink_data_xe;
        wire source_data_xe;
       
        localparam W = WIDTH * 2;
        genvar i;
        generate
                for(i = 0; i < W; i = i + 8)
                begin :xe_byte
                        assign sink_data_xe = sink_data;
                        assign source_data = source_data_xe;
                end
        endgenerate
   
    fft thefft
    (
            clk,
            reset_n,
            inverse,
            sink_valid,
            sink_sop,
            sink_eop,
            sink_data_xe,
            sink_data_xe,
            sink_error,
            source_ready,
            sink_ready,
            source_error,
            source_sop,
            source_eop,
            source_valid,
            source_exp,
            source_data_xe,
            source_data_xe
    );

endmodule
然后做成一个memory map的slave外设,它有两个地址,地址0读出exp,地址1读出 是FFT或是IFFT变换,任何地址写0,表示做FFT,写1表示做IFFT。

sopc builder中做两个sg-dma,一个用于给fft送数据,另一个收fft数据。

软件:

#include <system.h>
#include <stdio.h>
#include <stdlib.h>
#include <altera_avalon_sgdma.h>
#include <altera_avalon_sgdma_regs.h>
#include <altera_avalon_sgdma_descriptor.h>
#include <altera_avalon_performance_counter.h>
#include "sys/alt_cache.h"
#include "sys/alt_sys_wrappers.h"

#define FFT_LEN 1024

alt_sgdma_dev *pPreFftDma;
alt_sgdma_descriptor *pPreFftDmaDescrs;
alt_sgdma_dev *pPostFftDma;
alt_sgdma_descriptor *pPostFftDmaDescrs;

#pragma pack(1)
typedef struct __ShortCplx
{
    alt_16 Real;
        alt_16 Imag;
} ShortCplx;
ShortCplx X;
ShortCplx F;
alt_8 Fexp;
alt_8 FftTransFinished = 0;
alt_8 FftRecvFinished = 0;

void createPreFftDmaDescr()
{
        pPreFftDmaDescrs = (alt_sgdma_descriptor *)malloc(2 * sizeof(alt_sgdma_descriptor));
        alt_avalon_sgdma_construct_mem_to_stream_desc(
                        pPreFftDmaDescrs,
                        pPreFftDmaDescrs + 1,
                        (alt_u32 *)X,
                        FFT_LEN * sizeof(ShortCplx),
                        0,
                        1,
                        1,
                        0);
}
void createPostFftDmaDescr()
{
        pPostFftDmaDescrs = (alt_sgdma_descriptor *)malloc(2 * sizeof(alt_sgdma_descriptor));
        alt_avalon_sgdma_construct_stream_to_mem_desc(
                        pPostFftDmaDescrs,
                        pPostFftDmaDescrs + 1,
                        (alt_u32 *)F,
            0/*FFT_LEN * sizeof(ShortCplx)*/,
                        0);
}

static void preFftDma_ISR(void *pContext)
{
        int i, ctrl;
        ctrl = IORD_ALTERA_AVALON_SGDMA_STATUS(pPreFftDma->base);
        if(ctrl & ALTERA_AVALON_SGDMA_STATUS_CHAIN_COMPLETED_MSK)
        {
                i = 1;
                FftTransFinished = 1;
        }
}

static void postFftDma_ISR(void *pContext)
{
        int i, ctrl;
        ctrl = IORD_ALTERA_AVALON_SGDMA_STATUS(pPostFftDma->base);
        if(ctrl & ALTERA_AVALON_SGDMA_STATUS_EOP_ENCOUNTERED_MSK)
        {
                i = 1;
                FftRecvFinished = 1;
        }
}

int main()
{
        alt_u32 control;
        int i;

        printf("Hello from Nios II!\n");

        pPreFftDma = alt_avalon_sgdma_open(SGDMA_PREFFT_NAME);
        pPostFftDma = alt_avalon_sgdma_open(SGDMA_POSTFFT_NAME);
        alt_avalon_sgdma_register_callback(
                        pPreFftDma,
                        preFftDma_ISR,
                        ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK,
                        NULL);
        alt_avalon_sgdma_register_callback(
                        pPostFftDma,
                        postFftDma_ISR,
                        ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_EOP_ENCOUNTERED_MSK,
                        NULL);

        createPreFftDmaDescr();
        createPostFftDmaDescr();

        control = IORD_ALTERA_AVALON_SGDMA_CONTROL(pPreFftDma->base);
        control |= ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK;
        IOWR_ALTERA_AVALON_SGDMA_CONTROL(pPreFftDma->base, control);
        control = IORD_ALTERA_AVALON_SGDMA_CONTROL(pPostFftDma->base);
        control |= ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK;
        IOWR_ALTERA_AVALON_SGDMA_CONTROL(pPostFftDma->base, control);

        for(i = 0; i < FFT_LEN; i++)
        {
                X.Imag = 0;
                if(i < FFT_LEN / 2)
                {
                        X.Real = 32767;
                }
                else
                {
                        X.Real = -32767;
                }      
        }
        alt_dcache_flush((void *)X, FFT_LEN * sizeof(ShortCplx));

    PERF_RESET(PFC_BASE);
    PERF_START_MEASURING(PFC_BASE);
    PERF_BEGIN(PFC_BASE, 1);
    alt_avalon_sgdma_do_async_transfer(pPostFftDma, pPostFftDmaDescrs);
        alt_avalon_sgdma_do_async_transfer(pPreFftDma, pPreFftDmaDescrs);

        while(1)
        {
                if(FftRecvFinished)
                {
            PERF_END(PFC_BASE, 1);
            
                        FftRecvFinished = 0;
                        alt_dcache_flush((void *)F, FFT_LEN * sizeof(ShortCplx));
                        Fexp = IORD(FFT_AVALON_BASE, 0);

            PERF_STOP_MEASURING(PFC_BASE);
            perf_print_formatted_report((void *)PFC_BASE, alt_get_cpu_freq(), 1, "FFT");
            
            PERF_RESET(PFC_BASE);
            PERF_START_MEASURING(PFC_BASE);

                        alt_avalon_sgdma_do_async_transfer(pPostFftDma, pPostFftDmaDescrs);
                        alt_avalon_sgdma_do_async_transfer(pPreFftDma, pPreFftDmaDescrs);
            
            PERF_BEGIN(PFC_BASE, 1);
                }
        }

return 0;
}
当中有大量sg-dma的操作,特别是描述符链表,请到altera.com上搜其user guide并自行理解。

如有那条不明白,上altera.com搜之。如果你没有用sopc系统和nios2软核的经验,可能需要学的还很多。

如果单纯用逻辑写stream if,会稍麻烦,我没做过,不敢妄言。

ctqvsly 发表于 2013-3-31 09:28:48

loywong 发表于 2013-3-29 13:24 static/image/common/back.gif
你用nios2吗?如果用需要sg-dma和一个stream的wrapper,这个我有做过的现成代码给你参考:
比较久远了,有 ...

太谢谢啦,正需要!

飞鹤王子 发表于 2013-4-24 12:39:11

mark,很不错的帖子!

Laden 发表于 2013-4-30 12:29:08

飞鹤王子 发表于 2013-4-24 12:39 static/image/common/back.gif
mark,很不错的帖子!

LZ 我现在调试 Altera FFT IP Burst 架构出现了和官方提供的Testbench不一样的结果,但是source_erro 没有报错

Laden 发表于 2013-4-30 12:29:53

ctqvsly 发表于 2013-3-27 20:51 static/image/common/back.gif
没看懂 能举例说明一下吗?
比如AD采样得到8位的数据输入,然后输出的17位怎么转换为十六进制的无 ...


LZ 我现在调试 Altera FFT IP Burst 架构出现了和官方提供的Testbench不一样的结果,但是source_erro 没有报错



YA1W@Y$ZEKOG)`TA5QYTD{S.jpg (281.65 KB, 下载次数: 0)












激励给的是直流 幅值为1


ctqvsly 发表于 2013-4-30 16:00:55

Laden 发表于 2013-4-30 12:29 static/image/common/back.gif
LZ 我现在调试 Altera FFT IP Burst 架构出现了和官方提供的Testbench不一样的结果,但是source_erro 没 ...

我也没看懂~    实部和虚部上出现的类似噪声的是什么啊?

qidaimengxing 发表于 2013-4-30 16:13:52

不错有空研究一下

Laden 发表于 2013-5-1 12:34:05

ctqvsly 发表于 2013-4-30 16:00 static/image/common/back.gif
我也没看懂~    实部和虚部上出现的类似噪声的是什么啊?

谢谢 调试出来了 是我在后仿真的时候 时钟频率 太高了

zlpvch 发表于 2013-8-6 19:53:08

不错,   

zlpvch 发表于 2013-8-6 19:53:30

有收获   ,晚上这方面的资料太少了

zlpvch 发表于 2013-8-6 19:54:02

网上         

liyusnoopy 发表于 2013-8-22 10:02:31

请问一下要如何用ModelSim仿真 FFT ip core呢?

ctqvsly 发表于 2013-8-22 16:48:44

liyusnoopy 发表于 2013-8-22 10:02 static/image/common/back.gif
请问一下要如何用ModelSim仿真 FFT ip core呢?

自己百度搜试试,网上有教程

liyusnoopy 发表于 2013-8-22 20:59:30

想问一下,你的FFT ip 核的数据输出处理好了吗?是像楼上那位给的用NIOS实现的处理吗?

ctqvsly 发表于 2013-8-22 22:27:19

liyusnoopy 发表于 2013-8-22 20:59
想问一下,你的FFT ip 核的数据输出处理好了吗?是像楼上那位给的用NIOS实现的处理吗? ...

没有,直接串口打印,和da输出波形,留着以后备用,现考研没时间搞~

513696765 发表于 2013-8-30 01:50:24

ctqvsly 发表于 2013-8-22 22:27 static/image/common/back.gif
没有,直接串口打印,和da输出波形,留着以后备用,现考研没时间搞~

楼主能否分享一下!!!

fx568000 发表于 2015-3-26 15:15:41

正在用,正好看一下
页: [1]
查看完整版本: FPGA FFT IP使用问题