在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3342|回复: 6

[原创] 基于fpga的FIR滤波器设计(附上源码代码下载)

[复制链接]
发表于 2018-11-16 15:08:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

x
1 项目背景源码下载技术交流群:979253961.1 FIR和IIR滤波器

FIRFinite Impulse ResponseFilter:有限冲激响应滤波器,又称为非递归线性滤波器。

FIR滤波器,顾名思义,其脉冲响应由有限个采样值构成。长度(抽头数)为N、阶数为N−1的FIR系统的转移函数、差分方程和单位冲激响应分别如下列三式所示。

510

IIRInfinite Impulse ResponseFilter:无限冲激响应滤波器,又称为递归线性滤波器。

FIR相对与IIR来说,具有如下的优点:

[size=9.5000pt]Ø 可以具备线性相位特性

线性相位的概念: 如果滤波器的N个实值系数为对称或者反对称结构,该滤波器具有线性相位。
W(n)=±W(N−1−n)W(n)=±W(N−1−n)

线性相位的特性:通过线性相位滤波器的信号的所有频率部分具有相同的延迟量。


[size=9.5000pt]Ø 易于设计

FIR也有自身的缺点:同样指标的滤波器,FIR需要更多的参数,即实现时消耗更多的计算单元,产生更大的延迟。


1.2 FIR滤波器的原理


信号通过一个FIR滤波器其实就是信号与FIR滤波器的系数进行卷积(即乘累加)的过程。我们以一个简单信号模型为例,了解一下FIR波形器的原理。

现在有三组信号,分别是:

信号1:低频信号,即在时域上变化慢的信号,其输入先后为1 1 1 1 2 2 2 2

信号2:直流信号,其输入先后为1 1 1 1 1 1 1

信号3:高频信号,即在时域上变化快的信号,其输入先后为1 2 1 2 1 2 1 2

简单的滤波器模型

低通滤波器:1 1


信号1与低通滤波器进行卷积运算,其结果再除以2,得到如下数据:1 1 1 1.5 2 2 2。可以看到,低频信号经过低通滤波器后,各个点仍然保持了其形状,而且在1变成2时,还变平缓了。

信号2与低通滤波器进行卷积运算,其结果再除以2,得到如下数据:1 1 1 1 1 1 1。可以看到,直流信号与输入的信号完成相同。

信号3与低通滤波器进行卷积运算,其结果再除以2,得到如下数据:1.5 1.5 1.5 1.5 1.5 1.5 1.5。可以看到,高频信号经过低通滤波器后,已经完成消去了形状,变成了直流信号。


再考虑另一种滤波器模型,高通滤波器:1 -1

信号1与高通滤波器进行卷积运算,其结果再除以2,得到如下数据:0 0 0 -0.5 0 0 0。可以看到,低频信号经过高通滤波器后,信号变化基本上消失。

信号2与低通滤波器进行卷积运算,其结果再除以2,得到如下数据:0 0 0 0 0 0 0。可以看到,直流信号仍然是没有变化。

信号3与低通滤波器进行卷积运算,其结果再除以2,得到如下数据:-0.5 0.5 -0.5 0.5 -0.5 0.5 -0.5 0.5。可以看到,高频信号已经仍然保持了变化的形状。


由这两个例子可以看出,FIR滤波器其实就是信号与FIR滤波器的系数进行卷积(即乘累加)的过程。通过调整滤波器系数、抽头个数,就可实现低通、高通、带通等滤波器。



1.3 FIR滤波器的设计1.3.1 matlab产生滤波器系数

打开matlab在其命令窗口输入fdatool 按下回车


调出FIR滤波器的设计界面


511

在波形设计界面中,我们重要关注以下选项。

Response Type:选择可以选择滤波器的类型,可选择:lowpass低通滤波器、Highpass高通滤波器、bandpass带通滤波器、bandstop带阻滤波器。

Fs采样频率):

Fstop :信号截止频率

Fpass

Filter Order:用来设置滤波器的抽头个数。可以在specify order中输入个数,也可以选择Minimum order,让系统计算满足要求的前提下的最小抽头个数。


点击Design Filter,就可以计算出抽头系数。


产生系数后点击file 菜单里的Export 将系数保存到工作区


512

点击export

513

点击之后打开工作区里的Num

514

而后将下图第一列的数据复制粘贴到txt文件中

515

注意复制后需在两个系数间插入逗号(英文输入状态下的的逗号)

图片39.png

516

这样就得到滤波器的系数了。


1.3.2 FPGA生成FIR IP

打开工程后,在IP catalog这一界面中选择DSP下一目录中选择Filter 在选择选择 FIR II

图片40.png

517

首先在Fitter这一界面做如下操作

图片41.png

518


Filter Type

Interpolation Factor

Decimation Factor

Max Number of channels


Clock rate:填写本IP核的工作时钟频率。

clock slack

Input sample rate msps):采样率

点击coefficients,进入coefficients界面。

这一界面点击import from file ,弹出一下界面,找出我们之前用matlab生成的系数文件,点击import,导入成功后可以看到下图的 frequency response界面的波形发生变化

图片42.png

519


coefficient界面,还可以设置系数的格式、数据位宽等。

图片43.png

520

其它选项不改按默认的来点击finish即可。

以上就是生成 FIR滤波器的主要步骤。


2 设计目标

本次案例将使用到采样率大于100M的双通道的示波器。将示波器的两个通道,分别与FPGADA通道1DA通道2相连,观察两路DA的输出。其连接示意如下图所示。

图片44.png

521



本案例是FPGA内部产生正弦信号,这个正弦信号一路输出给DA通道1,另一路经过FIR滤波器后,输出给DA通道2

图片45.png

522

正弦信号的频率受开发板上的3个拨码开关控制,用3位信号key表示,一共可以产生8种频率。

正弦信号的频率 约等于: 100KHz * (key+1)

例如,当key等于0时,产生约100KHz的正弦信号;

key等于1时,产生约200KHz的正弦波;

key等于7时,产生约800KHz的正弦波。


FIR滤波器是低通滤波器,其截止频率是500KHz,这样原则上超过500KHz的信号就会被滤除。滤波器的输出给通道2

下面是示波器的显示效果,其中黄色是通道1输出的信号(上面的波形),下面蓝色是通道2的输出信号(下面的波形)。


