数字电路自由创作三.docx

上传人:b****2 文档编号:24149123 上传时间:2023-05-24 格式:DOCX 页数:20 大小:351.08KB
下载 相关 举报
数字电路自由创作三.docx_第1页
第1页 / 共20页
数字电路自由创作三.docx_第2页
第2页 / 共20页
数字电路自由创作三.docx_第3页
第3页 / 共20页
数字电路自由创作三.docx_第4页
第4页 / 共20页
数字电路自由创作三.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

数字电路自由创作三.docx

《数字电路自由创作三.docx》由会员分享,可在线阅读,更多相关《数字电路自由创作三.docx(20页珍藏版)》请在冰豆网上搜索。

数字电路自由创作三.docx

数字电路自由创作三

数电实验报告

题目基于FPGA的八音符电子琴电路设计

 

时间2011年6月25日

第一章实验任务与原理

一、实现功能

基于FPGA开发办设计一个八音符电子琴,由键盘输入控制音响或自动演奏。

用户可以将自己编制的乐曲存入电子琴,演奏时可以选择键盘输入乐曲或者自动演奏已存入的乐曲。

二、原理阐述

1、系统设计方案:

采用VHDL语言编程来实现电子琴的各项功能。

系统主要由电子琴发声模块、选择控制模块和储存器模块组成。

八音符电子琴设计总体框图

该系统由三个模块:

Songer、Div和SEG7(7段译码器)组成。

(1)Songer模块:

此模块包括3个小模块,分别是NoteTabs模块,ToneTab模块和Speakera模块。

此外,还需建立一个名为“music”的LPM_ROM模块与NoteTabs模块连接。

(2)NoteTabs模块:

该模块的功能就是定义音符数据ROM“music”随着该模块中的计数器控制时钟频率速率作加法计数时,即地址值递增时,音符数据ROM中的音符数据。

将从ROM中通过ToneIndex[3..0]端口输向ToneTaba模块,演奏《采茶舞曲》。

(3)ToneTaba模块:

是乐曲简谱码对应的分频预置数查找表电路,其中设置了乐曲的全部音符所对应的分频置数,每一音符的停留时间由音乐节拍和音调发生器模块NoteTabs的CLK的输入频率决定,这些值由对应于ToneTaba的4位输入值Index[3..0]确定,最多有16种可选值。

输向ToneTaba中Index[3..0]的值ToneIndex[3..0]的输出值与持续的时间由模块NoteTabs决定。

(4)Speakera模块:

是一个数控分频器,音符的频率可由此模块获得。

由CLK端输入一具有较高频率的信号,通过Speakera分频后由SPKOUT输出。

由于直接从数控分频器中出来的输出信号是脉宽极窄的脉冲式信号。

为了利用驱动扬声器,需加一个D触发器以均衡其占空比,频率将是原来的1/2。

Speakera对CLK输入信号的分频比由预置数Tone决定。

SPKOUT的输出频率将决定每一音符的音调。

(5)Div模块:

由于所使用的硬件设备不能满足设计所需要的两个CLK输出的频率,所以使用一个分频器来实现把一个50MHz的晶体振荡频率分成一个12MHz,一个8Hz两个分频率,再把两个频率分别给所需的两个模块。

(6)EG7模块:

SEG7模块是一个七段译码器,作用是在硬件上显示音频的高

低,用0到7分别对应空节拍do、ri、mi、fa、suo、la、xi,高音时,

LED灯亮,数码管显示对应数字。

2、发音原理:

(1)乐曲演奏的原理

组成乐曲的每个音符的频率值(音调)及其持续时间(音长)是乐曲能连续演奏所需的两个基本数据,因此只要控制输出到扬声器的激励信号的频率的高低和持续时间,就可以使扬声器发出连续的乐曲声。

(2)音调的控制:

频率的高低决定了音调的高低。

(4)基准频率f0的选取

所有不同频率的信号都是从同一个基准频率f0分频而得到的。

由于音节频率多为非整数,而分频系数又不能为小数,因此必须将计算所得的分频数四舍五入取整。

若基准频率过高,则分频比太小,取整后误差较大。

若基准频率过高,虽然误差减小,但分频数变大。

综合这两方面因素,在尽量减小频率误差的前提下取合适的基准频率,在此取f0=12MHz。

