用verilog 蜂鸣器的演奏乐曲

这首歌是吴金黛的森林狂想曲,喜欢可以去听听
在这里插入图片描述

module	song(clk,beep);	//模块名称song		
input	   clk;					//系统时钟50MHz	
output	beep;					//蜂鸣器输出端
reg		beep_r;				//寄存器
reg[7:0] state;				//乐谱状态机
reg[16:0]count,count_end;
reg[23:0]count1;
//乐谱参数:D=F/2K  (D:参数,F:时钟频率,K:音高频率)
parameter   L_3 = 17'd75850,  //低音3
            L_5 = 17'd63776,  //低音5
            L_6 = 17'd56818,	//低音6
				L_7 = 17'd50618,	//低音7
				M_1 = 17'd47774,	//中音1
				M_2 = 17'd42568,	//中音2
				M_3 = 17'd37919,	//中音3
				M_5 = 17'd31888,	//中音5
				M_6 = 17'd28409,	//中音6
				H_1 = 17'd23889;	//高音1			
parameter	TIME = 12000000;	//控制每一个音的长短(250ms)									
assign beep = beep_r;			//输出音乐
always@(posedge clk) begin
	count <= count + 1'b1;		//计数器加1
	if(count == count_end) begin	
		count <= 17'h0;			//计数器清零
		beep_r <= !beep_r;		//输出取反
	end
end

