音乐播放器设计说明

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

音乐播放器说明书
音乐播放器设计说明
1、设计目的
充分利用EITS2003 多用途EDA 开发实验平台的设计资源,完成一个比较复杂的FPGA 设计方案,增强对FPGA 设计的更深理解,提高设计水平,为今后的更复杂的FPGA 设计实践打下坚实的基础。

2、设计概述
EITS2003 多用途EDA 开发实验平台给我们提供了丰富的设计资源。

它的核心器件为Xilinx 公司的Spartan-IIE 系列的FPGA 芯片,且在FPGA 周围提供了丰富的资源:有串口、PS/2 接口、VGA 接口、LED 和七段数码管显示、拨码开关和按钮、AT89S52 单片机、SRAM、I2C、A/D D/A 转换、扬声器、电源、电源晶振等。

这就为我们的设计提供了丰富的选择。

考虑到以后实践的需要,且又要达到一定的难度,我们选择了把几种常用接口PS/2、LED 显示结合的一个电路。

虽然设计并不是很复杂,但其实践意义是很大的。

3、设计方案说明
3.1 总体方案
我们设计的总体思想是:利用EITS2003上的拨码开关选择不同的歌曲进行播放,并在相应的七段数码管及LED显示正在播放的音阶。

3.2 关键部分说明
3.2.1 音乐电路
音乐电路原理:组成乐曲的每个音符的频率值(音调)及持续时间(音长)是实际乐曲演奏的两个基本数据。

因此只要控制输出到扬声器的激励信号的频率和信号的持续时间就可以发出持续的乐曲声。

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

音乐的十二平均率规定:每连个八度音(如简谱中的中音1与高音1)之间的频率相差一倍。

在两个八度音之间,又可以分为十二个半音,每两个半音的频率比为12sqr(2)。

另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间,E到F之间为半音,其余为全音。

由此简谱中从低音1到高音1之间的每个音名对应的频率如下表3所示:
3.3 具体实现 3.3.1 顶层模块
TOP
switch1,2,3
reset
l1,2,3,4,5,6,7
dig1,2,3LED
speaker clock
顶层模块的输入输出如上图所示。

输入:
clock 是电路板时钟的输入,50 兆赫兹; reset 用于系统的初始化;
switch1、switch2、switch3是EITS2003的拨码开关输入,产生音乐选择信号。

输出:
speaker 用于输出不同频率的时钟,使得蜂鸣器发出不同声音; LED 为七段数码管,用于显示高中低音音阶;
dig1、dig2、dig3为三段数码管的控制信号,选择数码管的输出; l1、l2、l3、l4、l5、l6、l7为LED 显示,指示现输出音阶高低。