(5)分频系数,二进制计数器计数的容量N和预置数的选取

分频系数A=f0/音名频率

分频系数n=f0/音名频率/2

N〉=MAX{分频系数n}

由表1可得最大分频系数为1274,因此N=2048为2的11次方。

因此二进制计数器设为11位二进制加法计数器,其计数容量为2048,计数的最大值为2047。

预置数=N-分频系数n

表1为各音阶的频率、对应的分频系数及预置数:

(6)音长的控制:

音符的持续时间须根据乐曲的速度及每个音符的节拍数来确定的。

《采茶舞曲》中最短的音符为四分音符,如果全音符的持续时间为1s,则四分音符的持续时间为0.25s,二分音符持续的时间为0.5s等等,只需再提供一个4Hz的时钟频率。

每来一个脉冲计一次数,每一计数值的停留时间为0.25s,即要输入一个全音符时需要计四次数才行,则应在Rom表格中输出相应音符四次,表示一个全音符的持续时间。

第二章FPGA模块程序设计与仿真

1、Songer模块

Songer模块由三个模块组成:

NoteTabs模块,ToneTaba模块和Speakera模块。

Notetabs模块类似于弹琴人的手指,Tonetaba类似于琴键,Speakera类似于琴弦或音调发生器。

(1)NoteTabs模块:

原理:

在这个模块中设置了一个8位二进制计数器,作为音符数据ROM的地址发生器。

这个计数器的计数频率选为4HZ,即每一计数值的停留时间为0.25秒,当全音符设为1秒时,4分音符持续时间为0.25s,2分音符持续的时间为0.5s等等。

每来一个脉冲计一次数,每一计数值的停留时间为0.25s,即要输入一个全音符时需要计数4次才行,则应在Rom表格中输出相应音符四次,表示一个全音符的持续时间,要输入一个2分音符则需要计数2次,依次类推。

程序:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

useieee。

Std_logic_arith.all;

entitynotetabsis

port(clk1:

instd_logic;

toneindex:

outstd_logic_vector(3downto0)

);

Endnotetabs;

architectureoneofnotetabsis

componentmusic

port(address:

instd_logic_vector(7downto0);

clock:

instd_logic;

q:

outstd_logic_vector(3downto0));

endcomponent;

signalcounter:

std_logic_vector(7downto0);

begin

cnt8:

process(clk1,counter)

begin

ifcounter=336thencounter<="00000000";