下图是100KHz的信号图。

图片46.png

下图是200KHz的信号图。

图片47.png

下图是300KHz的信号图。

图片48.png

下图是400KHz的信号图,可以看到已经衰减了。

图片49.png

下图是500KHz的信号图,可以看到已经衰减的很小了。

图片50.png

下图是600KHz的信号图,可以看到通道2已经没有波形。

图片51.png

    图

下图是700KHz的信号图,可以看到通道2已经没有波形。

图片52.png

下图是800KHz的信号图,可以看到通道2已经没有波形。

       图片53.png

     图



3 设计实现3.1 顶层接口

新建目录:D:\mdy_book\fir_prj在该目录中,新建一个名为fir_prj.v的文件,并用GVIM打开,开始编写代码。


我们要实现的功能,概括起来就是FPGA产生控制AD9709,让其中的通道A未滤波的正弦信号,让通道B输出滤波后的正弦信号。为了控制AD9709的工作模式,就要控制AD9709MODESLEEP管脚;为了控制通道A,就需要控制AD9729CLK1WRT1DB7~0P1管脚;为了控制通道B,就需要控制AD9729CLK2WRT2DB7~0P2管脚。根据设计目标的要求,整个工程需要以下信号:

[size=9.5000pt]1. 使用clk连接到晶振,表示50M时钟的输入。

[size=9.5000pt]2. 使用rst_n连接到按键,表示复位信号。

[size=9.5000pt]3. 使用3位信号key,表示三位拨码开关。

[size=9.5000pt]4. 使用dac_mode信号连接到AD9709MODE管脚,用来控制其工作模式。

[size=9.5000pt]5. 使用dac_sleep信号连接到AD9709SLEEP管脚,用来控制其睡眠模式。

[size=9.5000pt]6. 使用dac_clka信号连接到AD9709CLK1管脚,用来控制通道A的时钟。

[size=9.5000pt]7. 使用dac_wra信号连接到AD9709WRT1管脚,用来控制通道A的写使能。

[size=9.5000pt]8. 使用8位信号dac_da连接到AD9709DB7~0P1管脚,用来控制通道A的写数据。

[size=9.5000pt]9. 使用dac_clkb号连接到AD9709CLK2脚,用来控制通道B时钟。

[size=9.5000pt]10. 使用dac_wrb号连接到AD9709WRT2脚,用来控制通道B使能。

[size=9.5000pt]11. 使用8位信号dac_db接到AD9709DB7~0P2脚,用来控制通道B写数据。


综上所述,我们这个工程需要11个信号,时钟clk,复位rst_n,拨码开关的输入keydac_modedac_sleepdac_clkadac_wradac_dadac_clkbdac_wrbdac_db信号,其中dac_dadac_db8位信号,其他都是1位信号。下面表格表示了硬件电路图的连接关系。


器件[size=9.5000pt]

AD9709管脚[size=9.5000pt]

原理图信号[size=9.5000pt]

FPGA管脚[size=9.5000pt]

FPGA工程信号[size=9.5000pt]

U8[size=9.5000pt]

MODE[size=9.5000pt]

DAC_MODE[size=9.5000pt]

Y4[size=9.5000pt]

dac_mode[size=9.5000pt]

SLEEP[size=9.5000pt]

DAC_SLEEP[size=9.5000pt]

H2[size=9.5000pt]

dac_sleep[size=9.5000pt]

CLK1[size=9.5000pt]

DA_CLKA[size=9.5000pt]

R2[size=9.5000pt]

dac_clka[size=9.5000pt]

WRT1[size=9.5000pt]

DA_WRA[size=9.5000pt]

U1[size=9.5000pt]

dac_wra[size=9.5000pt]

DB7P1[size=9.5000pt]

DAC_DA7[size=9.5000pt]

AA1[size=9.5000pt]

dac_da[7][size=9.5000pt]

DB6P1[size=9.5000pt]

DAC_DA6[size=9.5000pt]

Y2[size=9.5000pt]

dac_da[6][size=9.5000pt]

DB5P1[size=9.5000pt]

DAC_DA5[size=9.5000pt]

Y1[size=9.5000pt]

dac_da[5][size=9.5000pt]

DB4P1[size=9.5000pt]

DAC_DA4[size=9.5000pt]

W2[size=9.5000pt]

dac_da[4][size=9.5000pt]

DB3P1[size=9.5000pt]

DAC_DA3[size=9.5000pt]

W1[size=9.5000pt]

dac_da[3][size=9.5000pt]

DB2P1[size=9.5000pt]

DAC_DA2[size=9.5000pt]

V2[size=9.5000pt]

dac_da[2][size=9.5000pt]

DB1P1[size=9.5000pt]

DAC_DA1[size=9.5000pt]

V1[size=9.5000pt]

dac_da[1][size=9.5000pt]

DB0P1[size=9.5000pt]

DAC_DA0[size=9.5000pt]

U2[size=9.5000pt]

dac_da[0][size=9.5000pt]

CLK2[size=9.5000pt]

DA_CLKB[size=9.5000pt]

R1[size=9.5000pt]

dac_clkb[size=9.5000pt]

WRT2[size=9.5000pt]

DA_WRB[size=9.5000pt]

P2[size=9.5000pt]

dac_wrb[size=9.5000pt]

DB7P2[size=9.5000pt]

DAC_DB7[size=9.5000pt]

P1[size=9.5000pt]

dac_db[7][size=9.5000pt]

DB6P2[size=9.5000pt]

DAC_DB6[size=9.5000pt]

N2[size=9.5000pt]

dac_db[6][size=9.5000pt]

DB5P2[size=9.5000pt]

DAC_DB5[size=9.5000pt]

N1[size=9.5000pt]

dac_db[5][size=9.5000pt]

DB4P2[size=9.5000pt]

DAC_DB4[size=9.5000pt]

M2[size=9.5000pt]

dac_db[4][size=9.5000pt]

DB3P2[size=9.5000pt]

DAC_DB3[size=9.5000pt]

M1[size=9.5000pt]

dac_db[3][size=9.5000pt]

DB2P2[size=9.5000pt]

DAC_DB2[size=9.5000pt]

J1[size=9.5000pt]

dac_db[2][size=9.5000pt]

DB1P2[size=9.5000pt]

DAC_DB1[size=9.5000pt]

