搜索
bottom↓
回复: 22

FPGA FFT IP使用问题

[复制链接]

出0入0汤圆

发表于 2013-3-14 18:46:52 | 显示全部楼层 |阅读模式
在使用FFT  IP核的时候,输出格式是Natural order ,输入的是8位的AD数据,
参数如截图:(1)(2)
FFT例化的如下:
输入是
  reg[8 - 1:0] sink_real;
   reg[8 - 1:0] sink_imag;
FFT_IP输出的是18位
   wire [17 - 1: 0] source_real;
   wire [17 - 1: 0] source_imag;

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

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

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

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2013-3-14 21:33:30 | 显示全部楼层
能把河蟹文件共享一下啊

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

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

出0入0汤圆

 楼主| 发表于 2013-3-16 10:06:50 | 显示全部楼层
本帖最后由 ctqvsly 于 2013-3-16 10:13 编辑
yuhang 发表于 2013-3-14 21:33
能把河蟹文件共享一下啊

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


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

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

 楼主| 发表于 2013-3-27 20:51:19 | 显示全部楼层
loywong 发表于 2013-3-27 13:08
stream 的 fft, 输出还有一个exp, 是2的指数,
fft megacore 输出的乘以 2^exp (即帯符号左移( ...

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

出0入0汤圆

发表于 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 [7 : 0] mm_readdate,
        input mm_write,
        input [7 : 0] mm_writedate,
       
        output sink_ready,
        input sink_valid,
        input sink_sop,
        input sink_eop,
        input [WIDTH * 2 - 1 : 0] sink_data,
        input [1 : 0] sink_empty,
        input [1 : 0] sink_error,
       
        input source_ready,
        output source_valid,
        output source_sop,
        output source_eop,
        output [WIDTH * 2 - 1 : 0] source_data,
        output [1 : 0] source_empty,
        output [1 : 0] source_error
);

        parameter WIDTH = 16;

    reg inverse;
    reg [5 : 0] exponent;
    wire [5 : 0] source_exp;
   
    assign mm_readdate = (mm_address == 1'b0) ? {exponent[5], exponent[5] ,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[0];
                        end
                        if(source_sop)
                        begin
                                exponent <= source_exp;
                        end
                end
    end
       
        wire [WIDTH * 2 - 1 : 0] sink_data_xe;
        wire [WIDTH * 2 - 1 : 0] 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[i + 7 : i] = sink_data[W - 1 - i : W - 8 - i];
                        assign source_data[i + 7 : i] = source_data_xe[W - 1 - i : W - 8 - i];
                end
        endgenerate
   
    fft thefft
    (
            clk,
            reset_n,
            inverse,
            sink_valid,
            sink_sop,
            sink_eop,
            sink_data_xe[WIDTH - 1 : 0],
            sink_data_xe[WIDTH * 2 - 1 : WIDTH],
            sink_error,
            source_ready,
            sink_ready,
            source_error,
            source_sop,
            source_eop,
            source_valid,
            source_exp,
            source_data_xe[WIDTH - 1 : 0],
            source_data_xe[WIDTH * 2 - 1 : WIDTH]
    );

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[FFT_LEN];
ShortCplx F[FFT_LEN];
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,会稍麻烦,我没做过,不敢妄言。

出0入0汤圆

 楼主| 发表于 2013-3-31 09:28:48 | 显示全部楼层
loywong 发表于 2013-3-29 13:24
你用nios2吗?如果用需要sg-dma和一个stream的wrapper,这个我有做过的现成代码给你参考:
比较久远了,有 ...

太谢谢啦,正需要!

出0入0汤圆

发表于 2013-4-24 12:39:11 | 显示全部楼层
mark,很不错的帖子!

出0入0汤圆

发表于 2013-4-30 12:29:08 | 显示全部楼层
飞鹤王子 发表于 2013-4-24 12:39
mark,很不错的帖子!

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-4-30 12:29:53 | 显示全部楼层
ctqvsly 发表于 2013-3-27 20:51
没看懂 能举例说明一下吗?
比如AD采样得到8位的数据输入,然后输出的17位怎么转换为十六进制的无 ...



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



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












激励给的是直流 幅值为1


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-4-30 16:00:55 | 显示全部楼层
Laden 发表于 2013-4-30 12:29
LZ 我现在调试 Altera FFT IP Burst 架构出现了和官方提供的Testbench不一样的结果,但是source_erro 没 ...

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

出0入0汤圆

发表于 2013-4-30 16:13:52 | 显示全部楼层
不错  有空研究一下

出0入0汤圆

发表于 2013-5-1 12:34:05 | 显示全部楼层
ctqvsly 发表于 2013-4-30 16:00
我也没看懂~    实部和虚部上出现的类似噪声的是什么啊?

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

出0入0汤圆

发表于 2013-8-6 19:53:08 | 显示全部楼层
不错,   

出0入0汤圆

发表于 2013-8-6 19:53:30 | 显示全部楼层
有收获   ,晚上这方面的资料太少了

出0入0汤圆

发表于 2013-8-6 19:54:02 | 显示全部楼层
网上         

出0入0汤圆

发表于 2013-8-22 10:02:31 | 显示全部楼层
请问一下要如何用ModelSim仿真 FFT ip core呢?

出0入0汤圆

 楼主| 发表于 2013-8-22 16:48:44 | 显示全部楼层
liyusnoopy 发表于 2013-8-22 10:02
请问一下要如何用ModelSim仿真 FFT ip core呢?

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

出0入0汤圆

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

出0入0汤圆

 楼主| 发表于 2013-8-22 22:27:19 来自手机 | 显示全部楼层
liyusnoopy 发表于 2013-8-22 20:59
想问一下,你的FFT ip 核的数据输出处理好了吗?是像楼上那位给的用NIOS实现的处理吗? ...

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

出0入0汤圆

发表于 2013-8-30 01:50:24 | 显示全部楼层
ctqvsly 发表于 2013-8-22 22:27
没有,直接串口打印,和da输出波形,留着以后备用,现考研没时间搞~

楼主能否分享一下!!!

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-7-24 02:17

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

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