目录
摘要
通过ZYBOZ7开发板实现了分布式结构的FIR滤波器,实现了AD输入两路信号,通过开关输入可以分别单路输出、相加、相乘、相加后滤波、相乘后滤波的功能。
一、设计目标
设计基于FPGA的分布式结构的FIR滤波器,实现对输入信号的采集、滤波和输出。
二、 设计方案
1.硬件
材料 | 型号 | 规格 |
---|---|---|
ZyboZ7开发板 | zynq-7000 | xc7z020clg400 |
DA | PmodDA3 | 16位串行/类SPI接口 |
AD拓展接口 | - | - |
实物图:
2.系统流程图
三、具体实现步骤
1.XADC的使用
XADC包括一个双12位、1兆每秒采样(MSPS) ADC和片上ADC传感器。上图显示了XADC的框图。双重adc支持多种操作模式,例如,外部触发和同步。支持单极和差分输入。adc最多可以访问17个外部模拟输入通道。
由数据手册可知,ADC由两种操作模式:事件触发和连续转换模式。连续转换模式会在上次转换完成后继续下一次转换,默认一次转换需要26个ADCCLK;事件触发模式使用外部信号上升沿触发,启动一次转换。因为需按照固定采样率采样,故选择事件触发模式,使用100K信号触发,故采样率为100k。同时配置XDAC的时钟分频系数为4,clk为100MHz,所以ADCCLK实际大约为25MHz。
ADC的通道采样模式有四种:双ADC、独立ADC、单通道、多通道序列采样。因为本文须同时对两路信号信号进行采样,所以选择双ADC的模式,此模式下,在被外界信号触发后,两路ADC同时开始转换,并将结果保存的寄存器中。
ADC的接口可以配置为DRP(Dynamic Reconfiguration Port)和AXI,因为本文没有使用到PS部分,所以使用DRP接口。DRP接口读写时序如上图所示。
ADC的通道选择AD7和AD15,XADC引出如下引脚。查询时序图每次转换完成时会有eoc信号上升沿,channel会在转换完成时输出通道地址(AD7地址为7’h17,AD15地址为7’h1f),因为采用双ADC模式,所以channel只会输出AD7的地址。为了在每次转换完成时读取两通道AD的值,故编写XADC_wrapper.v封装了一层。编写如下状态机实现一次eoc信号触发两通道采样结果的读取:
仿真结果如下:
代码整理好后会上传到Github。
2.PmodDA3的调试
Pmod DA3是一个基于Analog Devices AD5541A的16位数字模拟转换器,参考电压为2.5V,其单端SMA输出口能够将从类SPI接口所获得的信息转换成一个清晰、有保障的单调模拟输出。
为了控制PmodDA3,需要编写一个并转串行的模块,此模块的外部接口如下图所示:输入16为数据,在DA_drdy信号上升沿时将数据读入并转化为串行后通过Pmod接口发送给DA模块。
参考AD5541A用户手册的时序图编写并转串模块,SCK为发送数据的时钟,其由clk分频得到,本文配置其为25Mhz;_CS为片选信号,_CS信号拉低时,DA会在下个SCLK的上升沿读取DIN信号作为信号最高位(DB15),每个SCLK读取一个二进制位,16个上升沿读取完成,_CS信号置高。_LDAC信号为装载信号,在数据传输完成后拉低,触发DA模块内部数据装载到DAC单元实现模拟信号输出。
编写状态机实现上述时序:
仿真结果:
编写个小程序:定义 reg[15:0] counter=0,每来一个clk ,counter+100,到65535溢出。如此就可以实现控制DA生成锯齿波,嘿嘿!
3.Fir滤波器
- 系统自带的IP核
- Matlab生成DA滤波器
4.开关控制
开关控制较为简单,顶层模块定义[3:0] sw输入信号,对其分配管脚,通过case(sw)语句块实现更改开关状态切换功能。
按键状态 | 功能 |
---|---|
0001 | AD7单路输出 |
0010 | AD15单路输出 |
0011 | 两路相乘 |
1011 | 两路相加 |
0111 | 两路相乘滤波 |
1111 | 两路相加滤波 |
实现代码如下:
//Control Logic
parameter[3:0] OnlyAd7=4'b0001;
parameter[3:0] OnlyAd15=4'b0010;
parameter[3:0] Ad15_AD7_mlt=4'b0011;
parameter[3:0] Ad15_AD7_add=4'b1011;
parameter[3:0] Ad15_AD7_mlt_Fir=4'b0111;
parameter[3:0] Ad15_AD7_add_Fir=4'b1111;
always@(posedge clk)
begin
case(sw)
OnlyAd7:
begin
da_indata<=_DataAD7;
da_invalid<=Data_rdy;
end
OnlyAd15:
begin
da_indata<=_DataAD15;
da_invalid<=Data_rdy;
end
Ad15_AD7_mlt:
begin
DataAD7=_DataAD7;
DataAD15=_DataAD15;
da_indata=DataAD15[15:8]*DataAD7[15:8];
da_invalid<=Data_rdy;
end
Ad15_AD7_add:
begin
DataAD7=_DataAD7;
DataAD15=_DataAD15;
da_indata=DataAD15[15:1]+DataAD7[15:1];
da_invalid<=Data_rdy;
end
Ad15_AD7_mlt_Fir:
begin
DataAD7=_DataAD7;
DataAD15=_DataAD15;
fir_indata=DataAD15[15:8]*DataAD7[15:8];
fir_invalid<=Data_rdy;
da_indata<=(fir_outdata<<2);
da_invalid<=fir_outvalid;
da_invalid<=Data_rdy;
end
Ad15_AD7_add_Fir:
begin
DataAD7=_DataAD7;
DataAD15=_DataAD15;
fir_indata=DataAD15[15:1]+DataAD7[15:1];
fir_invalid<=Data_rdy;
da_indata<=(fir_outdata<<2);
da_invalid<=fir_outvalid;
da_invalid<=Data_rdy;
end
default:
begin
da_indata<=_DataAD7;
da_invalid<=Data_rdy;
end
endcase
end
四、总结
总耗时3周,系统实现了AD输入两路信号,通过开关输入可以分别单路输出、相加、相乘、相加后滤波、相乘后滤波的功能。缺点是滤波器设计截至频率和实际测试截至频率不同,大约相差10倍,至今未找到原因在哪。
因为Fir核不是自己编写的,所以整体难度一般。主要是通过此项目对ZYNQ的FPGA部分进行入门学习,个人感觉开发过程中除了需要Verilog语言基础,仿真和Debug方法尤为重要。
欢迎和各位交流分享