J2[size=9.5000pt]

dac_db[1][size=9.5000pt]

DB0P2[size=9.5000pt]

DAC_DB0[size=9.5000pt]

H1[size=9.5000pt]

dac_db[0][size=9.5000pt]

X1[size=9.5000pt]


SYS_CLK[size=9.5000pt]

G1[size=9.5000pt]

clk[size=9.5000pt]

K1[size=9.5000pt]


SYS_RST[size=9.5000pt]

AB12[size=9.5000pt]

rst_n[size=9.5000pt]



module的名称定义为fir_prj,代码如下:


[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

[size=9.5000pt]4[size=9.5000pt]

[size=9.5000pt]5[size=9.5000pt]

[size=9.5000pt]6[size=9.5000pt]

[size=9.5000pt]7[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

[size=9.5000pt]9[size=9.5000pt]

module fir_prj([size=9.5000pt]

           clk       ,[size=9.5000pt]

           rst_n     ,[size=9.5000pt]

           key       ,[size=9.5000pt]

           dac_mode ,[size=9.5000pt]

           dac_sleep ,[size=9.5000pt]

           dac_clka  ,[size=9.5000pt]

           dac_da   ,[size=9.5000pt]

           dac_wra  ,[size=9.5000pt]

           dac_clkb  ,[size=9.5000pt]

           dac_db   ,[size=9.5000pt]

           dac_wrb               [size=9.5000pt]

           );[size=9.5000pt]


其中clkrst_n1位的输入信号,dac_dadac_db8位的输出信号,key3位输入信号,dac_modedac_clkadac_wradac_sleepdac_clkbdac_wrb是一位输出信号。


[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

[size=9.5000pt]4[size=9.5000pt]

[size=9.5000pt]5[size=9.5000pt]

[size=9.5000pt]6[size=9.5000pt]

[size=9.5000pt]7[size=9.5000pt]

input             clk        ;[size=9.5000pt]

input             rst_n      ;[size=9.5000pt]

input  [ 3-1:0]    key        ;[size=9.5000pt]

output            dac_mode ;[size=9.5000pt]

output            dac_clka  ;[size=9.5000pt]

output [ 8-1:0]    dac_da    ;[size=9.5000pt]

output            dac_wra   ;[size=9.5000pt]

output            dac_sleep ;[size=9.5000pt]

output            dac_clkb  ;[size=9.5000pt]

output [ 8-1:0]    dac_db    ;[size=9.5000pt]

output            dac_wrb   ;[size=9.5000pt]




3.2 正弦信号设计

假设产生的正弦信号命名为sin_data信号。sin_data是从表XX中选择出来的值,该表一共有128个点。该表的产生方法,请看案例“信号发生器和DA转换”一章的内容。

采样点i[size=9.0000pt]

sin_data[size=9.0000pt]

16进制)[size=9.0000pt]

采样点i[size=9.0000pt]

sin_data[size=9.0000pt]

16进制)[size=9.0000pt]

采样点i[size=9.0000pt]

sin_data[size=9.0000pt]

16进制)[size=9.0000pt]

采样点i[size=9.0000pt]

sin_data[size=9.0000pt]

16进制)[size=9.0000pt]

[size=9.0000pt]0[size=9.0000pt]

7F[size=9.0000pt]

32[size=9.0000pt]

FE[size=9.0000pt]

64[size=9.0000pt]

7D[size=9.0000pt]

96[size=9.0000pt]

[size=9.0000pt]1[size=9.0000pt]

[size=9.0000pt]1[size=9.0000pt]

85[size=9.0000pt]

33[size=9.0000pt]

FE[size=9.0000pt]

65[size=9.0000pt]

77[size=9.0000pt]

97[size=9.0000pt]

[size=9.0000pt]1[size=9.0000pt]

[size=9.0000pt]2[size=9.0000pt]

8C[size=9.0000pt]

34[size=9.0000pt]

FE[size=9.0000pt]

66[size=9.0000pt]

70[size=9.0000pt]

98[size=9.0000pt]

[size=9.0000pt]2[size=9.0000pt]

[size=9.0000pt]3[size=9.0000pt]

92[size=9.0000pt]

35[size=9.0000pt]

FD[size=9.0000pt]

67[size=9.0000pt]

6A[size=9.0000pt]

99[size=9.0000pt]

[size=9.0000pt]3[size=9.0000pt]

[size=9.0000pt]4[size=9.0000pt]

98[size=9.0000pt]

36[size=9.0000pt]

FC[size=9.0000pt]

68[size=9.0000pt]

64[size=9.0000pt]

100[size=9.0000pt]

[size=9.0000pt]4[size=9.0000pt]

[size=9.0000pt]5[size=9.0000pt]

9E[size=9.0000pt]

37[size=9.0000pt]

FA[size=9.0000pt]

69[size=9.0000pt]

5E[size=9.0000pt]

101[size=9.0000pt]

[size=9.0000pt]6[size=9.0000pt]

[size=9.0000pt]6[size=9.0000pt]

A4[size=9.0000pt]

38[size=9.0000pt]

F8[size=9.0000pt]

70[size=9.0000pt]

58[size=9.0000pt]

102[size=9.0000pt]

[size=9.0000pt]7[size=9.0000pt]

[size=9.0000pt]7[size=9.0000pt]

AA[size=9.0000pt]

39[size=9.0000pt]

F6[size=9.0000pt]

71[size=9.0000pt]

52[size=9.0000pt]

103[size=9.0000pt]

[size=9.0000pt]A[size=9.0000pt]

[size=9.0000pt]8[size=9.0000pt]

B0[size=9.0000pt]

40[size=9.0000pt]

F4[size=9.0000pt]

72[size=9.0000pt]

4C[size=9.0000pt]

104[size=9.0000pt]

[size=9.0000pt]C[size=9.0000pt]

[size=9.0000pt]9[size=9.0000pt]

B6[size=9.0000pt]

41[size=9.0000pt]

F1[size=9.0000pt]

73[size=9.0000pt]

46[size=9.0000pt]

105[size=9.0000pt]

[size=9.0000pt]F[size=9.0000pt]

10[size=9.0000pt]

BC[size=9.0000pt]

42[size=9.0000pt]

EF[size=9.0000pt]

74[size=9.0000pt]

41[size=9.0000pt]

