EDA技术及应用第8章_第1页
EDA技术及应用第8章_第2页
EDA技术及应用第8章_第3页
EDA技术及应用第8章_第4页
EDA技术及应用第8章_第5页
已阅读5页,还剩288页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第8章数字系统设计实例8.1数字密码锁电路设计8.2IIR滤波器电路设计8.3简单电子琴电路设计8.4交通信号灯控制器电路设计8.1数字密码锁电路设计

8.1.1系统设计要求

(1)密码输入:每按下一个数字键,就输入一个数值,并在显示器上显示出该数值,同时将先前输入的数据依次左移一个数字位置。

(2)密码清除:按下“清除”键可清除前面所有输入的值。

(3)密码更改:按下“更改”键可将目前的数码设定成新的密码。

(4)密码上锁:按下“上锁”键可将密码锁定。

(5)密码解锁:按下“解锁”键首先检查输入的密码是否正确,密码正确即开锁。8.1.2系统设计

根据系统设计要求,系统设计采用自顶向下的设计方法。顶层设计采用原理图设计方式,系统整体设计原理图如图8-1所示。它由密码锁输入模块(SR)、密码锁控制模块(CTRL)和译码显示模块(YM)三部分组成。图8-1系统的整体组装设计原理图8.1.3模块设计与实现

1.密码锁输入模块

(1)时序产生电路。时序产生电路中使用三种不同频率的工作脉冲波形,即系统时钟脉冲、弹跳消除取样信号和键盘扫描信号。

(2)键盘扫描电路。键盘扫描电路的作用是提供键盘扫描信号,扫描信号变化的顺序依次为1110→1101→1011→0111

