基于FPGA的蜂鸣器设计

描述

设计规划

驱动无源蜂鸣器进行七个基本音调“哆来咪发梭拉西”的循环鸣叫,每个音阶持续鸣叫0.5s后鸣叫下一个音阶。

对于无源蜂鸣器,输入不同的PWM方波就能发出不同的声音。方波的频率影响音调,占空比影响音量。音调频率对应表格如下,占空比保持为50%。因此这个实验我们只要循环产生占空比为50%的七个音调频率即可。

Do Re Mi Fa So La Si
262 294 330 349 392 440 494

现在我们考虑,除了时钟和复位,需要几个计数器:

1、蜂鸣维持0.5s,(50MHz对应20ns)计数从0-24999999,计数器名称cnt。

2、需要蜂鸣7个调,状态计数从0-6,cnt计满一次就+1,计数器名称cnt_500ms。

3、不同的调对应不同频率,需要一个频率计数器freq_cnt。

以Do为例,频率为262,周期为1/262=3.816794ms。时钟频率50MHz,对应周期是20ns,即计数个数为190840个,对应do的freq_cnt计数从0-190839。占空比为50%,即高电平和低电平的时长一样,高电平持续时钟脉冲个数为95420。

频率 262 294 330 349 392 440 494
频率数值 190840 170068 151515 143266 127551 113636 101214
占空比数值 95420 85034 75757 71633 63775 56818 50607

以Re为例的波形图:

FPGA

改变频率数值freq_data和占空比计数duty_data,就可以得到不同频率的波形。

编写代码

module beep
#(
parameter TIME_500MS = 25'd24999, //0.5s计数值
parameter DO = 18'd190 , //Do频率262
parameter RE = 18'd170 , //Re频率294
parameter MI = 18'd151 , //Mi频率330
parameter FA = 18'd143 , //Fa频率349
parameter SO = 18'd127 , //So频率392
parameter LA = 18'd113 , //La频率440
parameter XI = 18'd101 //Si频率494
 )
 (
 input wire sys_clk , 
 input wire sys_rst_n , 
 output reg beep 
 );


 //reg define
 reg [24:0] cnt ; //0.5s计数器
 reg [17:0] freq_cnt ; //音调计数器
 reg [2:0] cnt_500ms ; //0.5s个数计数
 reg [17:0] freq_data ; //音调分频计数值,取不同的DO,RE...可以得到不同频率的波形


 //wire define
 wire [16:0] duty_data ; //占空比计数值,即DO,RE...的一半


 assign duty_data = freq_data > > 1'b1;   //二进制右移一位就是原值的1/2


 //cnt:0.5s循环计数器
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt <= 25'd0;
 else if(cnt == TIME_500MS )
 cnt <= 25'd0;
 else
 cnt <= cnt + 1'b1;


 //cnt_500ms:对500ms个数进行计数,每个音阶鸣叫时间0.5s,7个音节一循环
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_500ms <= 3'd0;
 else if(cnt == TIME_500MS && cnt_500ms == 6)
 cnt_500ms <= 3'd0;
 else if(cnt == TIME_500MS)
 cnt_500ms <= cnt_500ms + 1'b1;


 //不同时间鸣叫不同的音阶
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 freq_data <= DO;
 else case(cnt_500ms)
 0: freq_data <= DO;
 1: freq_data <= RE;
 2: freq_data <= MI;
 3: freq_data <= FA;
 4: freq_data <= SO;
 5: freq_data <= LA;
 6: freq_data <= XI;
 default: freq_data <= DO;
 endcase


 //freq_cnt:当计数到音阶计数值或跳转到下一音阶时,开始重新计数
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 freq_cnt <= 18'd0;
 else if(freq_cnt == freq_data || cnt == TIME_500MS)
 freq_cnt <= 18'd0;
 else
 freq_cnt <= freq_cnt + 1'b1;


 //beep:输出蜂鸣器波形
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 beep <= 1'b0;
 else if(freq_cnt >= duty_data)
 beep <= 1'b1;
 else
 beep <= 1'b0;


 endmodule

定义参数:0.5s的计数值(用于cnt计数器的溢出值),七个频率的计数值(用于不同时间段的频率计数器freq_cnt的溢出值)

定义输入输出和中间变量

定义0.5s计数器:复位有效时拉低电平;溢出(计数到TIME_500MS即0.5s)时拉低电平,其他情况+1

定义0.5s个数计数器:由于音调要顺序循环出现,需要有个数计数器控制音调出现的时间。复位有效时拉低电平;溢出(0.5s计数器溢出且自身计数到溢出值6)时拉低电平,0.5s计数器溢出时+1

定义频率变量:我们使用一个频率变量,赋予不同的频率值。音调的顺序和频率的对应就是0.5s个数计数器和频率变量实现的当0.5s个数计数值为0时,对应Do音调,那么频率变量freq_data=DO。这里采用了case语句,注意需要有default语句

定义频率计数器:前面只定义了可音调顺序和频率的对应,现在需要把音调时间和音调频率对应。我们使用频率计数器,让音调数计满后到下一个音调。复位有效时拉低电平;溢出(频率计数器计数到freq_data或者0.5s计数器溢出)时拉低电平;其他情况+1

定义输出波形:复位有效时拉低电平;频率计数器为占空比数值(50%的占空比意味着高电平的持续时间是音调的周期的一半,数值也就是频率变量的一半),拉高电平,其他时候拉低电平。

FPGA

编写testbench

`timescale 1ns/1ns
module tb_beep();


//reg define
reg sys_clk ; 
reg sys_rst_n ; 


 //对时钟,复位信号赋初值
 initial
 begin
 sys_clk = 1'b1;
 sys_rst_n <= 1'b0;
 #100
 sys_rst_n <= 1'b1;
 end


 //产生时钟信号
 always #10 sys_clk = ~sys_clk;


//Instantiation 


 beep
 #(
 .TIME_500MS(25'd2499), //0.5s计数值
 .DO (18'd19 ), //"哆"音调分频计数值(频率262)
 .RE (18'd17 ), //"来"音调分频计数值(频率294)
 .MI (18'd15 ), //"咪"音调分频计数值(频率330)
 .FA (18'd14 ), //"发"音调分频计数值(频率349)
 .SO (18'd12 ), //"梭"音调分频计数值(频率392)
 .LA (18'd11 ), //"拉"音调分频计数值(频率440)
 .XI (18'd10 ) //"西"音调分频计数值(频率494)
 )
 beep_inst
 (
 .sys_clk (sys_clk ), //系统时钟,频率50MHz
 .sys_rst_n (sys_rst_n ), //系统复位,低有效


 .beep (beep ) //输出蜂鸣器控制信号
 );


 endmodule

初始化、产生时钟信号、实例化:为了节省时间参数值缩小了

对比波形

FPGA

由于节省时间将参数缩小了,DO音调的计数值是19,时钟是10ns的变化(周期20ns),因此BEEP在DO音调的周期是19201000ps=380000ps,且BEEP在RE周期是17201000ps=340000ps。图中的数值差异是标尺的误差。

分配管脚

FPGA

FPGA

全编译后上板验证

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分