106[size=9.0000pt]

12[size=9.0000pt]

11[size=9.0000pt]

C1[size=9.0000pt]

43[size=9.0000pt]

EB[size=9.0000pt]

75[size=9.0000pt]

3C[size=9.0000pt]

107[size=9.0000pt]

15[size=9.0000pt]

12[size=9.0000pt]

C6[size=9.0000pt]

44[size=9.0000pt]

E8[size=9.0000pt]

76[size=9.0000pt]

36[size=9.0000pt]

108[size=9.0000pt]

19[size=9.0000pt]

13[size=9.0000pt]

CB[size=9.0000pt]

45[size=9.0000pt]

E4[size=9.0000pt]

77[size=9.0000pt]

31[size=9.0000pt]

109[size=9.0000pt]

1D[size=9.0000pt]

14[size=9.0000pt]

D0[size=9.0000pt]

46[size=9.0000pt]

E0[size=9.0000pt]

78[size=9.0000pt]

2C[size=9.0000pt]

110[size=9.0000pt]

21[size=9.0000pt]

15[size=9.0000pt]

D5[size=9.0000pt]

47[size=9.0000pt]

DC[size=9.0000pt]

79[size=9.0000pt]

28[size=9.0000pt]

111[size=9.0000pt]

25[size=9.0000pt]

16[size=9.0000pt]

DA[size=9.0000pt]

48[size=9.0000pt]

D8[size=9.0000pt]

80[size=9.0000pt]

23[size=9.0000pt]

112[size=9.0000pt]

2A[size=9.0000pt]

17[size=9.0000pt]

DE[size=9.0000pt]

49[size=9.0000pt]

D3[size=9.0000pt]

81[size=9.0000pt]

1F[size=9.0000pt]

113[size=9.0000pt]

2E[size=9.0000pt]

18[size=9.0000pt]

E2[size=9.0000pt]

50[size=9.0000pt]

CE[size=9.0000pt]

82[size=9.0000pt]

1B[size=9.0000pt]

114[size=9.0000pt]

33[size=9.0000pt]

19[size=9.0000pt]

E6[size=9.0000pt]

51[size=9.0000pt]

C9[size=9.0000pt]

83[size=9.0000pt]

17[size=9.0000pt]

115[size=9.0000pt]

38[size=9.0000pt]

20[size=9.0000pt]

EA[size=9.0000pt]

52[size=9.0000pt]

C4[size=9.0000pt]

84[size=9.0000pt]

14[size=9.0000pt]

116[size=9.0000pt]

3E[size=9.0000pt]

21[size=9.0000pt]

ED[size=9.0000pt]

53[size=9.0000pt]

BE[size=9.0000pt]

85[size=9.0000pt]

11[size=9.0000pt]

117[size=9.0000pt]

43[size=9.0000pt]

22[size=9.0000pt]

F0[size=9.0000pt]

54[size=9.0000pt]

B9[size=9.0000pt]

86[size=9.0000pt]

[size=9.0000pt]E[size=9.0000pt]

118[size=9.0000pt]

49[size=9.0000pt]

23[size=9.0000pt]

F3[size=9.0000pt]

55[size=9.0000pt]

B3[size=9.0000pt]

87[size=9.0000pt]

[size=9.0000pt]B[size=9.0000pt]

119[size=9.0000pt]

4E[size=9.0000pt]

24[size=9.0000pt]

F5[size=9.0000pt]

56[size=9.0000pt]

AD[size=9.0000pt]

88[size=9.0000pt]

[size=9.0000pt]9[size=9.0000pt]

120[size=9.0000pt]

54[size=9.0000pt]

25[size=9.0000pt]

F7[size=9.0000pt]

57[size=9.0000pt]

A7[size=9.0000pt]

89[size=9.0000pt]

[size=9.0000pt]7[size=9.0000pt]

121[size=9.0000pt]

5A[size=9.0000pt]

26[size=9.0000pt]

F9[size=9.0000pt]

58[size=9.0000pt]

A1[size=9.0000pt]

90[size=9.0000pt]

[size=9.0000pt]5[size=9.0000pt]

122[size=9.0000pt]

60[size=9.0000pt]

27[size=9.0000pt]

FB[size=9.0000pt]

59[size=9.0000pt]

9B[size=9.0000pt]

91[size=9.0000pt]

[size=9.0000pt]3[size=9.0000pt]

123[size=9.0000pt]

67[size=9.0000pt]

28[size=9.0000pt]

FC[size=9.0000pt]

60[size=9.0000pt]

95[size=9.0000pt]

92[size=9.0000pt]

[size=9.0000pt]2[size=9.0000pt]

124[size=9.0000pt]

6D[size=9.0000pt]

29[size=9.0000pt]

FD[size=9.0000pt]

61[size=9.0000pt]

8F[size=9.0000pt]

93[size=9.0000pt]

[size=9.0000pt]1[size=9.0000pt]

125[size=9.0000pt]

73[size=9.0000pt]

30[size=9.0000pt]

FE[size=9.0000pt]

62[size=9.0000pt]

89[size=9.0000pt]

94[size=9.0000pt]

[size=9.0000pt]1[size=9.0000pt]

126[size=9.0000pt]

79[size=9.0000pt]

31[size=9.0000pt]

FE[size=9.0000pt]

63[size=9.0000pt]

82[size=9.0000pt]

95[size=9.0000pt]

[size=9.0000pt]1[size=9.0000pt]

127[size=9.0000pt]

7F[size=9.0000pt]


很自然地定义一个7位的选择信号addr。我们只要控制好addr,就能方便得到sin_data。因此可以写出下面代码。