→1110…。图8-2键盘扫描示意图当键盘扫描信号为1110时,按键位置分别为011(“1”键按下)、101(“2”键按下)、110(“3”键按下);当键盘扫描信号为1101时,按键位置分别为011(“4”键按下)、101(“5”键按下)、110(“6”键按下);当键盘扫描信号为1011时,按键位置分别为011(“7”键按下)、101(“8”键按下)、110(“9”键按下);当键盘扫描信号为0111时,按键位置分别为011(“*”键按下)、101(“0”键按下)、110(“#”键按下)。

(3)键盘译码电路。上述键盘中的按键分为数字按键和功能按键,每个功能按键可能负责不同的功能,例如“清除”键、“上锁”键和“解锁”键等。数字按键主要是用来输入数字的。但是键盘所产生的输出是无法直接拿来用作密码锁控制电路的输入的;另外,不同的按键具有不同的功能,所以必须有键盘译码电路来规划每个按键的输出形式,以便执行相应的动作。①按键存储电路。因为每次扫描会产生新的按键数据,可能会覆盖前面的数据,所以需要一个按键存储电路,将整个键盘扫描完毕的结果记录下来。本设计采用串入串出移位寄存器实现按键存储电路。②各按键位置与数码关系如表8-1所示。其中“*”为“上锁”键,“#”为“清除/解锁”键。若按下的是数字键,则译成相对应的BCD码;若按下的是功能键,则译成四位数的码字,并由密码锁控制电路给出相应的动作。根据上述分析,密码输入电路的VHDL源程序(SR.VHD)如下:

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

USEIEEE.STD_LOGIC_UNSIGNED.ALL;

USEIEEE.STD_LOGIC_ARITH.ALL;ENTITYSRIS

PORT(CLK_IN:INSTD_LOGIC;--时钟信号

KEY_IN:INSTD_LOGIC_VECTOR(2DOWNTO0); --按键输入信号

DATA_N:OUTSTD_LOGIC_VECTOR(3DOWNTO0); --数字键数据

DATA_F:OUTSTD_LOGIC_VECTOR(3DOWNTO0); --功能键数据

FLAG_N:OUTSTD_LOGIC;--数字键数据标志

FLAG_F:OUTSTD_LOGIC;--功能键数据标志

CQD:OUTSTD_LOGIC;--键盘输入采样时钟

KSEL:OUTSTD_LOGIC_VECTOR(3DOWNTO0);

--键盘扫描信号

CSR:OUTSTD_LOGIC_VECTOR(1DOWNTO0)); --按键行号00,01,10,11

ENDENTITYSR;

ARCHITECTUREARTOFSRIS

SIGNALC_QD:STD_LOGIC;

SIGNALC_SR:STD_LOGIC_VECTOR(1DOWNTO0);

SIGNALN,F:STD_LOGIC_VECTOR(3DOWNTO0);

SIGNALFN,FF:STD_LOGIC;

SIGNALSEL:STD_LOGIC_VECTOR(3DOWNTO0);

SIGNALQ:STD_LOGIC_VECTOR(5DOWNTO0);

SIGNALC:STD_LOGIC_VECTOR(2DOWNTO0);

BEGIN --内部连接

DATA_N<=N; --数字键译码值寄存器

DATA_F<=F;

FLAG_N<=FN; --数字键标志值数据

FLAG_F<=FF;

CQD<=C_QD; --键盘输入采样时钟

CSR<=C_SR; --按键位置

KSEL<=SEL; --键盘扫描信号

C(0)<=KEY_IN(0); --按键输入寄存器(键盘矩阵的输出)

C(1)<=KEY_IN(1);

C(2)<=KEY_IN(2);COUNTER:BLOCKIS; --键盘扫描模块(计数器)

BEGIN

PROCESS(CLK_IN)IS

BEGIN

IF(CLK_IN'EVENTANDCLK_IN='1')THEN

Q<=Q+1;

ENDIF;

C_QD<=Q(3); --键盘输入采样时钟

C_SR<=Q(5DOWNTO4); --确定键盘扫描行号

ENDPROCESS;

SEL<="1110"WHENC_SR=00ELSE;--扫描“0”行

"1101"WHENC_SR=01ELSE

"1011"WHENC_SR=10ELSE

"0111"WHENC_SR=11ELSE

"1111";

ENDBLOCKCOUNTER;

KEY_DECODER:BLOCK;--键盘译码模块

SIGNALZ:STD_LOGIC_VECTOR(4DOWNTO0);

--按键位置

BEGIN

PROCESS(C_QD);--键盘采样时钟触发

BEGIN

Z<=C_SR&C;

--按键位置<扫描行>(2位)&按键输入<读出列>(3位)

IF(C_QD'EVENTANDC_QD='1')THEN

CASEZIS

WHEN"11101"=>N<="0000"; --数字键“0”

WHEN"00011"=>N<="0001"; --数字键“1”

WHEN"00101"=>N<="0010";

WHEN"00110"=>N<="0011";

WHEN"01011"=>N<="0100";

WHEN"01101"=>N<="0101";

WHEN"01110"=>N<="0110";

WHEN"10011"=>N<="0111";

WHEN"10101"=>N<="1000";

WHEN"10110"=>N<="1001"; --数字键“9”

WHENOTHERS=>N<="1111";

ENDCASE;

ENDIF;

IF(C_QD'EVENTANDC_QD='1')THEN

CASEZIS

WHEN"11011"=>F<="0100"; --功能键“*”

WHEN"11110"=>F<="0001"; --功能键“#”

WHENOTHERS=>F<="1000";

ENDCASE;

ENDIF;

ENDPROCESS;

FN<=NOT(N(3)ANDN(2)ANDN(1)ANDN(0)); --数字键标志

FF<=F(2)ORF(0); --功能键标志

ENDBLOCKKEY_DECODER;

ENDARCHITECTUREART;

2.密码锁控制模块

1)数字按键输入的相应控制

(1)如果按下数字键,第一个数字会从显示器的最右端开始显示,此后每新按下一个数字,显示器上的数字必须左移一位,以便将新的数据显示出来。

(2)假如要更改输入的数字,可以按“倒退”键来清除前面输入的一个数字,或者按“清除”键清除所有输入数字,再重新输入四位数。

(3)由于这里设计的是一个四位电子密码锁,所以当输入的数字键超过4个时,电路不予理会,而且不再显示第四个以后的数字。

2)功能按键输入的相应控制

(1)“清除”键:清除所有的输入数字,即作归零动作。

(2)“上锁”键:按下此键时可将密码锁上锁(上锁前必须设置四位数字密码)。

(3)“解锁”键:按下此键会检查输入的密码是否正确,若密码正确无误则解锁。下面给出密码锁控制模块的VHDL源程序(CTRL.VHD):

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

USEIEEE.STD_LOGIC_ARITH.ALL;

USEIEEE.STD_LOGIC_UNSIGNED.ALL;ENTITYCTRLIS

PORT(DATA_N:INSTD_LOGIC_VECTOR(3DOWNTO0); --数字键数据

DATA_F:INSTD_LOGIC_VECTOR(3DOWNTO0); --功能键数据

FLAG_N:INSTD_LOGIC;--数字键数据标志

FLAG_F:INSTD_LOGIC;--功能键数据标志

MIMAIN:BUFFERSTD_LOGIC;--密码输入标志

SETIN:BUFFERSTD_LOGIC;--密码设置标志

OLD:BUFFERSTD_LOGIC;--旧密码设置标志

CQD:INSTD_LOGIC;--键盘输入采样时钟

ENLOCK:OUTSTD_LOGIC;--开锁信号

DATA_BCD:OUTSTD_LOGIC_VECTOR(15DOWNTO0));

--BCD数据

ENDENTITYCTRL;ARCHITECTUREARTOFCTRLIS

SIGNALACC,REG:STD_LOGIC_VECTOR(15DOWNTO0);

--ACC暂存键入的信息,REG存储输入的密码

BEGIN

PROCESS(CQD,FLAG_F)IS

BEGIN

IF(CQD'EVENTANDCQD='0')THEN

IFFLAG_F='1'THEN

IF(DATA_F="0100")THEN

ACC<="1111111111111111"; --功能键“*”

MIMAIN<='0';SETIN<='0';OLD<='0';

ELSIF(DATA_F="0001")THEN

IF(MIMAIN='0'ANDSETIN='0')THEN

CASEACC(7DOWNTO0)IS

WHEN"00010001"=>ENLOCK<='1';--开锁信号

WHEN"10011001"=>MIMAIN<='1';--密码输入标志

ACC<="1111111111111111";

WHEN"01010101"=>SETIN<='1';--密码设置标志

ACC<="1111111111111111";

OLD<='1';

WHENOTHERS=>NULL;

ENDCASE;

ELSIF(MIMAIN=‘1’)THEN

IFACC=REGTHEN;--密码核对

ENLOCK<='0';

MIMAIN<='0';

ELSE

MIMAIN<='0';

ENDIF;

ELSIF(SETIN='1')THEN

IF(OLD='1')THEN

IF(ACC=REG)THEN

OLD<='0';

ELSE

SETIN<='0';

OLD<='0';

ENDIF;

ELSE

IF(ACC<“1001100110011001”)THEN;

--BCD码小于“9999”为有效码

REG<=ACC; --密码存储

SETIN<='0';

ENDIF;

ENDIF;

ENDIF;

ENDIF;

ELSIFFLAG_N=‘1’THEN

ACC<=ACC(11DOWNTO0)&DATA_N;

--实现数位左移

ENDIF;

ENDIF;

ENDPROCESS;

DATA_BCD<=ACC;

ENDARCHITECTUREART;

3.译码显示模块

译码显示模块的主要功能是将输入的数字通过数码管显示出来,根据数码显示电路的原理,很容易得到数字密码锁译码显示电路的VHDL设计程序(YM.VHD):

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

USEIEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITYYMIS

PORT(DATA_BCD:INSTD_LOGIC_VECTOR(3DOWNTO0);

DOUT7:OUTSTD_LOGIC_VECTOR(6DOWNTO0));

ENDENTITYYM;ARCHITECTUREARTOFYMIS

BEGIN

PROCESS(DATA_BCD)

BEGIN

CASEDATA_BCDIS

WHEN"0000"=>DOUT7<="0111111";--显示字形“0”

WHEN"0001"=>DOUT7<="0000110";--显示字形“1”

WHEN"0010"=>DOUT7<="1011011";

WHEN"0011"=>DOUT7<="1001111";

WHEN"0100"=>DOUT7<="1100110";

WHEN"0101"=>DOUT7<="1101101";

WHEN"0110"=>DOUT7<="1111101";

WHEN"0111"=>DOUT7<="0000111";

WHEN"1000"=>DOUT7<="1111111";

WHEN“1001”=>DOUT7<=“1101111”;

WHENOTHERS=>DOUT7<=“0000000”;

ENDCASE;

ENDPROCESS;

ENDARCHITECTUREART;8.1.4波形仿真

1.密码锁输入模块的仿真波形

密码锁输入模块仿真波形如图8-3所示。图8-3密码锁输入模块仿真波形

2.密码锁控制模块的仿真波形

密码锁控制模块仿真波形如图8-4所示。图8-4密码锁控制模块仿真波形

3.密码锁译码模块的仿真波形

密码锁译码模块仿真波形如图8-5所示。图8-5密码锁译码模块仿真波形

4.密码锁系统总体仿真图

(1)设置新密码部分。初始出厂时设置的密码为“0000”,用户重新设置为“0062”。顶层模块仿真波形1如图8-6所示。图8-6顶层模块仿真波形1

(2)上锁部分。按下“#”表示上锁,设置完毕后上锁键(ENLOCK)有效。顶层模块仿真波形2如图8-7所示。图8-7顶层模块仿真波形2(3)解锁但输入错误。当按下“0692”、“*”时,上锁键(ENLOCK)仍然有效,表示输入密码有错误,没有解开密码。顶层模块仿真波形3如图8-8所示。图8-8顶层模块仿真波形3

(4)解锁且输入正确。当按下“0062”、“*”时,上锁键(ENLOCK)无效,表示输入的密码正确,解开密码。顶层模块仿真波形4如图8-9所示。图8-9顶层模块仿真波形48.2IIR滤波器电路设计

8.2.1概述

IIR滤波器传输函数的一般形式为

(8-1)其差分方程的一般形式为(8-2)常用的IIR数字滤波器实现方法有如下几种:①采用在通用计算机系统中加上专用的加速处理机实现;②利用DSP芯片实现;③采用普通硬件组合实现;④采用EDA技术和FPGA/CPLD器件实现。在这几种方法中,利用EDA加FPGA/CPLD的方法具有速度快、成本低、效率高等优点。通常利用EDA技术和FPGA/CPLD实现IIR数字滤波器有如下几种方法:

①利用VHDL实现;

②利用LPM设计方法;

③利用DSPBulider实现;

④利用IP核实现。8.2.2IIR滤波器设计方案

式(8-2)的二阶形式如下:(8-3)这样就可以将任意阶的IIR滤波器通过若干二阶网络(也称为滤波器的二阶基本节)级联起来,如图8-10所示。图8-10级联二阶IIR网络对于每一个二阶基本节,可以通过转置直接Ⅱ型结构加以实现,如图8-11所示。图8-11二阶基本节直接Ⅱ型结构采用这种级联结构实现IIR滤波器的优点是每一个基本节只是关系到滤波器的某一对极点和一对零点,调整系数ai,只单独地调整了滤波器第i对零点,而不影响其他任何零、极点。同样,调整bi系数,也只单独调整了第i对极点。因此,这种结构便于准确地实现滤波器的零、极点,也便于调整滤波器的频率响应性能。假设要设计一个4阶IIR滤波器,则采用MATLAB实现IIR滤波器的源代码如下:

FilterOrder=4;

[FeedForward,FeedBack]=ellip(FilterOrder,3,50,300/500);

figure(1);

freqz(FeedForward,FeedBack);

title(‘FrequencyResponse(fullprecisioncoefficients)’);

[z,p,k]=tf2zp(FeedForward,FeedBack);

SecOrd=zp2sos(z,p,k);可得

SecOrd=[0.1116 0.2086 0.1116 1.0000 -0.53620.4138

1.00001.4239 1.0000 1.0000 0.50990.8690]

则可得该滤波器的二阶差分方程的系数如表8-2所示,幅频响应如图8-12所示。图8-12IIR幅频响应8.2.3IIR滤波器实现

1.设计方案

式(8-3)所对应的二阶节系统函数的差分方程为(8-4)

2.主要功能模块设计

1)输入控制单元

将输入数据送入输入寄存器中,其VHDL描述如下:

input_reg_process:PROCESS(clk)

BEGIN

IFclk‘eventANDclk=’1‘THEN

IFreset=’1‘THEN

input_register<=0.0000000000000000E+000;

ELSIFclk_en=‘1’THEN

input_register<=x;

ENDIF;

ENDIF;

ENDPROCESSinput_reg_process;

scale1<=input_register*scaleconst1;

2)移位单元

将输入寄存器上一时刻的数据送入delay_section1(0),同时又将delay_section1(0)上一时刻的数据送入delay_section1(1),其VHDL描述如下:

delay_process_section1:PROCESS(clk)

BEGIN

IFclk‘eventANDclk=’1‘THEN

IFreset=’1‘THEN

delay_section1(0TO1)<=(OTHERS=>

0.0000000000000000E+000);

ELSIFclk_en=‘1’THEN

delay_section1(0)<=a1sum1;

delay_section1(1)<=delay_section1(0);

ENDIF;

ENDIF;

ENDPROCESSdelay_process_section1;

3)乘加单元

