内容发布更新时间 : 2024/12/27 13:32:15星期一 下面是文章的全部内容请认真阅读。
硬件电子琴电路模块设计
一、实验目的:
学习利用数控分频器设计硬件电子琴实验。 二、实验原理:
实验用FPGA实现乐曲的播放原理: ? 分四步
1、将待播放的《梁祝》音乐音符存入ROM 2、以4HZ频率读取ROM
3、根据1MHZ的内部时钟要求,将读出的音符换算成应计数的数值 4、以1MHZ为内部时钟,实现符合要求的方波信号。
图1 硬件电子琴电路结构
主系统由五个模块组成,songer.v是顶层设计文件,其内部有五个功能模块(如图1所示):Speakera.v 和ToneTaba.v,NoteTabs.v,div_50_12M.v,div_50_4HZ.v。
模块ToneTaba是音阶发生器,当8位发声控制输入Index中某一位为高电平时,则对应某一音阶的数值将从端口Tone输出,作为获得该音阶的分频预置值;同时由Code输出对应该音阶简谱的显示数码,如‘5’,并由High输出指示音阶高8度显示。
模块Speakera中的主要电路是一个数控分频器,它由一个初值可预置的加法计数器构成,当模块Speakera由端口Tone获得一个2进制数后,将以此值为计数器的预置数,对端口Clk12MHZ输入的频率进行分频,之后由Spkout向扬声器输出发声。
增加一个NoteTabs模块用于产生节拍控制(Index数据存留时间)和音阶选择信号,即在NoteTabs模块放置一个乐曲曲谱真值表,由一个计数器的计数值来控制此真值表的输出,而由此计数器的计数时钟信号作为乐曲节拍控制信号,从而可以设计出一个纯硬件的乐曲自动演奏电路。
div_50_12M.v是由于实验板上,只有50MHZ有源晶振,故将用50MHZ进行分频实现12.5MHZ的时钟,在后续模块Speakera.v中再分频得到近似1MHZ时钟。
div_50_4HZ.v是用系统需要4HZ频率读ROM,于是用50MHZ,分频得到4HZ频率。
三、实验内容:
1.自己编写12.5 MHZ和4HZ的分频程序div_50_12M和div_50_4HZ。用CLOCK=50MHZ(PIN_N2)的输入频率接入并进行分频得12.5MHz,此信号作为Speakera模块的输入频率;用CLOCK=50MHZ的输入频率接入并进行分频得4Hz,此信号作为NoteTabs模块的输入频率。
2.Music模块用ROM的IP CORE存放“梁祝”乐曲演奏数据,编写并加载.COE文件放置梁祝”乐曲演奏数据。
3.编译适配以上文件,给出仿真波形,最后进行下载和硬件测试实验。 4.选择LD5~LD2发光管显示Code[3]~Code[0]表示琴音简谱码,发光管LD7显示高8度,SPEAKOUT接蜂鸣器端口。
工程分布:
顶层模块:songer.v
module songer(clk_50M,reset,Code1,High1,Spkout); input clk_50M;//CLK=50MHZ input reset;
output[3:0] Code1; output High1,Spkout; wire[10:0] Tone;
wire[3:0] ToneIndex;
wire clk_4HZ,clk_12M; NoteTabs u0( .Clk(clk_4HZ), .ToneIndex(ToneIndex) );
ToneTaba u1( .Index(ToneIndex), .Code(Code1), .High(High1), .Tone(Tone) ); Speakera u2( .Clk(clk_12M), .Tone(Tone), .SpkS(Spkout) );
div_50_12M u3(clk_50M,clk_12M,reset); div_50_4HZ u4(clk_50M,clk_4HZ,reset); endmodule
NoteTabs模块:
module NoteTabs(Clk,ToneIndex); input Clk;
output[3:0] ToneIndex; reg[7:0] Counter;
always@(posedge Clk ) begin if(Counter>=138) Counter<=8'b00000000; else Counter<=Counter+1'b1; end
Music u5( .address(Counter), .clock(Clk), .q(ToneIndex) ); endmodule
ToneTaba模块:
module ToneTaba (Index,Code,High,Tone); input[3:0] Index; output[3:0] Code; output High; output[10:0] Tone; reg[3:0] Code; reg High; reg[10:0] Tone; always @ (Index) begin
case(Index)
4'b0000 :begin Tone<=11'b11111111111;Code<=4'b0000;High<=1'b0;end//2047 4'b0001 :begin Tone<=11'b01100000101;Code<=4'b0001;High<=1'b0;end//773 4'b0010 :begin Tone<=11'b01110010000;Code<=4'b0010;High<=1'b0;end//912 4'b0011 :begin Tone<=11'b10000001100;Code<=4'b0011;High<=1'b0;end//1036