[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

[size=9.5000pt]4[size=9.5000pt]

[size=9.5000pt]5[size=9.5000pt]

[size=9.5000pt]6[size=9.5000pt]

[size=9.5000pt]7[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

[size=9.5000pt]9[size=9.5000pt]

always  @(*)begin[size=9.5000pt]

    case(addr)[size=9.5000pt]

          0: sin_data = 8'h7F;[size=9.5000pt]

          1: sin_data = 8'h85;[size=9.5000pt]

          2: sin_data = 8'h8C;[size=9.5000pt]

          3: sin_data = 8'h92;[size=9.5000pt]

          4: sin_data = 8'h98;[size=9.5000pt]

          5: sin_data = 8'h9E;[size=9.5000pt]

          6: sin_data = 8'hA4;[size=9.5000pt]

          7: sin_data = 8'hAA;[size=9.5000pt]

          8: sin_data = 8'hB0;[size=9.5000pt]

          9: sin_data = 8'hB6;[size=9.5000pt]

         10: sin_data = 8'hBC;[size=9.5000pt]

         11: sin_data = 8'hC1;[size=9.5000pt]

         12: sin_data = 8'hC6;[size=9.5000pt]

         13: sin_data = 8'hCB;[size=9.5000pt]

         14: sin_data = 8'hD0;[size=9.5000pt]

         15: sin_data = 8'hD5;[size=9.5000pt]

         16: sin_data = 8'hDA;[size=9.5000pt]

         17: sin_data = 8'hDE;[size=9.5000pt]

         18: sin_data = 8'hE2;[size=9.5000pt]

         19: sin_data = 8'hE6;[size=9.5000pt]

         20: sin_data = 8'hEA;[size=9.5000pt]

         21: sin_data = 8'hED;[size=9.5000pt]

         22: sin_data = 8'hF0;[size=9.5000pt]

         23: sin_data = 8'hF3;[size=9.5000pt]

         24: sin_data = 8'hF5;[size=9.5000pt]

         25: sin_data = 8'hF7;[size=9.5000pt]

         26: sin_data = 8'hF9;[size=9.5000pt]

         27: sin_data = 8'hFB;[size=9.5000pt]

         28: sin_data = 8'hFC;[size=9.5000pt]

         29: sin_data = 8'hFD;[size=9.5000pt]

         30: sin_data = 8'hFE;[size=9.5000pt]

         31: sin_data = 8'hFE;[size=9.5000pt]

         32: sin_data = 8'hFE;[size=9.5000pt]

         33: sin_data = 8'hFE;[size=9.5000pt]

         34: sin_data = 8'hFE;[size=9.5000pt]

         35: sin_data = 8'hFD;[size=9.5000pt]

         36: sin_data = 8'hFC;[size=9.5000pt]

         37: sin_data = 8'hFA;[size=9.5000pt]

         38: sin_data = 8'hF8;[size=9.5000pt]

         39: sin_data = 8'hF6;[size=9.5000pt]

         40: sin_data = 8'hF4;[size=9.5000pt]

         41: sin_data = 8'hF1;[size=9.5000pt]

         42: sin_data = 8'hEF;[size=9.5000pt]

         43: sin_data = 8'hEB;[size=9.5000pt]

         44: sin_data = 8'hE8;[size=9.5000pt]

         45: sin_data = 8'hE4;[size=9.5000pt]

         46: sin_data = 8'hE0;[size=9.5000pt]

         47: sin_data = 8'hDC;[size=9.5000pt]

         48: sin_data = 8'hD8;[size=9.5000pt]

         49: sin_data = 8'hD3;[size=9.5000pt]

         50: sin_data = 8'hCE;[size=9.5000pt]

         51: sin_data = 8'hC9;[size=9.5000pt]

         52: sin_data = 8'hC4;[size=9.5000pt]

         53: sin_data = 8'hBE;[size=9.5000pt]

         54: sin_data = 8'hB9;[size=9.5000pt]

         55: sin_data = 8'hB3;[size=9.5000pt]

         56: sin_data = 8'hAD;[size=9.5000pt]

         57: sin_data = 8'hA7;[size=9.5000pt]

         58: sin_data = 8'hA1;[size=9.5000pt]

         59: sin_data = 8'h9B;[size=9.5000pt]

         60: sin_data = 8'h95;[size=9.5000pt]

         61: sin_data = 8'h8F;[size=9.5000pt]

         62: sin_data = 8'h89;[size=9.5000pt]

         63: sin_data = 8'h82;[size=9.5000pt]

         64: sin_data = 8'h7D;[size=9.5000pt]

         65: sin_data = 8'h77;[size=9.5000pt]

         66: sin_data = 8'h70;[size=9.5000pt]

         67: sin_data = 8'h6A;[size=9.5000pt]

         68: sin_data = 8'h64;[size=9.5000pt]

         69: sin_data = 8'h5E;[size=9.5000pt]

         70: sin_data = 8'h58;[size=9.5000pt]

         71: sin_data = 8'h52;[size=9.5000pt]

         72: sin_data = 8'h4C;[size=9.5000pt]

         73: sin_data = 8'h46;[size=9.5000pt]

         74: sin_data = 8'h41;[size=9.5000pt]

         75: sin_data = 8'h3C;[size=9.5000pt]

         76: sin_data = 8'h36;[size=9.5000pt]

         77: sin_data = 8'h31;[size=9.5000pt]

         78: sin_data = 8'h2C;[size=9.5000pt]

         79: sin_data = 8'h28;[size=9.5000pt]

         80: sin_data = 8'h23;[size=9.5000pt]

         81: sin_data = 8'h1F;[size=9.5000pt]

         82: sin_data = 8'h1B;[size=9.5000pt]

         83: sin_data = 8'h17;[size=9.5000pt]

         84: sin_data = 8'h14;[size=9.5000pt]

         85: sin_data = 8'h11;[size=9.5000pt]

         86: sin_data = 8'hE ;[size=9.5000pt]

         87: sin_data = 8'hB ;[size=9.5000pt]

         88: sin_data = 8'h9 ;[size=9.5000pt]

         89: sin_data = 8'h7 ;[size=9.5000pt]

         90: sin_data = 8'h5 ;[size=9.5000pt]

         91: sin_data = 8'h3 ;[size=9.5000pt]

         92: sin_data = 8'h2 ;[size=9.5000pt]

         93: sin_data = 8'h1 ;[size=9.5000pt]

         94: sin_data = 8'h1 ;[size=9.5000pt]

         95: sin_data = 8'h1 ;[size=9.5000pt]

         96: sin_data = 8'h1 ;[size=9.5000pt]

         97: sin_data = 8'h1 ;[size=9.5000pt]

         98: sin_data = 8'h2 ;[size=9.5000pt]

         99: sin_data = 8'h3 ;[size=9.5000pt]

        100: sin_data = 8'h4 ;[size=9.5000pt]

        101: sin_data = 8'h6 ;[size=9.5000pt]

        102: sin_data = 8'h7 ;[size=9.5000pt]

        103: sin_data = 8'hA ;[size=9.5000pt]

        104: sin_data = 8'hC ;[size=9.5000pt]

        105: sin_data = 8'hF ;[size=9.5000pt]

        106: sin_data = 8'h12;[size=9.5000pt]

        107: sin_data = 8'h15;[size=9.5000pt]

        108: sin_data = 8'h19;[size=9.5000pt]

        109: sin_data = 8'h1D;[size=9.5000pt]

        110: sin_data = 8'h21;[size=9.5000pt]

        111: sin_data = 8'h25;[size=9.5000pt]

        112: sin_data = 8'h2A;[size=9.5000pt]

        113: sin_data = 8'h2E;[size=9.5000pt]

        114: sin_data = 8'h33;[size=9.5000pt]

        115: sin_data = 8'h38;[size=9.5000pt]

        116: sin_data = 8'h3E;[size=9.5000pt]

        117: sin_data = 8'h43;[size=9.5000pt]

        118: sin_data = 8'h49;[size=9.5000pt]

        119: sin_data = 8'h4E;[size=9.5000pt]

        120: sin_data = 8'h54;[size=9.5000pt]

        121: sin_data = 8'h5A;[size=9.5000pt]

        122: sin_data = 8'h60;[size=9.5000pt]

        123: sin_data = 8'h67;[size=9.5000pt]

        124: sin_data = 8'h6D;[size=9.5000pt]

        125: sin_data = 8'h73;[size=9.5000pt]

        126: sin_data = 8'h79;[size=9.5000pt]

        127: sin_data = 8'h7F;[size=9.5000pt]

    endcase[size=9.5000pt]

end[size=9.5000pt]


接下来是设计信号addr

addr是用来控制选择数据的地址,通过控制addr的增加值,就能产生多种频率的正弦波。

以频率为100KHz的正弦信号为例。该正弦信号的周期是10000ns。本工程的工作时钟是20ns,也就是10000/20 = 500个时钟输出一个正弦信号,也就是500个时钟将上表的128个值输出一遍。因此每个时钟addr增加的值:128/500 = 0.256

按同样的分析方法,可以得到其他信号频率的addr增加值,总结如下。

100KHz的正弦信号,每个时钟addr增加:128/250      = 0.256

200KHz的正弦信号,每个时钟addr增加:128/250      = 0.512

300KHz的正弦信号,每个时钟addr增加:128/166.6667 = 0.7679

400KHz的正弦信号,每个时钟addr增加:128/125      = 1.024

500KHz的正弦信号,每个时钟addr增加:128/100      = 1.28  

600KHz的正弦信号,每个时钟addr增加:128/83.3333  = 1.5358

700KHz的正弦信号,每个时钟addr增加:128/71.4286  = 1.792

800KHz的正弦信号,每个时钟addr增加:128/62.5      = 2.048


由于addr是表示0~127的整数,而addr每次增加的值包含小数,而FPGA是没有小数的。为此,我们将上面的小数乘以1024,然后取整,就变成了每次要增加的整数,结果保存到addr_tmp中。即:

100KHz的正弦信号,每个时钟addr_tmp增加:0.256   *1024 = 262.144 262

200KHz的正弦信号,每个时钟addr_tmp增加:0.512   *1024 = 524.288 524

300KHz的正弦信号,每个时钟addr_tmp增加:0.7679  *1024 =786.3296 786

400KHz的正弦信号,每个时钟addr_tmp增加:1.024   *1024 =1028.576 1029

500KHz的正弦信号,每个时钟addr_tmp增加:1.28    *1024 =1310.72  1311

600KHz的正弦信号,每个时钟addr_tmp增加:1.5358  *1024 =1572.6592 1573

700KHz的正弦信号,每个时钟addr_tmp增加:1.792   *1024 =1835.008 1835

800KHz的正弦信号,每个时钟addr_tmp增加: 2.048  *1024 =2097.152 2097


而上面8种频率信号,是由拨码信号key控制的。因此,可以写出addr_tmp的代码。

[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

always  @(posedge clk or negedge rst_n)begin[size=9.5000pt]

    if(rst_n==1'b0)begin[size=9.5000pt]

        addr_tmp <= 0;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==0) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 262;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==1) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 524;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==2) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 786;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==3) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 1029;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==4) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 1311;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==5) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 1573;[size=9.5000pt]

    end[size=9.5000pt]

    else if(key==6) begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 1835;[size=9.5000pt]

    end[size=9.5000pt]

    else begin[size=9.5000pt]

        addr_tmp <= addr_tmp + 2097;[size=9.5000pt]

    end[size=9.5000pt]