先将系数与其相关数据相乘,再进行相加,其VHDL描述如下:

PROCESS(scale1,delay_section1,a1sum1)

BEGIN

inputconv1<=scale1;

a2mul1<=delay_section1(0)*coeff_a2_section1;

a3mul1<=delay_section1(1)*coeff_a3_section1;

b1mul1<=a1sum1;

b2mul1<=delay_section1(0)*coeff_b2_section1;

b3mul1<=delay_section1(1);

a2sum1<=inputconv1-a2mul1;

a1sum1<=a2sum1-a3mul1;

b2sum1<=b1mul1+b2mul1;

b1sum1<=b2sum1+b3mul1;

scale2<=b1sum1*scaleconst2;

4)输出控制单元

将输出数据送入输出寄存器输出,其VHDL描述如下:

output_register_process:PROCESS(clk)

BEGIN

IFclk‘eventANDclk=’1‘THEN

IFreset=’1‘THEN

output_register<=0.0000000000000000E+000

ELSIFclk_enable=‘1’THEN

output_register<=output_typeconvert;

ENDIF;

ENDIF;

ENDPROCESSoutput_register_process;

result<=output_register;将设计好的各模块按照二阶节电路连接,即构成4阶IIR滤波器其中一个二阶节,同理再设计另一个二阶节滤波器,然

