前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SDAccel结构实现之移位寄存器篇

SDAccel结构实现之移位寄存器篇

作者头像
AI异构
发布2020-07-29 10:51:57
3860
发布2020-07-29 10:51:57
举报
文章被收录于专栏:AI异构

fir滤波器与移位寄存器的结构匹配度100%

fir滤波器原理

FIR(Finite Impulse Response)滤波器:有限长单位冲激响应滤波器,又称为非递归型滤波器,是数字信号处理系统中最基本的元件,它可以在保证任意幅频特性的同时具有严格的线性相频特性,同时其单位抽样响应是有限长的,因而滤波器是稳定的系统。因此,FIR滤波器在通信、图像处理、模式识别等领域都有着广泛的应用。 在这里我们不谈FIR过多的原理知识,重点关注基于FIR计算的优化.我们预先确定一组参数,来实现一个11阶的FIR滤波器。计算流程如下:

fir 简单实现方式

代码语言:javascript
复制
#define N_COEFF 11

// A naive implementation of the Finite Impulse Response filter.
__kernel __attribute__ ((reqd_work_group_size(1, 1, 1)))
void fir_naive(__global int* restrict output,
               __global int* restrict signal,
               __global int* restrict coeff,
               long signal_length) {

    int coeff_reg[N_COEFF];
    read_coef: for (int i = 0 ; i < N_COEFF ; i++) coeff_reg[i] = coeff[i];

    outer_loop:
    for (int j = 0; j < signal_length; j++) {
        int acc = 0;
        shift_loop:
        __attribute__((xcl_pipeline_loop))
        for (int i = min(j,N_COEFF-1); i >= 0; i--) {
            acc += signal[j-i] * coeff_reg[i];
        }
        output[j] = acc;
    }
}

fir移位寄存器实现方式

代码语言:javascript
复制
// FIR using shift register
__kernel __attribute__ ((reqd_work_group_size(1, 1, 1)))
void fir_shift_register(__global int* restrict output,
                        __global int* restrict signal,
                        __global int* restrict coeff,
                        long signal_length) {
    int coeff_reg[N_COEFF];

    // Partitioning of this array is required because the shift register
    // operation will need access to each of the values of the array in
    // the same clock. Without partitioning the operation will need to
    // be performed over multiple cycles because of the limited memory
    // ports available to the array.
    int shift_reg[N_COEFF] __attribute__((xcl_array_partition(complete, 0)));

    init_loop:
    for (int i = 0; i < N_COEFF; i++) {
        shift_reg[i] = 0;
        coeff_reg[i] = coeff[i];
    }

    outer_loop:
    for(int j = 0; j < signal_length; j++) {
        int acc = 0;
        int x = signal[j];

        // This is the shift register operation. The N_COEFF variable is defined
        // at compile time so the compiler knows the number of operations
        // performed by the loop. This loop does not require the unroll
        // attribute because the outer loop will be automatically pipelined so
        // the compiler will unroll this loop in the process.
        shift_loop:
        for (int i = N_COEFF-1; i >= 0; i--) {
            if (i == 0) {
                acc += x * coeff_reg[0];
                shift_reg[0] = x;
            } else {
                shift_reg[i] = shift_reg[i-1];
                acc += shift_reg[i] * coeff_reg[i];
            }
        }
        output[j] = acc;
    }
}

移位寄存器应用总结

在该例程中,巧妙的利用了移位寄存器结构,对处理过的数据进行存储且移位,大幅度的减少了与global memory接口的频繁交互。移位寄存器在实现的过程中,需要注意的是因为牵扯到数组间的移位,因此一定要将数组切割成寄存器的形式,否则会产生carry dependency使得循环的II值变大。

参考

xilinx github SDAccel_Examples/getting_started

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-01-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI异构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • fir滤波器原理
  • fir 简单实现方式
  • fir移位寄存器实现方式
  • 移位寄存器应用总结
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档