end[size=9.5000pt]


上面的代码中,addr_tmp是小数乘以1024后得到的,那么最终addr_tmp要除以1024,再赋给addr。除以1024,其实就是向右移10位。addr_tmp向各移10位后,保留7位结果赋给addr就够了。所以addr_tmp位宽为17位。


[size=9.5000pt]1[size=9.5000pt]

assign addr = addr_tmp >>10 ;[size=9.5000pt]



3.3 FIR滤波器设计3.3.1 matlab生成FIR系数

打开matlab,在其命令窗口输入fdatool 按下回车调出波形设计界面。

图片33.png

在波形设计界面中

Response Type:案例要求滤波高于500KHz的信号,所以选择lowpass低通滤波器

Fstop: 截止频率设为600KHz

Fs采样频率: 12.5MHz(12500Khz)

图片54.png

526

其它选项默认点击Design Filter



产生系数后点击file 菜单里的Export 将系数保存的工作区

图片55.png

527

点击export

图片56.png

528

点击之后打开工作区里的Num

图片57.png

529

而后将下图第一列的数据复制粘贴到txt文件中

图片58.png

530

注意复制后需在两个系数间插入逗号(英文输入状态下的的逗号)

图片59.png

531


3.3.2 新建FPGA工程


图片60.png

532


1.)打开quartus,点击File File菜单中选择New Project Wizard....


图片61.png

533

2.弹出Introduction界面选择Next


图片62.png

534


(3)设置工程目录,工程名,顶层模块名

工程目录设置为:D:\mdy_book\fir_prj

工程名:fir_prj

顶层模块名:fir_prj

填写完毕后,点击next之后进入下一界面。


图片63.png

535