后连接起来即构成一个4阶的IIR滤波器,其波形仿真如图8-13所示。图8-13IIR滤波器波形仿真8.2.4IIR滤波器的其他FPGA/CPLD实现方案

1.基于LPM的IIR滤波器设计

(1) LPM乘加器的VHDL源文件如下:

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

LIBRARYaltera_mf;

USEaltera_mf.all;

ENTITYfmaddIS

PORT(aclr3:INSTD_LOGIC:=‘0’;

clock0:INSTD_LOGIC:='1';

dataa_0:INSTD_LOGIC_VECTOR(17DOWNTO0):

=(OTHERS=>'0');

dataa_1:INSTD_LOGIC_VECTOR(17DOWNTO0):

=(OTHERS=>'0');

dataa_2:INSTD_LOGIC_VECTOR(17DOWNTO0):

=(OTHERS=>'0');

datab_0:INSTD_LOGIC_VECTOR(17DOWNTO0):

=(OTHERS=>'0');

datab_1:INSTD_LOGIC_VECTOR(17DOWNTO0):

=(OTHERS=>'0');

datab_2:INSTD_LOGIC_VECTOR(17DOWNTO0):

=(OTHERS=>'0');

ena0:INSTD_LOGIC:='1';

result:OUTSTD_LOGIC_VECTOR(37DOWNTO0));

ENDfmadd;ARCHITECTURESYNOFfmaddIS

SIGNALsub_wire0:STD_LOGIC_VECTOR(37DOWNTO0);

SIGNALsub_wire1:STD_LOGIC_VECTOR(17DOWNTO0);

SIGNALsub_wire2:STD_LOGIC_VECTOR(53DOWNTO0);

SIGNALsub_wire3:STD_LOGIC_VECTOR(17DOWNTO0);

SIGNALsub_wire4:STD_LOGIC_VECTOR(17DOWNTO0);SIGNALsub_wire5:STD_LOGIC_VECTOR(17DOWNTO0);

