xilinx暑期学校学习笔记(一)基于HLS的FIR滤波器

代码分析

源文件内容为

#include "fir.h" 

void fir (
  data_t *y,
  data_t x
  ) {
  const coef_t c[N+1]={
 #include "fir_coef.dat"
    };
  

  static data_t shift_reg[N];
  acc_t acc;
  int i;
  
  acc=(acc_t)shift_reg[N-1]*(acc_t)c[N];
  loop: for (i=N-1;i!=0;i--) {
    acc+=(acc_t)shift_reg[i-1]*(acc_t)c[i];
    shift_reg[i]=shift_reg[i-1];
  }
  acc+=(acc_t)x*(acc_t)c[0];
  shift_reg[0]=x;
  *y = acc>>15;
}

头文件内容为

#ifndef _FIR_H_ 
#define _FIR_H_
#include "ap_cint.h"
#define N	58
#define SAMPLES N+10 // just few more samples then number of taps
typedef short	coef_t;
typedef short	data_t;
typedef int38	acc_t;
#endif

系数文件为
在这里插入图片描述

函数入口为

void fir (
  data_t *y,
  data_t x
  ) 

x为输入参量,y为输入指针参数,方便外部访问计算结果。
首先读入全部的FIR系数到一个长度N+1的常量数组中。

  const coef_t c[N+1]={
 #include "fir_coef.dat"
    };

定义静态数组,这是因为FIR滤波器需要对前k项的样本数据做处理,因此需要静态数组储存过去读入的数值。

static data_t shift_reg[N];

部分的FIR滤波器内容可以考虑HLS 开发学习(一)FIR滤波器

接下来就是将寄存器数组移位

acc=(acc_t)shift_reg[N-1]*(acc_t)c[N];
  loop: for (i=N-1;i!=0;i--) {
    acc+=(acc_t)shift_reg[i-1]*(acc_t)c[i];
    shift_reg[i]=shift_reg[i-1];
  }

然后将新值插入到shift_reg的初始位置。然后让y指针的内容为acc右移15位。(为什么要右移15位呢?除以2^15??)

acc+=(acc_t)x*(acc_t)c[0];
  shift_reg[0]=x;
  *y = acc>>15;

HLS

仿真和综合

仿真的代码内容

很直接,就是输入信号是一个脉冲信号(仅在t=0的时候不为0),然后将其不断送入fir滤波器

  int i;
  for (i=0;i<SAMPLES;i++) {
	  if(i==0)
		  signal = 0x8000;
	  else
		  signal = 0;
	  fir(&output,signal);
   	  printf("%i %d %d\n",i,(int)signal,(int)output);
//   	  fprintf(fp,"%i %d %d\n",i,signal,output);

在这里插入图片描述

其输出的信号波形为
在这里插入图片描述

综合报告

综合后可得综合报告

在这里插入图片描述
Estimated clock period: 8.702
Worst case latency: 174
Number of DSP48E used: 3
Number of BRAMs used: 0
Number of FFs used: 167
Number of LUTs used: 154

以及接口

在这里插入图片描述

优化

对源文件中的loop循环添加pipeline优化。重新综合

在这里插入图片描述
latency减少至62,但是硬件资源消耗提高了
在这里插入图片描述

这是流水线并行运算提高了运算速度,代价是更多的硬件资源消耗。

IP-XACT Adapter

在Directive里右击x,插入Directive,选择interface,进行如下配置

在这里插入图片描述
y也是如此

对顶层模块fir插入directive
在这里插入图片描述
在这里插入图片描述
这将包括ap_start,ap_done,ap_idle信号作为总线的适配器。

接下来重新生成设计,然后RTL导出来生成 IP-XACT adapter.

在impl文件夹中可以看到输出结果 ip, misc, verilog, vhdl.

Vivado工程

在vivado中创建一个xc7z020clg400-1的工程,通过提供的脚本进行工程初始化

在这里插入图片描述
相应工程文件下载

可以得到如下diagram
在这里插入图片描述
把刚才的fir滤波器的ip核添加进来

在这里插入图片描述

在diagram中添加2个fir 的ip核,分别叫fir_left和fir_right,然后自动连线

打开PL-PS中断
在这里插入图片描述

添加一个concat ip,将两个fir分别连到in0和in1,其输出则连接到处理系统的IRQ_F2P上

此时其地址为

在这里插入图片描述

接下来创建 HDL Wrapper
然后Add source,选择constraints,将提供的约束文件添加进去,之后老规矩生成bitstream。

SDK

export hardware后launch SDK,新建板级支持包。

新建空白应用工程

添加 pynq_z2_testapp.cpynq_z2_audio.h

开发板以jtag模式启动

在line in那里插入PC的音频输出,在HP——MIC那里插入耳机

Program FPGA

让PC播放一个音频,然后在SDK中Run As > Launch On Hardware (System Debugger).

sw0为关闭时候是原始信号,打开的时候是滤波后的信号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙粽子好吃嘛!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值