工程类型界面,Project Type选择Empty project,选择空白工程。点Next进入下一个界面。


图片64.png

536



3.)在文件添加界面,不选择任何文件。点击Next,进入下一个界面。


图片65.png

537


4.)器件选择界面。在Device family这一项之中选择 Cyclone IV E;在下部的Available device 选择EP4CE6F23C8。完成后直接点击Finish



3.3.3 FPGA生成FIR IP

图片66.png

538

建立工程后,在quartusIP catalog这一界面中选择DSP下一目录中选择Filter 再选择 FIR II


图片67.png

539

点击后进入此界面给新生成的fir滤波器ip核选择如下路径:D:\mdy_book\fir_prj\my_fir.vIPvariation file name这一项选择verilog。点击OK后,进入FIR滤波器设置界面。


图片68.png

540


Fitter specification界面按如下设置:

Filter Type:要选择Single Rate,表示只采用一种采样率。

Clock Rate:因为我们工程使用的是50MHz时钟,所以此处要填写50MHz

Input Sample Rate (PSPS):这个是填采样率。和matlab相匹配,因此要填12.5MHz

其他参数默认。

然后点击coefficients选项卡。

图片69.png

541


单击import from file ,在输出的界面中,找出我们用MATLAB生成的系数文件:my_fir_coe.txt,点击import导入。导入成功后可以看到下图的 frequency response界面的波形发生变化。

在Coefficient Bit Width中,填写16。表示每个系数用16比特量化。

图片70.png

543

如上图,在Input/Output Options选项卡中,做如下设置。

Input Type:选择Signed Binary,表示输入的数据是有符号数(补码形式)。

Input Width:输入8。表示输入的数据是8位位宽。

Output Type:选择Signed Binary,表示输出的数据是有符号数(补码形式)。

MSB Rounding:选择Truncation。表示输出结果的高位要截断。

MSB Bits to Remove:填写3。表示MSB要截取3个符号位。

LSB Rounding:选择Truncation。表示输出结果的低位要截断。

LSB Bits to Remove:填写19。表示LSB要截断低19位。这样最终输出的结果就是8位。

其他选项默认,点击Finish,软件就会去生成FIR IP核。



图片71.png

544

出现上面的提示,就是生成成功了。


图片72.png

545

IP核生成后弹出此对话框点击yes 将此IP核添加进工程。




3.3.4 例化FIR IP

GVIM打开D:\mdy_book\fir_prj\my_fir.v文件,该文件就是生成的FIR IP核文件。

图片73.png

546

my_fir模块的各个信号的描述见下表。

信号名[size=9.5000pt]

I/O[size=9.5000pt]

位宽[size=9.5000pt]

作用[size=9.5000pt]

clk[size=9.5000pt]

[size=9.5000pt]I[size=9.5000pt]

[size=9.5000pt]1[size=9.5000pt]

时钟输入信号。在FIR设置时,就已经填写了50MHz,所以此时连接50MHz时钟。[size=9.5000pt]

reset_n[size=9.5000pt]

[size=9.5000pt]I[size=9.5000pt]

[size=9.5000pt]1[size=9.5000pt]

复位信号,低电平有效。[size=9.5000pt]

ast_sink_data[size=9.5000pt]