SIGNALsub_wire6:STD_LOGIC_VECTOR(53DOWNTO0);

SIGNALsub_wire7:STD_LOGIC_VECTOR(17DOWNTO0);

SIGNALsub_wire8:STD_LOGIC_VECTOR(17DOWNTO0);

COMPONENTaltmult_add

GENERIC(

addnsub_multiplier_aclr1:STRING;

addnsub_multiplier_pipeline_aclr1:STRING;

addnsub_multiplier_pipeline_register1:STRING;

addnsub_multiplier_register1:STRING;

dedicated_multiplier_circuitry:STRING;

input_aclr_a0:STRING;

input_aclr_a1:STRING;

input_aclr_a2:STRING;

input_aclr_b0:STRING;

input_aclr_b1:STRING;

input_aclr_b2:STRING;

input_register_a0:STRING;

input_register_a1:STRING;

input_register_a2:STRING;

input_register_b0:STRING;

input_register_b1:STRING;

input_register_b2:STRING;

input_source_a0:STRING;

input_source_a1:STRING;

input_source_a2:STRING;

input_source_b0:STRING;

input_source_b1:STRING;

input_source_b2:STRING;

intended_device_family:STRING;

lpm_type:STRING;

multiplier1_direction:STRING;

multiplier_aclr0:STRING;

multiplier_aclr1:STRING;

multiplier_aclr2:STRING;

multiplier_register0:STRING;

multiplier_register1:STRING;

multiplier_register2 :STRING;

number_of_multipliers:NATURAL;

output_aclr:STRING;

output_register:STRING;

port_addnsub1:STRING;

port_signa:STRING;

port_signb:STRING;

representation_a:STRING;

representation_b:STRING;

signed_aclr_a:STRING;

signed_aclr_b:STRING;

signed_pipeline_aclr_a:STRING;

signed_pipeline_aclr_b:STRING;

signed_pipeline_register_a:STRING;

signed_pipeline_register_b:STRING;

signed_register_a:STRING;

signed_register_b:STRING;

width_a:NATURAL;

width_b:NATURAL;

width_result:NATURAL);

PORT(dataa:INSTD_LOGIC_VECTOR(53DOWNTO0);

datab:INSTD_LOGIC_VECTOR(53DOWNTO0);

clock0:INSTD_LOGIC;

aclr3:INSTD_LOGIC;

ena0:INSTD_LOGIC;

result:OUTSTD_LOGIC_VECTOR(37DOWNTO0));

ENDCOMPONENT;

BEGIN

sub_wire8<=datab_2(17DOWNTO0);

sub_wire7<=datab_0(17DOWNTO0);

sub_wire4<=dataa_2(17DOWNTO0);

sub_wire3<=dataa_1(17DOWNTO0);

result<=sub_wire0(37DOWNTO0);

sub_wire1<=dataa_0(17DOWNTO0);

sub_wire2<=sub_wire4(17DOWNTO0)&sub_wire3(17DOWNTO0)&

 sub_wire1(17DOWNTO0);

sub_wire5<=datab_1(17DOWNTO0);

sub_wire6<=sub_wire8(17DOWNTO0)&sub_wire5(17DOWNTO0)&

sub_wire7(17DOWNTO0);

altmult_add_component:altmult_add

GENERICMAP(

addnsub_multiplier_aclr1=>"ACLR3",

addnsub_multiplier_pipeline_aclr1=>"ACLR3",

addnsub_multiplier_pipeline_register1=>"CLOCK0",

addnsub_multiplier_register1=>"CLOCK0",

dedicated_multiplier_circuitry=>"AUTO",

input_aclr_a0=>"ACLR3",

input_aclr_a1=>"ACLR3",

input_aclr_a2=>"ACLR3",

input_aclr_b0=>"ACLR3",

input_aclr_b1=>"ACLR3",

input_aclr_b2=>"ACLR3",

input_register_a0=>"CLOCK0",

input_register_a1=>"CLOCK0",

input_register_a2=>"CLOCK0",

input_register_b0=>"CLOCK0",

input_register_b1=>"CLOCK0",

input_register_b2=>"CLOCK0",

input_source_a0=>"DATAA",

input_source_a1=>"DATAA",

input_source_a2=>"DATAA",

input_source_b0=>"DATAB",

input_source_b1=>"DATAB",

input_source_b2=>"DATAB",

intended_device_family=>"FLEX10K",

lpm_type=>"altmult_add",

multiplier1_direction=>"ADD",

multiplier_aclr0=>"ACLR3",

multiplier_aclr1=>"ACLR3",

multiplier_aclr2=>"ACLR3",

multiplier_register0=>"CLOCK0",

multiplier_register1=>"CLOCK0",

multiplier_register2=>"CLOCK0",

number_of_multipliers=>3,

output_aclr=>"ACLR3",

output_register=>"CLOCK0",

port_addnsub1=>"PORT_UNUSED",

port_signa=>"PORT_UNUSED",

port_signb=>"PORT_UNUSED",

representation_a=>"SIGNED",

representation_b=>"SIGNED",

signed_aclr_a=>"ACLR3",

signed_aclr_b=>"ACLR3",

signed_pipeline_aclr_a=>"ACLR3",

signed_pipeline_aclr_b=>"ACLR3",

signed_pipeline_register_a=>"CLOCK0",

signed_pipeline_register_b=>"CLOCK0",

signed_register_a=>"CLOCK0",

signed_register_b=>"CLOCK0",

width_a=>18,

width_b=>18,

width_result=>38)

