verilog课程设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计
设计题目:基于FPGA的乐曲演奏电路设计
✧指导教师:蒋俊华
✧学院:物理与电子学院
✧专业:电子信息科学与技术
✧姓名:郭志勇
✧学号:10230*******
✧实验地点:特种功能实验室(实验室502)
摘要:本文根据层次化的设计思路并在EDA开发工具Quartus II 9.0 (32-Bit) 平台上,采用Verilog语言、原理图、定制LPM-ROM块以及实例化的设计方法,利用数控分频的原理实现了基于FPGA片上系统(本实验用的是康芯GW48系列EDA设备)乐曲演奏的设计。
关键词 FPGA,EDA,Verilog,数控分频器
一. 概述部分:
(1)设计所要实现的功能
能够很好的演奏出“梁祝”的谱子,将音乐通过实验箱上的喇叭播放出;演奏发音相对应的简谱码输出显示由在数码管5显示;高八度音指示由发光管D5指示
(2)设计所采用的基本思想
根据层次化的设计思路,可把乐曲硬件演奏电路分为3个模块,音乐节拍发生模块,音符译码电路模块,数控分频模块。
音乐节拍发生模块的设计:将编辑好的音符填入MIF文件中再定制LPM-ROM块将音符数据加载入ROM再通过计数器逐步计数rom块的地址来提取音符;音符译码电路模块、数控分频模块的设计:都是由verilog代码实例化生成
通过输入原理图的方法将各个模块连接起来生成一个block块的.qpf文件作为最终的顶层文件。
二.系统设计部分
(1)整个设计的组织结构
(2)各个子单元的设计思路
音乐节拍发生模块的设计:
LPM-ROM块该模块为音乐曲谱的存放块。
其中设置了“梁祝”乐曲全部音符所对应的分频预置数。
其利用LPM_ROM宏模块将共设定256个音符,每个音符宽度为4位。
Mif文件存放乐曲中的音符数据,它是利用LPM-ROM来实现的,将乐谱中相应的音符放在一个连续的地址上。
它首先是编写音符数据文件,将乐谱中相应的音符存放在一个连续的地址上。
因为1拍的时间定为1秒,提供的是4Hz的时钟频率(即1/4拍的整数倍),则需将这个音符存储在相应次数的连续几个地址上。
.mif文件如下:
CNT138块这个计数器的计数频率选为4Hz,即每一计数值的停留时间为0.25秒,恰为当全音符设为1秒,四四拍的4分音符持续时间。
例如,地址发生器在以下的Verilog逻辑描述中,“梁祝”乐曲的第一个音符为“3”,此音在逻辑中停留了4个时钟节拍,即1秒时间。
模块程序如下:
module cnt138t(clk,cnt);
input clk;
output [7:0]cnt;
reg [7:0]cnt;
always @ (posedge clk)
begin
if(cnt==8'b10001010) cnt<=8'b00000000;
else cnt<=cnt+1;
end
endmodule
音符译码电路模块的设计:
音符译码电路模块即分频预置数模块是乐曲简谱码对应的分频预置数查表电路。
它提供了每个音符所对应的分频预置数,即给数控分频模块提供计数初值,这里以“梁祝”乐曲为例,列出了在这个乐曲中所用到的13个音符的分频预置数。
在这个模块的Verilog逻辑描述中设置了“梁祝”乐曲中全部音符所对应的分频预置数,共13个,每一音符的停留时间由音乐节拍和地址发生器模块的时钟(Clk)的输入频率决定,在此为4Hz。
这13个值的输出由计数模块的index[3..0]确定,而index[3..0]的值又由地址发生器模块的输出q[3..0]的输出值和持续时间决定。
程序如下:
module tonetaba(index,code,high,tone);
input [3:0]index;
output [3:0]code;
output [10:0]tone;
output high;
reg [3:0]code;
reg [10:0]tone;
reg high;
always @ (index)
begin
case(index)
4'b0000: begin tone<=11'b11111111111; code<=4'b0000; high<=1'b0; end
4'b0001: begin tone<=11'b01100000101; code<=4'b0001; high<=1'b0; end
4'b0010: begin tone<=11'b01110010000; code<=4'b0010; high<=1'b0; end
4'b0011: begin tone<=11'b10000001100; code<=4'b0011; high<=1'b0; end
4'b0101: begin tone<=11'b10010101101; code<=4'b0101; high<=1'b0; end
4'b0110: begin tone<=11'b10100001010; code<=4'b0110; high<=1'b0; end
4'b0111: begin tone<=11'b10101011100; code<=4'b0111; high<=1'b0; end
4'b1000: begin tone<=11'b10110000010; code<=4'b0001; high<=1'b1; end
4'b1001: begin tone<=11'b10111001000; code<=4'b0010; high<=1'b1; end
4'b1010: begin tone<=11'b11000000110; code<=4'b0011; high<=1'b1; end
4'b1100: begin tone<=11'b11001010110; code<=4'b0101; high<=1'b1; end
4'b1101: begin tone<=11'b11010000100; code<=4'b0110; high<=1'b1; end
4'b1111: begin tone<=11'b11011000000; code<=4'b0001; high<=1'b1; end
default: begin tone<=11'bx; code<=4'bx; high<=1'bx; end endcase
end
endmodule
数控分频模块的设计:
音符的频率由数控分频模块获得,这是一个数控分频电路。
它是由一个初值可变的加法计数器构成。
该计数器的模为2047,当计数器记满时,计数器产生一个溢出信号FULL,此溢出信号就是用作发音的频率信号。
在计数器的输入端给定不同的初值,就可得到不同音符的发音频率信号。
计数初值(Tone)=2047-分频系数而分频系数又可有下式来求:分频系数=基准频率/音符的发生频率低音时Tone值小,分频系数大,溢出信号周期长,扬声器发出的声音低,Tone随音乐的乐谱变化大,自动控制分频比,实现了数控分频,发生信号的频率与音调Tone成正比。
这就是利用数控分频器自动演奏音乐的原理。
其时钟(Clk)端输入的是在十六进制模块里对12MHz的信号进行16分频得到的750KHz,750KHz的信号根据分频预置数模块中所提
供的计数初值,分别得出相应音符频率的两倍值。
此时从数控分频器中出来的输出信号是脉宽极窄的脉冲式信号,为了有利于驱动扬声器,需另加一个D触发器以均衡其占空比,这时的频率就变为原来的1/2,刚好就是相应音符的频率。
数控分频模块中对Clk输入信号的分频比由11位预置数tone[10..0]决定。
输出频率将决定每一个音符的音调,这样,分频计数器的预置值tone[10..0]与输出频率就有了对应关系。
例如在分频预置数模块中若取tone[10..0]=1036,将发出音符为“3”音的信号频率。
程序如下:
module speakera(clk1,tone,spks);
input clk1;
input [10:0]tone;
output spks;
reg spks;
reg preclk;
reg fullspks;
reg [3:0]count4;
reg [10:0]count11;
always @ (posedge clk1)
begin
if(count4==4'b1000) begin preclk=1'b1; count4=4'b0000; end else begin count4=count4+1; preclk=1'b0; end
end
always @ (posedge preclk)
begin
if (count11==11'b11111111111) begin count11=tone; fullspks=1'b1; end
else begin count11=count11+1;fullspks=1'b0; end
end
always @ (posedge fullspks)
begin
spks=~spks;
end
endmodule
(3)各个子单元之间的接口关系
如下图所示:
(4)该设计与其它设计的接口方式等
实验选用模式1。
C L O C K 9C L O C K 5C L O C K 2
C L O C K 0
SPEAKER 扬声器
NO.1
PIO11-PIO8PIO15-PIO12PIO48
PIO49D15
D16HEX
HEX
PIO32
PIO33
PIO34
PIO35
PIO36
PIO37
PIO38
PIO39
D1D2D3D4D5D6D7D8实验电路结构图
译码器
译码器
译码器
译码器
FPGA/CPLD 目标芯片1
2
3
4
5
6
7
8
PIO3-PIO0
PIO7-PIO4HEX
HEX
键1
键2键3键4键5键6键7键8PIO39-PIO32PIO31-PIO28
PIO27-PIO24PIO23-PIO20PIO19-PIO16
使CLK1与clock9相接,接受12MHz 时钟频率(用短路帽在clock9接“12MHz ”);CLK 与clock2相接,接受4Hz 频率;发音输出SPKOUT 接Speaker ;与演奏发音相对应的简谱码输出显示可由CODE1在数码管5显示;HIGH1为高八度音指示,可由发光管D5指示
然后根据实验手册上 的GW48CK 系统万能接插口与结构图信号/与芯片引脚对照表来分配该设计与其它设计的接口名称。
如下图所示:
仿真综合部分
(1)关键节点的位置、作用及其测试波形的描述
Tone:分频计数器的预置值,数控分频模块中对clk1高频输入信号的分频比就是由11位预置数tone[10..0]决定的
Q:地址发生器模块(包括LPM-ROM块)的输出,将和持续时间共同决定index[3..0]输入的值,共13个,然后这13个值会确定下一个数控分频模块的分频预置数
Cnt:计数器的输出,随着计数器按4Hz的时钟频率作加法计数,即随地址递增时,将从LPM-ROM块中的mif音符数据中连续取出音符输向分频预置数。
(2) I/O引脚的名称、作用及其测试波形的描述;
此为input管脚:
Clk1:接受12MHz时钟频率,控制着数控分频器的节奏,测试波形频率太高已经密集成一条黑条
Clk:接受4HZ时钟频率,控制着计数器的节奏,测试波形周期即0.25秒
此为output管脚:
由于时序仿真时 受12位预置数及普通计算机性能的限制 仿真时间极长 数值仅做参考 实际结果请参考本程序的硬件仿真结果。
Code:演奏发音相对应的简谱码
High:高八度音指示
Spks:发音输出即不同预置数情况下数控分频的不同结果
(3)采用的FPGA器件的型号
(4)片内各种资源的使用情况时序仿真前的资源的使用情况:
时序仿真后的资源的使用情况:
4 结论
最后向目标芯片下载适配后的SOF逻辑设计文件,蜂鸣器即发出声音,演奏出“梁祝”乐曲。
本文介绍了基于FPGA的音乐硬件演奏电路的设计,实现了一个乐曲播放器,而且描述了其工作原理、设计思路及实现方法,并在用目标芯片仿真实现了音乐硬件演奏电路的功能。
这种基于FPGA的音乐硬件演奏电路的设计与实现,不仅通过VHDL 层次化和模块化设计方法,同时采用数控分频和定制LPM-ROM的设计思想通过本次实验,让我进一步了解了数控分频器的工作原理和功能作用,并学会了利用LPM模块制作ROM文件的方法,也更深一层地懂得了顶层文件通过例化语句与其他模块结合的好处我想我对EDA的学习只能算是个入门,这个领域的发展空间非常大,应用范围也非常广泛,而且我相信在将来还会有更加广阔的应用前景。
因此在以后的学习过程中,我不能因为课程学习的结束而结束了我对这个方面的学习甚至这个领域的探索,相反我会更加努力的去学习它。
感谢蒋俊华老师兢兢业业的教导,让我不仅学到了知识,也学到了做人做事的一些道理,为我提供了很多帮助。
在接下来的学习中,我会继续努力,
努力扎实地学习专业知识,为以后打好铺垫,奠定基础。
5 附录(程序代码)
module cnt138t(clk,cnt);//计数器模块代码
input clk;
output [7:0]cnt;
reg [7:0]cnt;
always @ (posedge clk)
begin
if(cnt==8'b10001010) cnt<=8'b00000000;
else cnt<=cnt+1;
end
endmodule
module tonetaba(index,code,high,tone);//译码模块的代码input [3:0]index;
output [3:0]code;
output [10:0]tone;
output high;
reg [3:0]code;
reg [10:0]tone;
reg high;
always @ (index)
begin
case(index)
4'b0000: begin tone<=11'b11111111111; code<=4'b0000; high<=1'b0; end
4'b0001: begin tone<=11'b01100000101; code<=4'b0001; high<=1'b0; end
4'b0010: begin tone<=11'b01110010000; code<=4'b0010; high<=1'b0; end
4'b0011: begin tone<=11'b10000001100; code<=4'b0011; high<=1'b0; end
4'b0101: begin tone<=11'b10010101101; code<=4'b0101; high<=1'b0; end
4'b0110: begin tone<=11'b10100001010; code<=4'b0110; high<=1'b0; end
4'b0111: begin tone<=11'b10101011100; code<=4'b0111; high<=1'b0; end
4'b1000: begin tone<=11'b10110000010; code<=4'b0001; high<=1'b1; end
4'b1001: begin tone<=11'b10111001000; code<=4'b0010; high<=1'b1; end
4'b1010: begin tone<=11'b11000000110; code<=4'b0011; high<=1'b1; end
4'b1100: begin tone<=11'b11001010110; code<=4'b0101; high<=1'b1; end
4'b1101: begin tone<=11'b11010000100; code<=4'b0110; high<=1'b1; end
4'b1111: begin tone<=11'b11011000000; code<=4'b0001; high<=1'b1; end
default: begin tone<=11'bx; code<=4'bx; high<=1'bx; end
endcase
end
endmodule
module speakera(clk1,tone,spks);//数控分频器的代码
input clk1;
input [10:0]tone;
output spks;
reg spks;
reg preclk;
reg fullspks;
reg [3:0]count4;
reg [10:0]count11;
always @ (posedge clk1)
begin
if(count4==4'b1000) begin preclk=1'b1; count4=4'b0000; end else begin count4=count4+1;preclk=1'b0; end
end
always @ (posedge preclk)
begin
if (count11==11'b00000100000) begin count11=tone; fullspks=1'b1; end
else begin count11=count11+1;fullspks=1'b0; end
end
always @ (posedge fullspks)
begin
spks=~spks;
end
Endmodule。