[size=9.5000pt]I[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

FIR滤波器输入的数据输入。注意,输入的是有符号数。[size=9.5000pt]

ast_sink_valid[size=9.5000pt]

[size=9.5000pt]I[size=9.5000pt]

[size=9.5000pt]1[size=9.5000pt]

FIR滤波器输入的数据有效指示信号。[size=9.5000pt]

ast_sink_error[size=9.5000pt]

[size=9.5000pt]I[size=9.5000pt]

[size=9.5000pt]1[size=9.5000pt]

输入数据错误指示信号。实在想不出有啥错误情况,所以此处直接填0[size=9.5000pt]

ast_source_data[size=9.5000pt]

[size=9.5000pt]O[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

FIR滤波器的输出。注意,是有符号数。[size=9.5000pt]

ast_source_valid[size=9.5000pt]

[size=9.5000pt]O[size=9.5000pt]

[size=9.5000pt]1[size=9.5000pt]

FIR滤波器输出有效指示信号。由于输入一直有效,那么输出也一直有效,此信号可以忽略不用,例化时不连接。[size=9.5000pt]

ast_source_error[size=9.5000pt]

[size=9.5000pt]O[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

FIR滤波器输出错误指示信号。由于输入没错误,输出也不会有错误,所以可以忽略该信号,例化时不连接。[size=9.5000pt]


特别注意的是,滤波器的输入数据和输出数据都是有符号数(补码的形式,-128~127)。而我们知道,正弦信sin_data是无符号数(0~255)。所以要将sin_data变成有符号数,再送给FIR进行滤波。假设转换后的信号为fir_din,该信号位宽为8位。

无符号数转成有符号数的方法很简单:fir_din = sin_data - 128。读者有兴趣可以验证一下。


生成FIR IP核后,我们要对其进行例化,才行使用上这个IP核,例化名起名u_my_firfir的输出数据信号命名为fir_dout

[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

[size=9.5000pt]4[size=9.5000pt]

[size=9.5000pt]5[size=9.5000pt]

[size=9.5000pt]6[size=9.5000pt]

[size=9.5000pt]7[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

assign fir_din = sin_data - 128;[size=9.5000pt]


my_fir u_my_fir([size=9.5000pt]



.clk             (clk     ) ,              [size=9.5000pt]



.reset_n         (rst_n   ) ,          [size=9.5000pt]



.ast_sink_data   (fir_din ) ,    [size=9.5000pt]



.ast_sink_valid  (1       ) ,   [size=9.5000pt]



.ast_sink_error  (0       ) ,   [size=9.5000pt]



.ast_source_data (fir_dout) ,  [size=9.5000pt]



.ast_source_valid(        ) , [size=9.5000pt]



.ast_source_error(        )    [size=9.5000pt]


);[size=9.5000pt]




3.4 DA接口信号设计

接下来是设计信号dac_dadac_da是直接输出正弦信号,但由于DA的输出电压与dac_da是成反比例线性关系,所以dac_da都是按(255-sin_data)得到。那么可以写出dac_da的代码。

[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

[size=9.5000pt]4[size=9.5000pt]

[size=9.5000pt]5[size=9.5000pt]

[size=9.5000pt]6[size=9.5000pt]

[size=9.5000pt]7[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

always  @(posedge clk or negedge rst_n)begin[size=9.5000pt]

    if(rst_n==1'b0)begin[size=9.5000pt]

        dac_da <= 0;[size=9.5000pt]

    end[size=9.5000pt]

    else begin[size=9.5000pt]

        dac_da <= 255 - sin_data;[size=9.5000pt]

    end[size=9.5000pt]

end[size=9.5000pt]


接下来是设计信号dac_sleepAD是一直工作的,所以要让dac_sleep一直为0

dac_clka为了满足tS的时间要求,可以让dac_clka = ~clk

dac_wra可以与dac_clka相同。


[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

assign dac_sleep = 0        ;[size=9.5000pt]

assign dac_wra   = dac_clka ;[size=9.5000pt]

assign dac_clka  = ~clk      ;[size=9.5000pt]


接下来是设计信号dac_dbdac_db是直接输出滤波后的信号fir_dout。但要注意的是fir_dout是有符号数(范围是-128~127),所以要转有无符号数(0~255)。假设转换后的信号为fir_dout2,则fir_dout2 = fir_dout + 128。另外,由于DA的通道2的输出电压与dac_db是成反比例线性关系,所以dac_db都是按(255-fir_dout2)得到。那么可以写出dac_db的代码。

[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

[size=9.5000pt]4[size=9.5000pt]

[size=9.5000pt]5[size=9.5000pt]

[size=9.5000pt]6[size=9.5000pt]

[size=9.5000pt]7[size=9.5000pt]

[size=9.5000pt]8[size=9.5000pt]

assign fir_dout2 = fir_dout + 128;[size=9.5000pt]

always  @(posedge clk or negedge rst_n)begin[size=9.5000pt]

    if(rst_n==1'b0)begin[size=9.5000pt]

        dac_d[size=9.5000pt]b<= 0;[size=9.5000pt]

    end[size=9.5000pt]

    else begin[size=9.5000pt]

        dac_d[size=9.5000pt]b<= 255 - fir[size=9.5000pt]_dout2[size=9.5000pt];[size=9.5000pt]

    end[size=9.5000pt]

end[size=9.5000pt]

dac_clkb为了满足tS的时间要求,可以让dac_clkb = ~clk

dac_wrb可以与dac_clkb相同。


[size=9.5000pt]1[size=9.5000pt]

[size=9.5000pt]2[size=9.5000pt]

[size=9.5000pt]3[size=9.5000pt]

assign dac_wrb   = dac_clkb ;[size=9.5000pt]

assign dac_clkb  = ~clk      ;[size=9.5000pt]


3.5 信号定义

至此,模块主体已经完成。接下来是将module补充完整。

addr是用assign设计的,因此类型为wire。其值最大为127,一共有7根线,位宽为7,故而代码如下


[size=9.5000pt]1[size=9.5000pt]

wire    [6:0]    addr    ;[size=9.5000pt]


addr_tmp是用always设计的,因此类型为reg。如前面所述,该信号的位宽是17,故而代码如下


[size=9.5000pt]1[size=9.5000pt]

reg   [16:0]    addr_tmp    ;[size=9.5000pt]


sin_data是用always设计的,因此类型为reg。其最大值为255,要有8根线表示,位宽为8,故而代码如下


[size=9.5000pt]1[size=9.5000pt]

reg   [7:0]    sin_data    ;[size=9.5000pt]


fir_din是用assign设计的,因此类型为wire。其位宽为8,故而代码如下


[size=9.5000pt]1[size=9.5000pt]

wire    [7:0]    fir_din    ;[size=9.5000pt]


fir_dout是用例化模块的输出,非always设计的,因此类型为wire。其位宽为8,故而代码如下


[size=9.5000pt]1[size=9.5000pt]

wire    [7:0]    fir_dout    ;[size=9.5000pt]


fir_dout2是用assign设计的,非always设计的,因此类型为wire。其位宽为8,故而代码如下


[size=9.5000pt]1[size=9.5000pt]

wire    [7:0]    fir_dout2    ;[size=9.5000pt]



dac_da是用always设计的,因此类型为reg。其位宽为8dac_sleep是用assign设计的,因此类型为wire,位宽为1dac_wra是用assign设计的,因此类型为wire,位宽为1dac_clka是用assign设计的,因此类型为wire,位宽为1dac_mode是用assign设计的,因此类型为wire,位宽为1。故而代码如下


[size=9.5000pt]1[size=9.5000pt]

reg   [7:0]    dac_da    ;[size=9.5000pt]

wire          dac_sleep  ;[size=9.5000pt]

wire          dac_wra   ;[size=9.5000pt]

wire          dac_clka   ;[size=9.5000pt]

wire          dac_mode ;[size=9.5000pt]


dac_db是用always设计的,因此类型为reg。其位宽为8dac_wrb是用assign设计的,因此类型为wire,位宽为1dac_clkb是用assign设计的,因此类型为wire,位宽为1。故而代码如下


[size=9.5000pt]1[size=9.5000pt]

reg   [7:0]    dac_db    ;[size=9.5000pt]

wire          dac_wrb   ;[size=9.5000pt]

wire          dac_clkb   ;[size=9.5000pt]


在代码的最后一行写下endmodule

[size=9.5000pt]1[size=9.5000pt]

endmodule[size=9.5000pt]



至此,整个代码的设计工作已经完成。下一步是新建工程和上板查看现象。

图片62.png
图片67.png
图片70.png
发表于 2018-11-19 17:36:58 | 显示全部楼层
LZ,好像很多图没有啊
 楼主| 发表于 2018-11-20 10:02:49 | 显示全部楼层
回复 2# novel_qin


   可以加Q群97925396 领取文档和源码
发表于 2018-11-20 19:13:44 | 显示全部楼层
谢谢分享
发表于 2018-11-21 12:44:18 | 显示全部楼层
谢谢分享
发表于 2018-11-21 16:24:53 | 显示全部楼层
赞!!!!!
 楼主| 发表于 2018-11-21 16:57:51 | 显示全部楼层
回复 4# shidiqi


   完整文章及源码下载和技术交流请加FPGA交流群:97925396
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-15 08:17 , Processed in 0.038459 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表