这些输入输出的对应管脚如下图所示:
3.3.2 该工程模块结构
ShowKey
HEX2LED Freqorigin
song1switch Freq_Div top
工程模块层次结构图
3.3.3 程序说明 3.3.3.1 Freq_Div 模块
/*****************************************************************************/ Freq_Div.v
模块名称: Freq_Div()
模块功能: 按输入参数对输入时钟进行分频,输出 Clk_User <= Clk_Sys/Div
输入输出: Clk_Sys 输入,输入时钟,一般为系统时钟,1 位 Div 输入,分频参数输入,26 位
Clk_User 输出,分频后的时钟输出,1 位
/*****************************************************************************/ module Freq_Div(Clk_Sys,Div,Clk_User,Reset);
input Clk_Sys;
input [25:0] Div;
output Clk_User;
input Reset;
reg Clk_Usertemp;
reg[25:0] cout;
assign Clk_User=(Div>=2)?Clk_Usertemp:Clk_Sys; //若Div比2小,输出系统时钟
always @(posedge Clk_Sys or negedge Reset) //等待系统时钟上升沿
if(!Reset)
begin
cout<=26'b0;
Clk_Usertemp<=1'b0;
end
else
begin
if(Div>=26'h000_0002)
begin
if(cout>=Div-1) //输出达到一个周期,重新开始
begin
Clk_Usertemp<=1'b0;
cout<=26'h000_0000;
end
else if(cout>=((Div>>1)-1))
begin
cout<=cout+1;
Clk_Usertemp<=1'b1;
end
else
begin
Clk_Usertemp<=1'b0;
cout<=cout+1;
end
end
end
endmodule
3.3.3.2HEX2LED 模块
/****************************************************************************/ HEX2LED.v
/****************************************************************************/
//***************************************************************************** //HEX-to-seven-segment decoder
// input [3:0] HEX;
// output [6:0] LED;
// reg [6:0] LED;
//
// segment encoding
// 0
// //-
// 5 | | 1
// //- <- 6
// 4 | | 2
// //-
// 3
//***************************************************************************** module HEX2LED(HEX,LED);
//***************************************************************************** // HEX:输入十六进制信号
// LED:输出显示信号
//***************************************************************************** input [3:0] HEX;
output [6:0] LED;
reg [6:0] LED;
always @(HEX)
begin
case (HEX)
4'b0001 : LED <= 7'b0000110; //1
4'b0010 : LED <= 7'b1011011; //2
4'b0011 : LED <= 7'b1001111; //3
4'b0100 : LED <= 7'b1100110; //4
4'b0101 : LED <= 7'b1101101; //5
4'b0110 : LED <= 7'b1111101; //6
4'b0111 : LED <= 7'b0000111; //7
4'b1000 : LED <= 7'b1111111; //8
4'b1001 : LED <= 7'b1101111; //9
4'b1010 : LED <= 7'b1110111; //A
4'b1011 : LED <= 7'b1111100; //b
4'b1100 : LED <= 7'b0111001; //C
4'b1101 : LED <= 7'b1011110; //d
4'b1110 : LED <= 7'b1111001; //E
4'b1111 : LED <= 7'b1110001; //F
default : LED <= 7'b0111111; //0
endcase
end
endmodule
3.3.3.3 ShowKey模块
/****************************************************************************/ ShowKey.v
根据音阶高低,相应的LED发亮。

/****************************************************************************/ module ShowKey(selectLED,l1,l2,l3,l4,l5,l6,l7);
input [3:0] selectLED;
output l1;
output l2;
output l3;
output l4;
output l5;
output l6;
output l7;
reg l1,l2,l3,l4,l5,l6,l7;
always @(selectLED)
begin
case (selectLED)
4'b0001: {l1,l2,l3,l4,l5,l6,l7}<=7'b0111111;
4'b0010: {l1,l2,l3,l4,l5,l6,l7}<=7'b1011111;
4'b0011: {l1,l2,l3,l4,l5,l6,l7}<=7'b1101111;
4'b0100: {l1,l2,l3,l4,l5,l6,l7}<=7'b1110111;
4'b0101: {l1,l2,l3,l4,l5,l6,l7}<=7'b1111011;
4'b0110: {l1,l2,l3,l4,l5,l6,l7}<=7'b1111101;
4'b0111: {l1,l2,l3,l4,l5,l6,l7}<=7'b1111110;
default: {l1,l2,l3,l4,l5,l6,l7}<=7'b1111111;
endcase
end
endmodule
3.3.3.4 switch模块
/**************************************************************************/ switch.v
根据三个拨码开关的情况,选择相应的歌曲输出
/**************************************************************************/ module switch(clk_4,clk_6M,switchnum,selectLED,dig1,dig2,dig3,speaker);
input [2:0] switchnum;
input clk_4,clk_6M;
output selectLED;
output dig1,dig2,dig3;
output speaker;
wire clk_4,clk_6M;
wire [3:0] high,med,low;
reg [3:0] selectLED;
reg dig1,dig2,dig3;
song1 mysong (
.clk_4Hz(clk_4),
.clk_6MHz(clk_6M),
.switchnum(switchnum),
.speaker(speaker),
.high(high),
.med(med),
.low(low)
);
always @(high or med or low)
begin
if(high!=4'b0000)
begin
dig1<=0;
dig2<=1;
dig3<=1;
selectLED<=high;
end
if(med!=4'b0000)
begin
dig1<=1;
dig2<=0;
dig3<=1;
selectLED<=med;
end
if(low!=4'b0000)
begin
dig1<=1;
dig2<=1;
dig3<=0;
selectLED<=low;
end
end
endmodule
3.3.3.5 song1模块
/****************************************************************************/ song1.v
记录歌谱内容。

当拨码开关为高电平时,输出相应的歌曲,若拨码开关状态不变,实现循环播放。

/****************************************************************************/ module song1(clk_4Hz,clk_6MHz,switchnum,speaker,high,med,low);
input clk_4Hz;
input clk_6MHz;
input switchnum;
output speaker;
output high,med,low;
wire [2:0] switchnum;
reg[3:0] high,med,low;
reg[13:0] divider;
wire[13:0] origin;
reg[7:0] counter;
reg speaker;
wire carry;
assign carry=(divider==16383);
always @(posedge clk_6MHz)
begin
if(carry) divider=origin;
else divider=divider+1;
end
always @(posedge carry)
begin
speaker=~speaker;
end
Freqorigin myorigin (
.clk_4Hz(clk_4Hz),
.high(high),
.med(med),
.low(low),
.origin(origin)
);
always @(posedge clk_4Hz)
begin
if(switchnum==3'b100)
begin
if(counter==63) counter=0;
else counter=counter+1; case(counter)
0: {high,med,low}='b000000000011; 1: {high,med,low}='b000000000011; 2: {high,med,low}='b000000000011; 3: {high,med,low}='b000000000011; 4: {high,med,low}='b000000000101; 5: {high,med,low}='b000000000101; 6: {high,med,low}='b000000000101; 7: {high,med,low}='b000000000110; 8: {high,med,low}='b000000010000; 9: {high,med,low}='b000000010000; 10: {high,med,low}='b000000010000; 11: {high,med,low}='b000000100000; 12: {high,med,low}='b000000000110; 13: {high,med,low}='b000000010000; 14: {high,med,low}='b000000000101; 15: {high,med,low}='b000000000101;
16: {high,med,low}='b000001010000; 17: {high,med,low}='b000001010000; 18: {high,med,low}='b000001010000; 19: {high,med,low}='b000100000000; 20: {high,med,low}='b000001100000; 21: {high,med,low}='b000001010000; 22: {high,med,low}='b000000110000; 23: {high,med,low}='b000001010000; 24: {high,med,low}='b000000100000; 25: {high,med,low}='b000000100000; 26: {high,med,low}='b000000100000; 27: {high,med,low}='b000000100000;
28: {high,med,low}='b000000100000; 29: {high,med,low}='b000000100000; 30: {high,med,low}='b000000100000; 31: {high,med,low}='b000000100000;
32: {high,med,low}='b000000100000; 33: {high,med,low}='b000000100000; 34: {high,med,low}='b000000100000; 35: {high,med,low}='b000000110000; 36: {high,med,low}='b000000000111; 37: {high,med,low}='b000000000111; 38: {high,med,low}='b000000000110; 39: {high,med,low}='b000000000110; 40: {high,med,low}='b000000000101; 41: {high,med,low}='b000000000101; 42: {high,med,low}='b000000000101; 43: {high,med,low}='b000000000110; 44: {high,med,low}='b000000010000; 45: {high,med,low}='b000000010000; 46: {high,med,low}='b000000100000; 47: {high,med,low}='b000000100000;
48: {high,med,low}='b000000000011; 49: {high,med,low}='b000000000011; 50: {high,med,low}='b000000010000; 51: {high,med,low}='b000000010000; 52: {high,med,low}='b000000000110; 53: {high,med,low}='b000000000101; 54: {high,med,low}='b000000000110; 55: {high,med,low}='b000000010000; 56: {high,med,low}='b000000000101; 57: {high,med,low}='b000000000101; 58: {high,med,low}='b000000000101; 59: {high,med,low}='b000000000101; 60: {high,med,low}='b000000000101; 61: {high,med,low}='b000000000101; 62: {high,med,low}='b000000000101; 63: {high,med,low}='b000000000101; endcase
end
if(switchnum==3'b010)
begin
if(counter==100) counter=0;
else counter=counter+1;
case(counter)
0: {high,med,low}='b000000000101; //中音5 1: {high,med,low}='b000000000101;
2: {high,med,low}='b000000000101;
3: {high,med,low}='b000000000101;
4: {high,med,low}='b000000000110; //中音6 5: {high,med,low}='b000000000110;
6: {high,med,low}='b000000000110;
7: {high,med,low}='b000000000110;
8: {high,med,low}='b000000000101; //中音5 9: {high,med,low}='b000000000101;
10: {high,med,low}='b000000000101;
11: {high,med,low}='b000000000101;
12: {high,med,low}='b000000010000; //高音1 13: {high,med,low}='b000000010000;
14: {high,med,low}='b000000010000;
15: {high,med,low}='b000000010000;
16: {high,med,low}='b000000000111; //中音7 17: {high,med,low}='b000000000111;
18: {high,med,low}='b000000000111;
19: {high,med,low}='b000000000111;
20: {high,med,low}='b000000000111;
21: {high,med,low}='b000000000111;
22: {high,med,low}='b000000000111;
23: {high,med,low}='b000000000111;
24: {high,med,low}='b000000000111;
25: {high,med,low}='b000000000101; //中音5 26: {high,med,low}='b000000000101;
27: {high,med,low}='b000000000101;
28: {high,med,low}='b000000000101;
29: {high,med,low}='b000000000110; //中音6 30: {high,med,low}='b000000000110;
31: {high,med,low}='b000000000110;
32: {high,med,low}='b000000000110;
33: {high,med,low}='b000000000101; //中音5 34: {high,med,low}='b000000000101;
35: {high,med,low}='b000000000101;
36: {high,med,low}='b000000000101;
37: {high,med,low}='b000000100000; //高音2 38: {high,med,low}='b000000100000;
39: {high,med,low}='b000000100000;
40: {high,med,low}='b000000100000;
41: {high,med,low}='b000000010000; //高音1 42: {high,med,low}='b000000010000;
43: {high,med,low}='b000000010000;
44: {high,med,low}='b000000010000;
45: {high,med,low}='b000000010000;
46: {high,med,low}='b000000010000;
47: {high,med,low}='b000000010000;
48: {high,med,low}='b000000010000;
49: {high,med,low}='b000000000101; //中音5 50: {high,med,low}='b000000000101;
51: {high,med,low}='b000000000101;
52: {high,med,low}='b000000000101;
53: {high,med,low}='b000001010000; //高音5 54: {high,med,low}='b000001010000;
55: {high,med,low}='b000001010000;
56: {high,med,low}='b000001010000;
57: {high,med,low}='b000000110000; //高音3 58: {high,med,low}='b000000110000;
59: {high,med,low}='b000000110000;
60: {high,med,low}='b000000110000;
61: {high,med,low}='b000000010000; //高音1 62: {high,med,low}='b000000010000;
63: {high,med,low}='b000000010000;
64: {high,med,low}='b000000010000;
65: {high,med,low}='b000000000111; //中音7 66: {high,med,low}='b000000000111;
67: {high,med,low}='b000000000111;
68: {high,med,low}='b000000000111;
69: {high,med,low}='b000000000110; //中音6 70: {high,med,low}='b000000000110;
71: {high,med,low}='b000000000110;
72: {high,med,low}='b000000000110;
73: {high,med,low}='b000000000110;
74: {high,med,low}='b000000000110;
75: {high,med,low}='b000000000110;
76: {high,med,low}='b000000000110;
77: {high,med,low}='b000000100000; //高音4 78: {high,med,low}='b000000100000;
79: {high,med,low}='b000000100000;
80: {high,med,low}='b000000100000;
81: {high,med,low}='b000000110000; //高音3 82: {high,med,low}='b000000110000;
83: {high,med,low}='b000000110000;
84: {high,med,low}='b000000110000;
85: {high,med,low}='b000000010000; //高音1 86: {high,med,low}='b000000010000;
87: {high,med,low}='b000000010000;
88: {high,med,low}='b000000010000;
89: {high,med,low}='b000000100000; //高音2 90: {high,med,low}='b000000100000;
91: {high,med,low}='b000000100000;
92: {high,med,low}='b000000100000;
93: {high,med,low}='b000000010000; //高音1 94: {high,med,low}='b000000010000;
95: {high,med,low}='b000000010000;
96: {high,med,low}='b000000010000;
97: {high,med,low}='b000000010000;
98: {high,med,low}='b000000010000;
99: {high,med,low}='b000000010000;
100: {high,med,low}='b000000010000;
endcase
end
if(switchnum==3'b001)
begin
if(counter==63) counter=0;
else counter=counter+1;
case(counter)
0: {high,med,low}='b000000000011; //中音3 1: {high,med,low}='b000000000010; //中音2 2: {high,med,low}='b000000000011; //中音3 3: {high,med,low}='b000000000101; //中音5 4: {high,med,low}='b000000000110; //中音6 5: {high,med,low}='b000000000101; //中音5 6: {high,med,low}='b000000010000; //高音1 7: {high,med,low}='b000000000110; //中音6 8: {high,med,low}='b000000000101; //中音5 9: {high,med,low}='b000000000011; //中音3 10: {high,med,low}='b000000000101; //中音5 11: {high,med,low}='b000000000101;
12: {high,med,low}='b000000000101;
13: {high,med,low}='b000000000101;
14: {high,med,low}='b000000000110; //中音6 15: {high,med,low}='b000000000110;
16: {high,med,low}='b000000010000; //高音1 17: {high,med,low}='b000000010000;
18: {high,med,low}='b000000100000; //高音2 19: {high,med,low}='b000000110000; //高音3 20: {high,med,low}='b000000100000; //高音2 21: {high,med,low}='b000000010000; //高音1 22: {high,med,low}='b000000000110; //中音6 23: {high,med,low}='b000000010000; //高音1 24: {high,med,low}='b000000000101; //中音5 25: {high,med,low}='b000000000101;
26: {high,med,low}='b000000000101;
27: {high,med,low}='b000000000101;
28: {high,med,low}='b000000000101;
29: {high,med,low}='b000000000101;
30: {high,med,low}='b000000000101;
31: {high,med,low}='b000000000101;
32: {high,med,low}='b000000000101; //中音5 33: {high,med,low}='b000000000011; //中音3 34: {high,med,low}='b000000000101; //中音5 35: {high,med,low}='b000000000101;
36: {high,med,low}='b000000000101;
37: {high,med,low}='b000000000101;
38: {high,med,low}='b000000000110; //中音6 39: {high,med,low}='b000000000110;
40: {high,med,low}='b000000010000; //高音1 41: {high,med,low}='b000000010000;
42: {high,med,low}='b000000100000; //高音2 43: {high,med,low}='b000000110000; //高音3 44: {high,med,low}='b000000010000; //高音1 45: {high,med,low}='b000000000110; //中音6 46: {high,med,low}='b000000000101; //中音5 47: {high,med,low}='b000000000101;
48: {high,med,low}='b000000000101;
49: {high,med,low}='b000000000101;
50: {high,med,low}='b000000000010; //中音2 51: {high,med,low}='b000000000010;
52: {high,med,low}='b000000000011; //中音3 53: {high,med,low}='b000000000101; //中音5 54: {high,med,low}='b000000000011; //中音3 55: {high,med,low}='b000000000010; //中音2 56: {high,med,low}='b000000000001; //中音1 57: {high,med,low}='b000000000001;
58: {high,med,low}='b000000000001;
59: {high,med,low}='b000000000001;
60: {high,med,low}='b000000000001;
61: {high,med,low}='b000000000001;
62: {high,med,low}='b000000000001;
63: {high,med,low}='b000000000001;
endcase
end
if(switchnum==3'b000)
begin
{high,med,low}='b000000000000;
counter=0;
end
end
endmodule
3.3.3.6 Freqorigin模块
/*************************************************************************/ Freqorigin.v
设置分频比,实现不同音阶不同频率的
/*************************************************************************/ module Freqorigin(clk_4Hz,high,med,low,origin);
input clk_4Hz;
input [3:0] high,med,low;
output origin;
reg[13:0] origin;
always @(posedge clk_4Hz)
begin
case({high,med,low})
'b000000000001: origin=5864;
'b000000000010: origin=6168;
'b000000000011: origin=7086;
'b000000000100: origin=7663;
'b000000000101: origin=8730;
'b000000000110: origin=9565;
'b000000000111: origin=10310;
'b000000010000: origin=10647;
'b000000100000: origin=11272;
'b000000110000: origin=11831;
'b000001000000: origin=12066;
'b000001010000: origin=12556;
'b000001100000: origin=12974;
'b000001110000: origin=13335;
'b000100000000: origin=13516;
'b000000000000: origin=16383;
endcase
end
endmodule
3.3.3.7 top模块
/****************************************************************************/ top.v
/***************************************************************************/ module top(clock,reset,switch1,switch2,switch3,speaker,LED,dig1,dig2,dig3,l1,l2,l3,l4,l5,l6,l7);
input clock;
input reset;
input switch1;
input switch2;
input switch3;
output speaker;
output [6:0] LED;
output dig1,dig2,dig3;
output l1,l2,l3,l4,l5,l6,l7;
wire dig1,dig2,dig3;
wire [25:0] d1,d2;
wire [3:0] selectLED;
wire clk_4,clk_6M;
wire [2:0] switchnum;
assign d1=26'h0BEBC20;
assign d2=26'h08;
assign switchnum={switch1,switch2,switch3};
Freq_Div myFreq_Div(clock,d1,clk_4,reset);
Freq_Div myFreq_Div2(clock,d2,clk_6M,reset);
switch chosesong (
.switchnum(switchnum),
.clk_4(clk_4),
.clk_6M(clk_6M),
.selectLED(selectLED),
.dig1(dig1),
.dig2(dig2),
.dig3(dig3),
.speaker(speaker)
);
HEX2LED showkey (
.HEX(selectLED),
.LED(LED)
);
ShowKey instance_name (
.selectLED(selectLED),
.l1(l1),
.l2(l2),
.l3(l3),
.l4(l4),
.l5(l5),
.l6(l6),
.l7(l7)
);
endmodule
4、设计的改进设想
由于时间的关系,该设计并不完善,还有许多方面需要改进。

列举如下:1)没加入键盘音阶输入,让用户自己编歌;
2)歌曲数量较少;
5、体会
在上这门课之前,我们可以说是对FPGA 的设计完全不了解,但在上了这门课之后,再加上我们的实际动手设计,让我们学到了很多,亲身体会到应用FPGA 进行实际设计的无穷乐趣。

在整个设计过程中,我们体会到:无论多么简单的东西,都一定要实际动手去研究去理解它,很简单的时间也会给我们增加很多的经验;无论多么复杂的设计,都是由无数简单的设计堆砌、发展而来的;别人的经验是我们很好的借鉴,
我们可以站在巨人的肩膀上更上一层楼,但是我们同时也一定要有坚实的基础,借鉴的别人的经验定要好好消化吸收,使之完全成为自己的东西。

前辈们常说的FPGA 的四大设计原则:
1)面积和速度的平衡和互换;
2)硬件原则;
3)系统原则;
4)同步设计原则。

以前对这一知半解,通过这次实际的设计,虽然不能说有很深的体会,但起码有点明白这些原则的道理,同时也有了那么一点体会。

对于FPGA 技术,我们还只是刚入门,前面还有很多的路要走,一切的成功都离不开自己的努力钻研,要想成为真正的高手,还需要下很多的功夫。

相关文档
最新文档