PORTMAP(

dataa=>sub_wire2,

datab=>sub_wire6,

clock0=>clock0,

aclr3=>aclr3,

ena0=>ena0,

result=>sub_wire0

);

ENDSYN;

(2) LPM加法器的VHDL源程序如下:

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

LIBRARYlpm;

USElpm.ALL;ENTITYadderIS

PORT(dataa:INSTD_LOGIC_VECTOR(17DOWNTO0);

datab:INSTD_LOGIC_VECTOR(17DOWNTO0);

cout :OUTSTD_LOGIC;

overflow :OUTSTD_LOGIC;

result:OUTSTD_LOGIC_VECTOR(17DOWNTO0));

ENDadder;ARCHITECTURESYNOFadderIS

SIGNALsub_wire0:STD_LOGIC;

SIGNALsub_wire1:STD_LOGIC;

SIGNALsub_wire2:STD_LOGIC_VECTOR(17DOWNTO0);

COMPONENTlpm_add_sub

GENERIC(lpm_direction:STRING;

lpm_hint :STRING;

lpm_type :STRING;

lpm_width:NATURAL );

PORT(dataa :INSTD_LOGIC_VECTOR(17DOWNTO0);

datab:INSTD_LOGIC_VECTOR(17DOWNTO0);

overflow :OUTSTD_LOGIC;

cout :OUTSTD_LOGIC;

result:OUTSTD_LOGIC_VECTOR(17DOWNTO0));

ENDCOMPONENT;

BEGIN

overflow<=sub_wire0;

cout<=sub_wire1;

result<=sub_wire2(17DOWNTO0);

lpm_add_sub_component:lpm_add_sub

GENERICMAP(lpm_direction=>"ADD",

lpm_hint=>"ONE_INPUT_IS_CONSTANT=NO,CIN_USED=NO",

lpm_type=>"LPM_ADD_SUB",

lpm_width=>18)

PORTMAP(dataa=>dataa,

datab=>datab,

overflow=>sub_wire0,

cout=>sub_wire1,

result=>sub_wire2);

ENDSYN;

(3)二阶节IIR滤波器模块iir_1的VHDL构造体源程序如下:

ARCHITECTUREtranslatedOFiir_1IS

COMPONENTadder

PORT(dataa:INSTD_LOGIC_VECTOR(17DOWNTO0);

datab:INSTD_LOGIC_VECTOR(17DOWNTO0);

result:OUTSTD_LOGIC_VECTOR(17DOWNTO0);

cout:OUTSTD_LOGIC;

overflow:OUTSTD_LOGIC);

ENDCOMPONENT;

SIGNALcoef_b1:STD_LOGIC_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALcoef_b2:STD_LOGIC_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALcoef_a0:STD_LOGIC_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALcoef_a1:STD_LOGIC_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALcoef_a2:STD_LOGIC_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALcoef_a2:STD_LOGIC_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALresult_xhdl1:STD_LOGIC_VECTOR(OUTPUT_WIDTH-1DOWNTO0);

SIGNALfeedback_fp_xhdl2:STD_LOGIC_VECTOR(OUTPUT_WIDTH-2DOWNTO0);

SIGNALwn_xhdl3:STD_LOGIC_VECTOR(DLY_WIDTH01-DOWNTO0);

SIGNALfeedback_xhdl4:STD_LOGIC_VECTOR(DLY_WIDTH01-1DOWNTO0);COMPONENTfmaddIS

PORT(clock0:INSTD_LOGIC;

dataa_0:INSTD_LOGIC_VECTOR(17DOWNTO0);

aclr3:INSTD_LOGIC;

datab_0:INSTD_LOGIC_VECTOR(17DOWNTO0);

dataa_2:INSTD_LOGIC_VECTOR(17DOWNTO0);

datab_1:INSTD_LOGIC_VECTOR(17DOWNTO0);

ena0:INSTD_LOGIC;

datab_2:INSTD_LOGIC_VECTOR(17DOWNTO0);

result:OUTSTD_LOGIC_VECTOR(37DOWNTO0));ENDCOMPONENT;

COMPONENTtmaddIS

PORT(clock0:INSTD_LOGIC;

dataa_0:INSTD_LOGIC_VECTOR(17DOWNTO0);

aclr3:INSTD_LOGIC;

datab_0:INSTD_LOGIC_VECTOR(17DOWNTO0);

datab_1:INSTD_LOGIC_VECTOR(17DOWNTO0);

ena0:INSTD_LOGIC;

result:OUTSTD_LOGIC_VECTOR(36DOWNTO0));ENDCOMPONENT;

BEGIN

result<=result_xhdl1;

feedback_fp<=feedback_fp_xhdl2;

wn<=wn_xhdl3;

feedback<=feedback_xhdl4;

coef_b1<=conv_STD_LOGIC_VECTOr(-b1,18);

coef_b2<=conv_STD_LOGIC_VECTOR(-b2,18);

coef_a0<=conv_STD_LOGIC_VECTOR(a0,18);