elsif(clk1'eventandclk1='1')then

counter<=counter+1;

endif;

endprocess;

u1:

music

portmap(address=>counter,q=>toneindex,clock=>clk1);

end;

NoteTabs模块波形仿真图:

(注:

每来一个时钟clk,输出一个相应的数,每个音符的拍子不一样所记次数也不一样)

图5Notetabs的波形仿真图

 

《采茶舞曲》简谱如图6

图6《采茶舞曲》简谱

 

下表7是Rom表格:

(即为此程序中调用的music模块)。

表7Rom表格

(2)ToneTaba模块:

原理:

ToneTaba是乐曲简谱码对应的分频预置数查表电路。

音符的持续时间需要根据乐曲的速度及每个音符的节拍数来确定,Tonetaba的功能首先是为Speakera提供决定所发音符的分频预置数,而此数在Speakera输入口停留的时间为此音符的节拍值。

模块Tonetaba是乐曲简码对应的分频预置数查表电路,其中设置了《采茶舞曲》乐曲全部音符所对应的分频预置数,共16个,每一音符的停留时间由音乐节拍和音调发生器模块Notetabs的clk的输入频决定,在此为4Hz。

这16个值得输出由对应于Tonetaba的4位输入值Index[3..0]确定。

输向Tonetaba中Index[3..0]的值,ToneIndex[3..0]的输出值与持续的时间由模块Notetabs决定。

程序

libraryieee;

useieee.std_logic_1164.all;

useieee,std_logic_arith.all;

useieee.std_logic_unsigned.all;

entityToneTabais

port(Index:

instd_logic_vector(3downto0);

CODE:

outstd_logic_vector(3downto0);

HIGH:

outstd_logic;

Tone:

outstd_logic_vector(10downto0));

EndToneTaba;

architectureoneofToneTabais

begin

Search:

process(Index)

begin

caseIndexis

When"0000"=>tone<="11111111111";code<="0000";high<='0';--2047

When"0001"=>tone<="01100000101";code<="0001";high<='0';--773

When"0010"=>tone<="01110010000";code<="0010";high<='0';--912

When"0011"=>tone<="10000001100";code<="0011";high<='0';--1036

When"0100"=>tone<="10000110101";code<="0100";high<='0';--1077

When"0101"=>tone<="10010101101";code<="0101";high<='0';--1197

When"0110"=>tone<="10100001010";code<="0110";high<='0';--1290

When"0111"=>tone<="10101011100";code<="0111";high<='0';--1372

When"1000"=>tone<="10110000010";code<="0001";high<='1';--1410

When"1001"=>tone<="10111001000";code<="0010";high<='1';--1480

When"1010"=>tone<="11000000110";code<="0011";high<='1';--1542

When"1011"=>tone<="11000101000";code<="0100";high<='1';--1576

When"1100"=>tone<="11001010110";code<="0101";high<='1';--1622

When"1101"=>tone<="11010000100";code<="0110";high<='1';--1668

When"1110"=>tone<="11011000000";code<="0001";high<='1';--1728

When"1111"=>tone<="11011101010";code<="0010";high<='1';--1770

Whenothers=>null;

endcase;

endprocess;

end;

(注:

每一个index的值都对应一个code,tone值,index的值从0000到0111对应的,high为低电,从1000到1111对应的high为高电。

ToneTaba模块波形仿真图如图10:

图10Tonetaba的波形仿真图

 

(3)Speakera(数控分频器)模块:

原理:

数控分频器的功能是当在输入端给定不同的输入数时,将对输入的时钟信号有不同的分频比,数控分频器是用计数值可并行预置的加法计数器来完成的。

在此,音符的频率可由数控分频器Speakera获得。

由其clk端输入一具有较高频率的信号,通过Speakera分频后由Spkout输出,由于直接从数控分频器中出来的输出信号是脉宽极窄的脉冲式信号,为了有利于驱动扬声器,需加一个D触发器以均衡其占空比,但这时的频率将是原来的1/2。

Speakera对clk

输入信号的分频比由11位预置数Tone[10..0]决定。

Spkout的输出频率将决定每一音符的音调,这样分频计数器的预置值Tone[10..0]与Spkout的输出频率就有了对应关系。

程序:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

useieee.std_logic_arith.all;

entityspeakerais

port(clk2:

instd_logic;

tone:

instd_logic_vector(10downto0);

spks:

outstd_logic);

endspeakera;

architectureoneofspeakerais

signalpreclk,fullspks:

std_logic;

begin

divideclk:

process(clk2)

variablecount4:

std_logic_vector(3downto0);

begin

preclk<='0';

ifcount4>11thenpreclk<='1';

count4:

="0000";

elsifclk2'eventandclk2='1'then

count4:

=count4+1;

endif;

endprocess;

genspks:

process(preclk,tone)

variablecount11:

std_logic_vector(10downto0);

begin

ifpreclk'eventandpreclk='1'then

ifcount11=16#7FF#then

count11:

=tone;

fullspks<='1';

elsecount11:

=count11+1;

fullspks<='0';

endif;

endif;

endprocess;

delayspks:

process(fullspks)

variablecount2:

std_logic;

begin

iffullspks'eventandfullspks='1'then

count2:

=notcount2;

ifcount2='1'then

spks<='1';

else

spks<='0';

endif;

endif;

endprocess;

end;

Speakera(数控分频器)模块仿真波形如图12:

图12Speakera的波形仿真图

2、Div模块:

原理:

由于我们所使用的硬件设备不能满足我们所需要的两个CLK输出的

频率,所以我们使用一个分频器来实现把一个50MHz的晶体振荡频率分成一个12MHz,一个8Hz两个分频率,再把两个频率分别给所需的两个模块。

程序:

LIBRARYieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

useieee.std_logic_arith.all;

ENTITYdivIS

PORT(

clk:

INSTD_LOGIC;

CLK12MHz,CLK8Hz:

OUTstd_logic);

ENDdiv;

ARCHITECTUREoneofdivis

begin

u1:

process(clk)

variablecnt:

integerrange0to2;

variabletmp:

std_logic;

begin

if(clk'eventandclk='1')then

ifcnt>=1then

cnt:

=0;

tmp:

=nottmp;

else

cnt:

=cnt+1;

endif;

endif;

CLK12MHz<=tmp;

endprocessu1;

u2:

process(clk)

variablecnt:

integerrange0to3125000;

variabletmp:

std_logic;

begin

if(clk'eventandclk='1')then

ifcnt>=3124999then

cnt:

=0;

tmp:

=nottmp;

else

cnt:

=cnt+1;

endif;

endif;

CLK8Hz<=tmp;

endprocessu2;

endone;

Div模块波形仿真图如图14:

图14Div的波形仿真图

(注:

由50MHz的时钟信号分频得到CLK12MHz,CLK12MHz)

3、SEG7模块:

原理:

SEG7模块是一个七段译码器,作用是在硬件上显示音频的高低,用0到7分别对应空节拍do、ri、mi、fa、suo、la、xi,高音时,LED灯亮,数码管显示对应数字。

VGA为0010。

程序:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

useieeestd_logic_arith.all;

ENTITYSEG7IS

PORT(num:

INstd_logic_vector(3downto0);

A:

OUTstd_logic;

B:

OUTstd_logic;

C:

OUTstd_logic;

D:

OUTstd_logic;

E:

OUTstd_logic;

F:

OUTstd_logic;

G:

OUTstd_logic;

DP:

OUTstd_logic

);

ENDSEG7;

ARCHITECTUREfunOFSEG7IS

signalled:

std_logic_vector(6downto0);

BEGIN

A<=led(6);

B<=led(5);

C<=led(4);

D<=led(3);

E<=led

(2);

F<=led

(1);

G<=led(0);

DP<='0';

led<="1111110"whennum="0000"else

"0110000"whennum="0001"else

"1101101"whennum="0010"else

"1111001"whennum="0011"else

"0110011"whennum="0100"else

"1011011"whennum="0101"else

"1011111"whennum="0110"else

"1110000"whennum="0111"else

"1111111"whennum="1000"else

"1111011"whennum="1001"else

"1110111"whennum="1010"else

"0011111"whennum="1011"else

"1001110"whennum="1100"else

"0111101"whennum="1101"else

"1001111"whennum="1110"else

"1000111"whennum="1111";

ENDfun;

SEG7模块波形仿真如图17:

图17Seg7的波形仿真图(0000-1000)

(注:

当nums输入0000-1000时,A-H输出0-8的相应值)

图17Seg7的波形仿真图1001-1111)

(nums输入1001-1111时,A-H输出9—16的相应值)

4、总体设计电路图

(1)顶层设计的电路原理图如图18:

图18顶层设计的电路原理图

原理:

Notetabs中按Rom表格中已填好的乐曲输出一谱子,转化为相应的二进制数输出,再将输出的二进制数输入Tonetaba中,转化为相应的预置数输入数控分频器Speakera中进行分频并输出,输出接扬声器用于发音。

从Notetabs中输出的二进制数也将对应于Tonetaba中的二进制数,输出接数码显示管用于显示所发音的简码,还有一个高低音的输出连接一个Led灯,灯亮表示高音,灯暗表示低音。

Songer模块就是顶层设计文件,所有的模块都由它调用。

Songer模块的程序为:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

useieee.std_logic_arith.all;

entitysongeris

port(clk8HZ,clk12MHZ:

instd_logic;

num:

outstd_logic_vector(3downto0);

high1:

outstd_logic;

spkout:

outstd_logic);

endentitysonger;

architectureoneofsongeris

componentnotetabs

port(clk1:

instd_logic;

toneindex:

outstd_logic_vector(3downto0));

endcomponent;

componenttonetaba

port(index:

instd_logic_vector(3downto0);

code:

outstd_logic_vector(3downto0);

high:

outstd_logic;

tone:

outstd_logic_vector(10downto0));

endcomponent;

componentspeakera

port(clk2:

instd_logic;

tone:

instd_logic_vector(10downto0);

spks:

outstd_logic);

endcomponent;

signaltone:

std_logic_vector(10downto0);

signaltoneindex:

std_logic_vector(3downto0);

begin

u1:

notetabs

portmap(clk1=>clk8HZ,toneindex=>

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 理化生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1