马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
1 项目背景源码下载技术交流群:979253961.1 FIR和IIR滤波器FIR(Finite Impulse Response)Filter:有限冲激响应滤波器,又称为非递归线性滤波器。 FIR滤波器,顾名思义,其脉冲响应由有限个采样值构成。长度(抽头数)为N、阶数为N−1的FIR系统的转移函数、差分方程和单位冲激响应分别如下列三式所示。 图 510 IIR(Infinite Impulse Response)Filter:无限冲激响应滤波器,又称为递归线性滤波器。 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 注意复制后需在两个系数间插入逗号(英文输入状态下的的逗号)
图 516 这样就得到滤波器的系数了。
1.3.2 FPGA生成FIR IP核打开工程后,在IP catalog这一界面中选择DSP下一目录中选择Filter 在选择选择 FIR II
图 517 首先在Fitter这一界面做如下操作
图 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界面的波形发生变化
图 519
在coefficient界面,还可以设置系数的格式、数据位宽等。
图 520 其它选项不改按默认的来点击finish即可。 以上就是生成 FIR滤波器的主要步骤。
2 设计目标本次案例将使用到采样率大于100M的双通道的示波器。将示波器的两个通道,分别与FPGA的DA通道1和DA通道2相连,观察两路DA的输出。其连接示意如下图所示。
图 521
本案例是FPGA内部产生正弦信号,这个正弦信号一路输出给DA通道1,另一路经过FIR滤波器后,输出给DA通道2。
图 522 正弦信号的频率受开发板上的3个拨码开关控制,用3位信号key表示,一共可以产生8种频率。 正弦信号的频率 约等于: 100KHz * (key+1)。 例如,当key等于0时,产生约100KHz的正弦信号; 当key等于1时,产生约200KHz的正弦波; 当key等于7时,产生约800KHz的正弦波。
FIR滤波器是低通滤波器,其截止频率是500KHz,这样原则上超过500KHz的信号就会被滤除。滤波器的输出给通道2。 下面是示波器的显示效果,其中黄色是通道1输出的信号(上面的波形),下面蓝色是通道2的输出信号(下面的波形)。
下图是100KHz的信号图。
图 下图是200KHz的信号图。
图 下图是300KHz的信号图。
图 下图是400KHz的信号图,可以看到已经衰减了。
图 下图是500KHz的信号图,可以看到已经衰减的很小了。
图 下图是600KHz的信号图,可以看到通道2已经没有波形。
图 下图是700KHz的信号图,可以看到通道2已经没有波形。
图 下图是800KHz的信号图,可以看到通道2已经没有波形。
图
3 设计实现3.1 顶层接口新建目录:D:\mdy_book\fir_prj。在该目录中,新建一个名为fir_prj.v的文件,并用GVIM打开,开始编写代码。
我们要实现的功能,概括起来就是FPGA产生控制AD9709,让其中的通道A未滤波的正弦信号,让通道B输出滤波后的正弦信号。为了控制AD9709的工作模式,就要控制AD9709的MODE、SLEEP管脚;为了控制通道A,就需要控制AD9729的CLK1、WRT1、DB7~0P1管脚;为了控制通道B,就需要控制AD9729的CLK2、WRT2、DB7~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信号连接到AD9709的MODE管脚,用来控制其工作模式。 [size=9.5000pt]5. 使用dac_sleep信号连接到AD9709的SLEEP管脚,用来控制其睡眠模式。 [size=9.5000pt]6. 使用dac_clka信号连接到AD9709的CLK1管脚,用来控制通道A的时钟。 [size=9.5000pt]7. 使用dac_wra信号连接到AD9709的WRT1管脚,用来控制通道A的写使能。 [size=9.5000pt]8. 使用8位信号dac_da连接到AD9709的DB7~0P1管脚,用来控制通道A的写数据。 [size=9.5000pt]9. 使用dac_clkb号连接到AD9709的CLK2脚,用来控制通道B时钟。 [size=9.5000pt]10. 使用dac_wrb号连接到AD9709的WRT2脚,用来控制通道B使能。 [size=9.5000pt]11. 使用8位信号dac_db接到AD9709的DB7~0P2脚,用来控制通道B写数据。
综上所述,我们这个工程需要11个信号,时钟clk,复位rst_n,拨码开关的输入key,dac_mode、dac_sleep、dac_clka、dac_wra、dac_da、dac_clkb、dac_wrb和dac_db信号,其中dac_da和dac_db是8位信号,其他都是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] |
其中clk、rst_n是1位的输入信号,dac_da和dac_db是8位的输出信号,key是3位输入信号,dac_mode,dac_clka,dac_wra,dac_sleep,dac_clkb,dac_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 按下回车调出波形设计界面。
在波形设计界面中 Response Type:案例要求滤波高于500KHz的信号,所以选择lowpass低通滤波器 Fstop: 截止频率设为600KHz Fs:采样频率: 12.5MHz(12500Khz)
图 526 其它选项默认点击Design Filter
产生系数后点击file 菜单里的Export 将系数保存的工作区
图 527 点击export
图 528 点击之后打开工作区里的Num
图 529 而后将下图第一列的数据复制粘贴到txt文件中
图 530 注意复制后需在两个系数间插入逗号(英文输入状态下的的逗号)
图 531
3.3.2 新建FPGA工程
图 532
1.)打开quartus,点击File 在File菜单中选择New Project Wizard.... 。
图 533 2.弹出Introduction界面选择Next。
图 534
(3)设置工程目录,工程名,顶层模块名 工程目录设置为:D:\mdy_book\fir_prj 工程名:fir_prj 顶层模块名:fir_prj 填写完毕后,点击next之后进入下一界面。
图 535 工程类型界面,Project Type选择Empty project,选择空白工程。点Next进入下一个界面。
图 536
(3.)在文件添加界面,不选择任何文件。点击Next,进入下一个界面。
图 537
4.)器件选择界面。在Device family这一项之中选择 Cyclone IV E;在下部的Available device 选择EP4CE6F23C8。完成后直接点击Finish。
3.3.3 FPGA生成FIR IP核
图 538 建立工程后,在quartus中IP catalog这一界面中选择DSP下一目录中选择Filter 再选择 FIR II。
图 539 点击后进入此界面给新生成的fir滤波器ip核选择如下路径:D:\mdy_book\fir_prj\my_fir.v,IPvariation file name这一项选择verilog。点击OK后,进入FIR滤波器设置界面。
图 540
在Fitter specification界面按如下设置: Filter Type:要选择Single Rate,表示只采用一种采样率。 Clock Rate:因为我们工程使用的是50MHz时钟,所以此处要填写50MHz。 Input Sample Rate (PSPS):这个是填采样率。和matlab相匹配,因此要填12.5MHz。 其他参数默认。 然后点击coefficients选项卡。
图 541
单击import from file ,在输出的界面中,找出我们用MATLAB生成的系数文件:my_fir_coe.txt,点击import导入。导入成功后可以看到下图的 frequency response界面的波形发生变化。 在Coefficient Bit Width中,填写16。表示每个系数用16比特量化。
图 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核。
图 544 出现上面的提示,就是生成成功了。
图 545 IP核生成后弹出此对话框点击yes 将此IP核添加进工程。
3.3.4 例化FIR IP核用GVIM打开D:\mdy_book\fir_prj\my_fir.v文件,该文件就是生成的FIR IP核文件。
图 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_fir,fir的输出数据信号命名为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_da。dac_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_sleep,AD是一直工作的,所以要让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_db。dac_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。其位宽为8;dac_sleep是用assign设计的,因此类型为wire,位宽为1;dac_wra是用assign设计的,因此类型为wire,位宽为1;dac_clka是用assign设计的,因此类型为wire,位宽为1;dac_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。其位宽为8;dac_wrb是用assign设计的,因此类型为wire,位宽为1;dac_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] |
至此,整个代码的设计工作已经完成。下一步是新建工程和上板查看现象。 |