coef_a1<=conv_STD_LOGIC_VECTOR(a1,18);

coef_a2<=conv_STD_LOGIC_VECTOR(a2,18);

feedback_xhdl4<=feedback_fp_xhdl2(27DOWNTO10);

four_mult_add_inst:fmadd

PORTMAP(

clock0=>clk,

aclr3=>reset,

ena0=>clken,

dataa_0=>wn_xhdl3,

dataa_2=>wn_xhdl3,

datab_0=>coef_a1,

datab_1=>coef_a2,

datab_2=>coef_a0,

result=>result_xhdl1);

two_mult_add_inst:tmadd

PORTMAP(

clock0=>clk,

dataa_0=>wn_xhdl3,

aclr3=>reset,

datab_0=>coef_b1,

datab_1=>coef_b2,

ena0=>clken,

result=>feedback_fp_xhdl2);

adder_inst:adder

PORTMAP(

dataa=>x,

datab=>feedback_xhdl4,

result=>wn_xhdl3,

cout=>open,

overflow=>open);

ENDtranslated;总体设计的构造体VHDL源程序如下:

ARCHITECTUREtranslatedOFiir_topIS

SIGNALout_1:BIT_VECTOR(OUTPUT_WIDTH-1DOWNTO0);

SIGNALpzeros:BIT_VECTOR(F_BITS-1DOWNTO0);

SIGNALxn:BIT_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALresult_w:BIT_VECTOR(OUTPUT_WIDTH-1DOWNTO0);

SIGNALxn_reg:BIT_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALin_2:BIT_VECTOR(DLY_WIDTH-1DOWNTO0);

SIGNALresult_xhdl1:BIT_VECTOR(OUTPUT_WIDTH-1DOWNTO0);COMPONENTiir_1is

PORT(reset:INBIT;

clk:INBIT;

clken:INBIT;

x:INBIT_VECTOR(INPUT_WIDTH-1DOWNTO0);

result:OUTBIT_VECTOR(OUTPUT_WIDTH-1DOWNTO0);

feedback_fp:OUTBIT_VECTOR(OUTPUT_WIDTH-2DOWNTO0);

feedback:OUTBIT_VECTOR(DLY_WIDTH-1DOWNTO0);

wn:OUTBIT_VECTOR(DLY_WIDTH-1DOWNTO0));

ENDCOMPONENT;

BEGIN

result<=result_xhdl1;

pzeros<=“0000”;

xn<=x(INPUT_WIDTH-1)&x(INPUT_WIDTH-1DOWNTO0)&pzeros

(F_BITS-1DOWNTO0);

PROCESS

BEGIN

