无源蜂鸣器 verilog FPGA 基础练习9

无源蜂鸣器 verilog FPGA 基础练习9

发现问题,用技术解决问题。兴趣是自己的源动力 !

前言

无源蜂鸣器的练习,就是对计数器和状态机练习的变种,学会用计数器和状态机的思想来设计。


一、无源蜂鸣器原理

无源蜂鸣器与有缘蜂鸣器不同,因其内部不带震荡源,所以其无法向有缘蜂鸣器那样直接用直流信号驱动,这里需要使用PWM方波才能驱动其发声。

如何发出不同的声音呢?上面说到需要使用PWM方波才能驱动其发声,所以这里我们只要控制输入的PWM方波,输入不同的PWM方波发出的声音就不一样了。而不同频率和占空比的方波发出的声音是不同的,其中频率对音调有影响,占空比对音量大小有影响。所以我们只需产生不同频率和占空比的PWM方波去驱动无源蜂鸣器就能让 无源蜂鸣器发出不同的音调了。

二、无源蜂鸣器设计方案

本次实验我们驱动无源蜂鸣器进行七个基本音调“哆来咪发梭拉西”的循环鸣叫,每个音阶持续鸣叫0.5s后鸣叫下一个音阶,本练习设计占空比为50%。
在这里插入图片描述在这里插入图片描述

需要注意的是,设计并不复杂,只需输出一个beep的输出即可。由要输出beep倒推需要设计什么电路

2.1 无源蜂鸣器代码

代码主要有几个组成(从倒推的逻辑):

  • 输出一个50%占空比的beep,需要一个判断50%占空比的计数器,和输出beep的always语句(这里是对分频和倍频的练习)
  • 因为要输出7种音调,所以要设计一个状态机来表示7种音调的频率,用于输出当前状态的beep(考察状态机的思想)
  • 因为每一种音调持续0.5s,所以设计0.5s计数器
  • 需要产生一个目前的发音状态,即0.5s个数计数

2.1.1 功能代码

module beep
#(
parameter TIME_500MS = 25'd24999999, //0.5s计数值
parameter DO = 18'd190839 , //"哆"音调分频计数值(频率262)
parameter RE = 18'd170067 , //"来"音调分频计数值(频率294)
parameter MI = 18'd151514 , //"咪"音调分频计数值(频率330)
parameter FA = 18'd143265 , //"发"音调分频计数值(频率349)
parameter SO = 18'd127550 , //"梭"音调分频计数值(频率392)
parameter LA = 18'd113635 , //"拉"音调分频计数值(频率440)
 parameter XI = 18'd101214 //"西"音调分频计数值(频率494)
 )
 (
 input wire sys_clk , //系统时钟,频率50MHz
 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 ; //音调分频计数值

 //wire define
 wire [16:0] duty_data ; //占空比计数值


// 0.5s计数
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0) 
		cnt <= 'b0; 
	else if( cnt == TIME_500MS )
		cnt <= 'b0;
	else	
		cnt <= cnt + 1'b1 ;
end
//0.5s个数计数,7个音节一循环
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0) 
		cnt_500ms <= 'b0; 
	else if( cnt_500ms == 'd6  & cnt == TIME_500MS ) // 这里就要考虑此时基本计数单位的问题了
		cnt_500ms <= 'b0;
	else if(cnt == TIME_500MS)
		cnt_500ms <= cnt_500ms + 1'b1 ;
end

// 设定一个case语句,用于状态转移
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0) 
		freq_data <= DO; 
	// 频率归零条件,一个是一个频率周期,另一个是下一个0.5s
	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
end
// 上面是设计实现当前输出的音调的状态(音调频率输出的状态)
// 下面是设计实现设定频率的计数器和50%占空比的输出,可以定义为输出层(功能)

// 设计一个频率计数器,用一个频率计数就可以了,7个音调共用一个计数器
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0) 
		freq_cnt <= 'b0; 
	// 频率归零条件,一个是一个频率周期,另一个是下一个0.5s
	else if( (freq_cnt == freq_data) ||  (cnt == TIME_500MS) )
		freq_cnt <= 'b0;
	else	
		freq_cnt <= freq_cnt + 1'b1 ;
end

assign duty_data = freq_data >> 1'b1 ;

// *占空比输出beep
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0) 
		beep <= 'b0; 
	else if( freq_cnt >= duty_data)
		beep <= 'b1;
	else	
		beep <= 'b0; 
end

endmodule

2.1.2 仿真代码

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


//\* Parameter and Internal Signal \//


//reg define
reg sys_clk ; //时钟
 reg sys_rst_n ; //复位

 
 //\* Main Code \//
 

 //对时钟,复位信号赋初值
 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'd24999), //0.5s计数值
 .DO (18'd190 ), //"哆"音调分频计数值(频率262)
 .RE (18'd170 ), //"来"音调分频计数值(频率294)
 .MI (18'd151 ), //"咪"音调分频计数值(频率330)
 .FA (18'd143 ), //"发"音调分频计数值(频率349)
 .SO (18'd127 ), //"梭"音调分频计数值(频率392)
 .LA (18'd113 ), //"拉"音调分频计数值(频率440)
 .XI (18'd101 ) //"西"音调分频计数值(频率494)
 )
 beep_inst
 (
 .sys_clk (sys_clk ), //系统时钟,频率50MHz
 .sys_rst_n (sys_rst_n ), //系统复位,低有效

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

 endmodule

2.1.3 仿真结果

在这里插入图片描述

总结

  • 核心思想:理清楚设计思路,从到推的角度来分层次设计和功能来设计
  • 欢迎一起交流学习,如有错误之处,还请各位指正。

参考资料

[1] FPGA系列教学

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值