谢海海 简易电子琴设计
乐曲演奏的原理是这样的:组成乐曲的每个音符的频率值(音调)及其持续的时间(音长)是乐曲能连续演奏所需的两个基本数据,因此只要控制输出到扬声器的激励信号频率的高低和持续的时间,就可以使扬声器发出连续的乐曲声。
图3 乐曲自动演奏模块仿真图
当 auto为“0”时,由存储在此模块中的8位二进制数作为发声控制输入,可自动演奏乐曲。 (3) 数控分频模块
数控分频模块是对时基脉冲进行分频,得到与1、2、3、4、5、6、7七个音符相对应的频率。
图4 数控分频模块的仿真图
数控分频模块对时基脉冲进行分频,得到与1、2、3、4、5、6、7七个音符对应频率。该图输入系统时钟信号CLK1初值为0(各输出值都是在时钟信号的下降沿有效),音符分频系数TONE1为00100000即1290Hz,驱动扬声器的音频信号SPKS输出为1。 (4) 顶层设计
顶层模块由乐曲自动演奏(auto),音调发生器(tone)和数控分频器(fenpin)三个模块组成。设置一个自动演奏/键盘输入切换auto,即当auto=“0”时,选择自动演奏音乐存储器里面的乐曲,auto=“1”时,选择键盘输入的信号。输入系统时钟信号CLK32MHZ初值为0,自动演奏信号HANDTOAUTO初值为0,键盘输入信号INDEX1为00000000;输出音符信号CODE1则为0110000,高低音节信号HIGH1变为1,即高音,音频信号SPKOUT即输出0,输出为1时CODE1变为0110100,这时出现10ns的延时。在仿真时由于系统各方面原因影响,出现延时属于正常现象。
也许是能力不够,再加上临近期末时间较为紧迫,顶层设计没能做出来,程序在编译过程中出错,可是知识范围太窄,没能找出错误所在,导致顶层的模块没能完成,因此也没有仿真的图形出来。
9.结束语
6
谢海海 简易电子琴设计
到现在为止,简易电子琴的设计基本上告一段落,虽然由于自身问题没能很好地完成设计的要求,但是在设计的过程中,我受益匪浅,自身的知识能力得到了锻炼的同时还对专业的认识有了进一步的加强。
通过几天的课程设计,我对数据库软件EDA技术、Verilog HDL、等系列知识都有了一定的了解。使用EDA技术开发页面的能力也有了很大提高。这个程序设计让我学会一种新的语言,对数字系统结构也有了更进一步的了解和认识,对我以后的学习有很大的帮助。
通过这次的设计,我也认识到自己的缺点和不足,如对专业理论知识了解不够透彻,不能很好地将之运用于实践中,虽然在暑期的电子设计大赛中有过动手能力的增强训练,但是对于我们电子专业的学生,实践能力是占非常大的比重的,因此在接下来的日子里,提高自己的实践能力是重点,而且必须加深对专业知识的理解。
参考文献:
[1]曹昕燕、周凤臣、聂春燕:《EDA技术实验与课程设计》 清华大学出版社 [2]王金明 《数字系统设计与Verilog HDL》 电子工业出版社
附录:
附录1:乐曲自动演奏源程序清单
module AUTO (CLK, AUTO, CLK2, INDEX2, INDEX0); input CLK; input AUTO; output CLK2; reg CLK2;
input[7:0] INDEX2; output[7:0] INDEX0; reg[7:0] INDEX0; reg[4:0] COUNT0; always @(CLK or AUTO) begin : PULSE0 reg[3:0] COUNT; if (AUTO == 1'b1) begin
COUNT = 0; CLK2 <= 1'b0 ; end
else if (CLK == 1'b1) begin
COUNT = COUNT + 1; if (COUNT == 4) begin
7
CLK2 <= 1'b1 ; end
else if (COUNT == 8) begin
CLK2 <= 1'b0 ; COUNT = 0; end end end
always @(CLK2) begin : MUSIC if (CLK2 == 1'b1) begin
if (COUNT0 == 31) begin
COUNT0 <= 0 ; end else begin
COUNT0 <= COUNT0 + 1 ; end end
谢海海 简易电子琴设计
end
always @(COUNT0 or AUTO or INDEX2) begin : COM1
if (AUTO == 1'b0) begin
case (COUNT0) 0 :
begin
INDEX0 <= 8'b00000100 ; end 10 :
begin
INDEX0 <= 8'b10000000 ; end 11 :
begin
INDEX0 <= 8'b00000100 ; end end 1 :
begin
INDEX0 <= 8'b00000100 ; end 2 :
begin
INDEX0 <= 8'b00000100 ; end 3 :
begin
INDEX0 <= 8'b00000100 ; end 4 :
begin
INDEX0 <= 8'b00010000 ; end 5 :
begin
INDEX0 <= 8'b00010000 ; end 6 :
begin
INDEX0 <= 8'b00010000 ; end 7 :
begin
INDEX0 <= 8'b00100000 ; end 8 :
begin
INDEX0 <= 8'b10000000 ; end 9 :
begin
INDEX0 <= 8'b10000000 ;
12 :
begin
INDEX0 <= 8'b00000010 ; end 13 :
begin
INDEX0 <= 8'b00000010 ; end 14 :
begin
INDEX0 <= 8'b00000001 ; end 15 :
begin
INDEX0 <= 8'b00000001 ; end 16 :
begin
INDEX0 <= 8'b00010000 ; end 17 :
begin
INDEX0 <= 8'b00010000 ; end 18 :
begin
INDEX0 <= 8'b00001000 ; end 19 :
begin
INDEX0 <= 8'b00001000 ; end 20 :
begin
INDEX0 <= 8'b00001000 ; end
8
谢海海 简易电子琴设计
21 :
begin
INDEX0 <= 8'b00000100 ; end 22 :
begin
INDEX0 <= 8'b00000010 ; end 23 :
begin
INDEX0 <= 8'b00000010 ; end 24 :
begin
INDEX0 <= 8'b00010000 ; end 25 :
begin
INDEX0 <= 8'b00010000 ; end 26 :
begin
INDEX0 <= 8'b00001000 ; end 27 :
begin
INDEX0 <= 8'b00001000 ; end
附录2:音调发生源程序清单
module TONE_A (INDEX, CODE, HIGH, TONE0);
input[7:0] INDEX; output[6:0] CODE; reg[6:0] CODE; output HIGH; reg HIGH;
output[10:0] TONE0; reg[10:0] TONE0;
always @(INDEX) begin : SEARCH case (INDEX) 8'b00000001 : begin
28 :
begin
INDEX0 <= 8'b00000100 ; end 29 :
begin
INDEX0 <= 8'b00000100 ; end 30 :
begin
INDEX0 <= 8'b00000010 ; end 31 :
begin
INDEX0 <= 8'b00000010 ; end default : begin end endcase end else begin
INDEX0 <= INDEX2 ; end end endmodule
TONE0 <= 773 ; CODE <= 7'b1001111 ; HIGH <= 1'b1 ; end 8'b00000010 : begin
TONE0 <= 912 ; CODE <= 7'b0010010 ; HIGH <= 1'b1 ; end 8'b00000100 : begin
TONE0 <= 1036 ; CODE <= 7'b0000110 ; HIGH <= 1'b1 ; 9
谢海海 简易电子琴设计
end 8'b00001000 : begin
TONE0 <= 1116 ; CODE <= 7'b1001100 ; HIGH <= 1'b1 ; end 8'b00010000 : begin
TONE0 <= 1197 ; CODE <= 7'b0100100 ; HIGH <= 1'b1 ; end 8'b00100000 : begin
TONE0 <= 1290 ; CODE <= 7'b0100000 ; HIGH <= 1'b0 ; end 8'b01000000 :
附录3:数控分频源程序清单
module FENPIN (CLK1, TONE1, SPKS);
input CLK1; input[10:0] TONE1; output SPKS; reg SPKS;
reg PRECLK; reg FULLSPKS;
always @(CLK1) begin : xhdl_1 reg[3:0] COUNT; if (CLK1 == 1'b1) begin
COUNT = COUNT + 1; if (COUNT == 2) begin
PRECLK <= 1'b1 ; end
else if (COUNT == 4) begin
PRECLK <= 1'b0 ;
begin
TONE0 <= 1372 ; CODE <= 7'b0001111 ; HIGH <= 1'b0 ; end 8'b10000000 : begin
TONE0 <= 1410 ; CODE <= 7'b0000000 ; HIGH <= 1'b0 ; end default : begin
TONE0 <= 2047 ; CODE <= 7'b0000001 ; HIGH <= 1'b0 ; end endcase end endmodule
COUNT = 0; end end end
always @(PRECLK or TONE1) begin : xhdl_3
reg[10:0] COUNT11; if (PRECLK == 1'b1) begin
if (COUNT11 < TONE1) begin
COUNT11 = COUNT11 + 1; FULLSPKS <= 1'b1 ; end else begin
COUNT11 = 0; FULLSPKS <= 1'b0 ; end end end
2