WAITUNTIL(clk'EVENTANDclk='1');

IF(reset='1')THEN

xn_reg<=(OTHERS=>'0');

result_xhdl1<=(OTHERS=>'0');

in_2<=(OTHERS=>'0');

ELSE

IF(clken='1')THEN

xn_reg<=xn;

result_xhdl1<=result_w;

in_biquad2<=out_1(27DOWNTO10);

ENDIF;

ENDIF;

ENDPROCESS;

base_iir_1:iir_1

GENERICMAP(a0=>a10,

a1=>a11,

a2=>a12,

b1=>b11,

b2=>b12)

PORTMAP(clk=>clk,

clken=>clken,

reset=>reset,

x=>xn_reg,

result=>out_1);

base_iir_2:iir_1

GENERICMAP(a0=>a20,

a1=>a21,

a2=>a22,

b1=>b21,

b2=>b22)

PORTMAP(clk=>clk,

clken=>clken,

reset=>reset,

x=>in_2,

result=>result_w);

ENDtranslated;

2.基于DSPBuilder的IIR滤波器设计

(1)在MATLAB/Simulink中进行设计输入,即在MATLAB的Simulink环境中建立一个mdl模型文件,用图形方式调用AlteraDSPBuilder和其他Simulink库中的图形模块(Block),构成系统级或算法级设计框图(或称Simulink设计模型)。DSPBuilder模块库如图8-14所示。图8-14DSPBuilder模块库

(2)利用Simulink强大的图形化仿真、分析功能,分析此设计模型的正确性,完成模型仿真。

(3)打开SingalCompiler,选定对应器件,把模型转成VHDL文件,并在SignalCompiler中选择Quartus Ⅱ进行综合。

(4)适配下载。在QuartusⅡ中打开SignalCompiler建立的Quartus项目文件,选择具体器件,锁定管脚,完成适配后下载至FPGADSP开发板中。

3.基于IP核的IIR滤波器设计

Altera以及其他FPGA厂商提供了IIRFilterCore。IIR滤波器核既可以与DSPBuilder衔接开发,也可以在Quartus Ⅱ中直接使用。下面主要介绍在Quartus Ⅱ中使用IPCore的方法。在QuatusⅡ中使用IP核设计IIR滤波器步骤如下:

(1)配置Quartus Ⅱ以便使用IIR滤波器核。打开Quartus Ⅱ集成环境,新建一个项目。选择菜单“Assignments”→“Settings”,打开Quartus Ⅱ的设置对话框,在对话框的左侧选择“UserLibraries(用户库)”,如图8-15所示。图8-15IP核配置

(2)使用IIR滤波器核。首先完成IIR滤波器核的安装配置,然后按照第2章给出的类似的方法,定制使用IIR滤波器核。具体步骤如下:

①打开MegaWizardPlug-InManager。选择菜单“Tools”→

“MegaWizardPlug-InManager”,接着打开MegaCore向导。在窗口的左侧选中“IIRFilterv1.3.3”,在右侧选择实现时的HDL类型,并输入生成IIR滤波器核的名字,如图8-16所示。图8-16选择IIR滤波器核②选择IIR滤波器结构。Altera的IIR滤波器核对这三种IIR结构都是支持的。图8-17是IIR滤波器结构设置对话框,在这里我们选择了级联型(Cascaded)进行实现,滤波器阶数设为4。图8-17选择滤波器结构③导入滤波器系数。这里我们使用MATLAB的FDATool来完成滤波器系数的计算,再通过图8-18所示的对话框导入(通过文件)滤波系数。图8-18导入滤波器系数

(3) IIR滤波系数的量化。IIR系数必须进行量化处理,如图8-19所示。在这里设置了输入信号的位宽为13位,系数位宽为10位,采用自动方式让IIRCompiler具体决定系数的归一化问题。图8-19量化IIR滤波系数

(4) IIR滤波器的具体实现。为了提高IIR滤波器的性能,同时减少IIR滤波器耗费的资源,有时需要对IIR滤波器实现时的某些细节进行调整,如图8-20所示。图8-20IIR滤波器调整

(5)设置仿真参数。这一步主要设置仿真模型及测试信号,如图8-21所示。图8-21仿真参数设置经过前面几个步骤,即完成了基于IP核的IIR滤波器的设计,点击“Finish”按钮完成设计,系统自动输出相关文件,如图8-22所示。图8-22输出设计文件8.3简单电子琴电路设计

8.3.1系统设计要求

(1)设计一个简单的八音符(1,2,3,4,5,6,7,8,其中8表示高音1)电子琴,可通过按键输入来控制音响。

(2)演奏时可以选择是手动演奏(键盘输入)还是自动演奏已存入的乐曲。

(3)能够自动演奏多首乐曲,且每首乐曲可重复演奏。8.3.2系统设计

简单电子琴电路的原理方框图如图8-23所示,其主要由以下几个模块组成:

(1)基准频率产生器。该电路由晶振和反相器CC4069构成时钟脉冲振荡器。振荡器输出频率为4MHz,作为系统的基准频率。图8-23简单电子琴电路原理方框图

(2)自动演奏及键盘编码模块。该模块主要实现两大功能:键盘输入编码及乐曲自动演奏。该模块可对系统时钟4MHz的信号(CLK)分频得到4Hz的自动演奏地址计数频率,用来控制每个音阶之间的停顿时间;地址计数器的计数范围为0~63,音乐存储模块中音符的最大地址用于完成自动演奏乐曲的地址累加,同时实现乐曲循环演奏;记录所选乐曲的乐谱,根据乐谱产生发声控制输出INDEX0信号。

(3)声音输出控制模块。该模块主要电路为数控分频器。CLK输入系统的基准频率为4MHz,TONE1接TONE来的分频预置数,SPKS输出端接音色产生器,输出各音符所对应频率的声音信号。

(4)音符产生电路模块。该模块的作用是产生各音符的分频预置值。根据各音符名与频率的关系(如表8-3所示)以及声音输出控制模块(FENPIN)中数控分频器的设计,分别计算出高音区、中音区、低音区不同音符的分频预置数。

(5)各类开关按键及琴键。初步设计出自动演奏及键盘编码模块、各类开关按键及琴键等声音输出控制模块、音符产生电路模块,再设计顶层电路。8.3.3模块设计与实现

1.自动演奏模块(YANZOU)设计

乐曲演奏是通过记谱的方式来记录一段音乐,它可以极大地减少存储容量。声音的频谱范围一般在几十到几千赫兹,利用程序来控制FPGA芯片输出一定频率的矩形波,配上一些必要的外围电路就可以发出相应频率的声音。乐曲中的每一个音符对应着一个确定的频率,因此,想要发出不同音符的音调,只要能控制输出相应音符的频率即可。乐曲都是由一连串音符组成的,因此按照乐曲的乐谱依次输出这些音符所对应的频率,就可以通过扬声器连续播放这些音符所对应的音乐。要准确地演奏一首乐曲,仅仅让扬声器发声是不够的,还必须准确地控制乐曲的节奏,即每个音符的持续时间,也就是节拍。音乐存储模块的作用是产生音符发声控制输入INDEX。当AUTO = “0”时,由存储在此模块中的8位二进制数作为发声控制输入,可自动演奏乐曲。此模块的VHDL程序包括三个进程:第一个进程为分频器,实现4Hz的分频;第二个进程为地址计数器,计数范围为0~63,表示音乐存储模块中音符的最大地址数,该进程完成自动演奏乐曲的地址累加。同时实现乐曲循环演奏;第三个进程主要用来记录所选乐曲的乐谱,根据乐谱产生8位发声控制输出INDEX0信号,当AUTO为“0”时,将存储在此模块中的8位二进制数作为发声控制信号,自动演奏乐曲。在记

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论