//曲谱 产生分频的系数并描述出曲谱
always @(posedge clk) begin
   if(count1 < TIME)             //一个节拍250mS
      count1 = count1 + 1'b1;
   else begin
      count1 = 24'd0;
      if(state == 8'd63)
         state = 8'd0;
      else
         state = state + 1'b1;
   case(state)
   8'd0:count_end = L_6;  
	8'd1:count_end=M_1;
	8'd2:count_end=M_3;
	8'D3:count_end=M_5;
	8'D4,8'D5:count_end=M_3;
	8'D6:count_end=M_3;
	8'D7:count_end=M_2;
   
	8'D8,8'D9:count_end=M_3;
	8'D10:count_end=M_3;
	8'D11:count_end=M_2;
	8'D12,8'D13:count_end=M_3;
	8'D14:count_end=L_6;
	8'D15:count_end=L_7;
	
	8'D16:count_end=M_1;
	8'D17:count_end=M_3;
	8'D18:count_end=M_2;
	8'D19:count_end=M_1;
	8'D20,8'D21:count_end=L_6;
	8'D22,8'D23:count_end=L_5;
	
	8'D24,8'D25,8'D26,8'D27,8'D28,8'D29,8'D30,8'D31:count_end=L_3;
	
	8'd32:count_end = L_6;  
	8'd33:count_end=M_1;
	8'd34:count_end=M_3;
	8'D35:count_end=M_5;
	8'D36,8'D37:count_end=M_3;
	8'D38:count_end=M_3;
	8'D39:count_end=M_2;
   
	8'D40,8'D41:count_end=M_3;
	8'D42:count_end=M_3;
	8'D43:count_end=M_2;
	8'D44,8'D45:count_end=M_3;
	8'D46:count_end=L_6;
	8'D47:count_end=L_7;
	
	8'D48:count_end=M_1;
	8'D49:count_end=M_3;
	8'D50:count_end=M_2;
	8'D51:count_end=M_1;
	8'D52,8'D53:count_end=L_6;
	8'D54,8'D55:count_end=L_5;
	
	8'D56,8'D57,8'D58,8'D59,8'D60,8'D61:count_end=L_6;
	8'D62:count_end=L_6;
	8'D63:count_end=L_7;
   default: count_end = 16'h0;
   endcase
   end
end
endmodule

  • 24
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
蜂鸣器演奏乐曲是一种常见的数字系统设计练习。本文将介绍如何使用Verilog语言设计一个能够演奏指定乐曲蜂鸣器控制系统。 1. 系统概述 本系统由蜂鸣器模块和控制模块组成,其中控制模块通过时钟信号控制蜂鸣器模块的输出,从而实现演奏指定乐曲的目的。 2. 系统设计 2.1 蜂鸣器模块 蜂鸣器模块的主要功能是输出指定频率的正弦波信号。根据正弦波的公式,我们可以得出如下的输出信号: ```verilog assign sin_out = sin_addr[11] ? ~sin_out_pre : sin_out_pre; assign sin_addr = sin_addr_pre + sin_step; ``` 其中,sin_out_pre表示上一个时钟周期的正弦波输出值,sin_addr_pre表示上一个时钟周期的正弦波地址,sin_step为每个时钟周期地址的增量。根据正弦波的性质,我们可以通过改变sin_step来改变输出频率。 2.2 控制模块 控制模块的主要功能是控制蜂鸣器模块的输出,从而实现演奏指定乐曲的目的。 在控制模块中,我们需要定义一个指定乐曲的时序脉冲信号。每个时序脉冲信号的周期代表一个音符的持续时间,而每个时序脉冲信号的高电平时间代表该音符的频率。 ```verilog always @(posedge clk or negedge rst) begin if(~rst) begin tone_step <= 12'b0; tone_addr <= 12'b0; tone_pulse <= 1'b0; end else begin if(tone_pulse) begin tone_addr <= tone_addr + tone_step; end if(count == 1) begin tone_pulse <= ~tone_pulse; if(tone_pulse) begin tone_step <= tone_data[tone_index][11:0]; tone_addr <= 12'b0; tone_index <= tone_index + 1; end end end end ``` 其中,tone_data表示指定乐曲的频率数据,每个元素代表一个音符的频率。tone_index表示当前演奏的音符序号,tone_step表示当前音符的地址增量,tone_addr表示当前正弦波的地址。count表示当前时序脉冲信号的计数器,当计数器为1时,需要切换到下一个音符。 3. 系统实现 在实现时,我们需要将蜂鸣器模块和控制模块集成起来。 ```verilog module buzzer( input clk, input rst, output reg sin_out ); reg [11:0] sin_addr_pre; // 正弦波地址 reg [11:0] sin_step; // 正弦波地址增量 reg sin_out_pre; // 上一个时钟周期的正弦波输出值 // 蜂鸣器模块 assign sin_out = sin_addr[11] ? ~sin_out_pre : sin_out_pre; assign sin_addr = sin_addr_pre + sin_step; always @(posedge clk or negedge rst) begin if(~rst) begin sin_addr_pre <= 12'b0; sin_step <= 12'b0; sin_out_pre <= 1'b0; end else begin sin_addr_pre <= sin_addr; sin_step <= 12'd10; sin_out_pre <= sin_out; end end endmodule module buzzer_controller( input clk, input rst, output reg [11:0] sin_addr, input [11:0] tone_data[7] ); reg [11:0] tone_step; // 音符地址增量 reg [11:0] tone_addr; // 音符地址 reg [2:0] count; // 时序脉冲信号计数器 reg [2:0] tone_index; // 当前演奏的音符序号 reg tone_pulse; // 时序脉冲信号 // 控制模块 always @(posedge clk or negedge rst) begin if(~rst) begin tone_step <= 12'b0; tone_addr <= 12'b0; tone_pulse <= 1'b0; count <= 3'd0; tone_index <= 3'd0; end else begin if(tone_pulse) begin tone_addr <= tone_addr + tone_step; end if(count == 3'd1) begin tone_pulse <= ~tone_pulse; if(tone_pulse) begin tone_step <= tone_data[tone_index][11:0]; tone_addr <= 12'b0; tone_index <= tone_index + 1; end end if(count == 3'd7) begin count <= 3'd0; end else begin count <= count + 1; end end end assign sin_addr = tone_pulse ? tone_addr : 12'b0; endmodule module buzzer_top( input clk, input rst, output reg sin_out ); wire [11:0] sin_addr; wire [11:0] tone_data[7] = { 12'd477, // C 12'd425, // D 12'd379, // E 12'd357, // F 12'd318, // G 12'd283, // A 12'd252 // B }; buzzer_controller controller(clk, rst, sin_addr, tone_data); buzzer buzzer(clk, rst, sin_out); endmodule ``` 在实现时,我们需要将蜂鸣器模块和控制模块实例化起来,并通过wire连接起来。tone_data数组中存储了指定乐曲的频率数据,通过修改该数组中的元素可以演奏不同的乐曲。 4. 总结 本文介绍了如何使用Verilog语言设计一个能够演奏指定乐曲蜂鸣器控制系统。该系统由蜂鸣器模块和控制模块组成,其中控制模块通过时序脉冲信号控制蜂鸣器模块的输出,从而实现演奏指定乐曲的目的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值