内容介绍
内容介绍
一、项目背景
为了让高校电子/电气/电力等专业的同学们对FPGA的了解和熟练使用,将学习到的理论知识在实际的动手中深刻体会,也配合明年的全国大学生电子设计大赛,硬禾课堂和相关电子研究会联合开展了“2021寒假在家练活动”,并且设定了一些简单的规则,完成项目就能免费获得板卡,这让更多的同学们参与进来,让同学们学有成效。
二、项目要求
1.通过PWM产生不同的音调,并驱动板上蜂鸣器将音调输出
2.能够播放三首不同的曲子,每个曲子的时间长度为1分钟,可以切换播放
3.曲子的切换使用小脚丫核心板上的按键,需要有按键消抖的功能
4.播放的曲子的名字在OLED屏幕上显示出来(汉字显示)
三、项目实现
1.总体设计框图
2.模块详述
本项目包括顶层模块,蜂鸣器模块,OLED显示模块,计时模块。
a.顶层模块
顶层模块用于连接各个子模块。
module top( input clk_in, //系统时钟
input rst_n_in, //系统复位,低有效
input tone_en, //开关
input chose_up, //上一首
input chose_down, //下一首
input start_stop, //暂停和开始
output oled_csn, //OLCD液晶屏使能
output oled_rst, //OLCD液晶屏复位
output oled_dcn, //OLCD数据指令控制
output oled_clk, //OLCD时钟信号
output oled_dat, //OLCD数据信号
output piano_out //蜂鸣器控制输出
);
wire up,down;
wire[2:0] flag;
wire ss;
wire [127:0] time_1;
wire [127:0] time_2;
debounce U1 (.clk(clk_in),
.rst(rst_n_in),
.key(chose_up),
.key_pulse(up));
debounce U2(.clk(clk_in),
.rst(rst_n_in),
.key(start_stop),
.key_pulse(ss));
debounce U3(.clk(clk_in),
.rst(rst_n_in),
.key(chose_down),
.key_pulse(down));
timer U4(
.clk(clk_in),
.flag(flag),
.rst(rst_n_in),
.tone_en(tone_en),
.start_stop(ss),
.out_1(time_1),
.out_2(time_2));
Beeper U5(.clk_in(clk_in),
.rst_n_in(rst_n_in),
.tone_en(tone_en),
.chose_up(up),
.chose_down(down),
.start_stop(ss),
.flag(flag),
.piano_out(piano_out)
);
OLED12832 U6(.clk(clk_in),
.rst_n(rst_n_in),
.flag(flag),
.tone_en(tone_en),
.time_1(time_1),
.time_2(time_2),
.oled_csn(oled_csn),
.oled_rst(oled_rst),
.oled_dcn(oled_dcn),
.oled_clk(oled_clk),
.oled_dat(oled_dat)
);
endmodule
b.蜂鸣器模块
该模块用于驱动蜂鸣器播放乐曲,并使用标志位flag控制OLED模块的汉字显示,和计时模块的计时情况,本模块代码是基于电子森林的案例进行修改的
module Beeper
(
input clk_in, //系统时钟
input rst_n_in, //系统复位,低有效
input tone_en, //蜂鸣器使能信号
input chose_up, //上一首
input chose_down, //下一首
input start_stop, //暂停和开始
output reg [2:0] flag, //确定当前播放歌曲
output reg piano_out //蜂鸣器控制输出
);
reg [4:0] note [553:0];//音符表
reg [4:0] beat [553:0];//节拍表,音符表和节拍表一一对应
reg [4:0] tone; //蜂鸣器音节控制
reg [4:0] tcon; //蜂鸣器节拍控制
reg [9:0] num; //用于控制节拍和音频
reg s_s; //暂停开始标志位
/*
无源蜂鸣器可以发出不同的音节,与蜂鸣器震动的频率(等于蜂鸣器控制信号的频率)相关,
为了让蜂鸣器控制信号产生不同的频率,我们使用计数器计数(分频)实现,不同的音节控制对应不同的计数终值(分频系数)
计数器根据计数终值计数并分频,产生蜂鸣器控制信号
*/
reg [15:0] time_end;//用于控制频率
reg [27:0] time_delay;//用于控制时间
reg [25:0] cnt_delay;
reg [17:0] time_cnt;
//根据不同的音节控制,选择对应的计数终值(分频系数)
//低音1的频率为261.6Hz,蜂鸣器控制信号周期应为12MHz/261.6Hz = 45871.5,
//因为本设计中蜂鸣器控制信号是按计数器周期翻转的,所以几种终值 = 45871.5/2 = 22936
//需要计数22936个,计数范围为0 ~ (22936-1),所以time_end = 22935
always@(tone) begin
case(tone)
5'd1: time_end = 16'd22935; //L1,
5'd2: time_end = 16'd20428; //L2,
5'd3: time_end = 16'd18203; //L3,
5'd4: time_end = 16'd17181; //L4,
5'd5: time_end = 16'd15305; //L5,
5'd6: time_end = 16'd13635; //L6,
5'd7: time_end = 16'd12147; //L7,
5'd8: time_end = 16'd11464; //M1,
5'd9: time_end = 16'd10215; //M2,
5'd10: time_end = 16'd9100; //M3,
5'd11: time_end = 16'd8589; //M4,
5'd12: time_end = 16'd7652; //M5,
5'd13: time_end = 16'd6817; //M6,
5'd14: time_end = 16'd6073; //M7,
5'd15: time_end = 16'd5740; //H1,
5'd16: time_end = 16'd5107; //H2,
5'd17: time_end = 16'd4549; //H3,
5'd18: time_end = 16'd4294; //H4,
5'd19: time_end = 16'd3825; //H5,
5'd20: time_end = 16'd3408; //H6,
5'd21: time_end = 16'd3036; //H7,
default:time_end = 16'd65535;
endcase
end
always@(tcon or flag) begin
if(flag == 3'd1) begin
case(tcon)//奇迹再现,一小节四排,拍速为160拍/分钟
5'd 1: time_delay = 28'd1125000;//四分之一拍
5'd 2: time_delay = 28'd2250000;//半拍
5'd 3: time_delay = 28'd3375000;//四分之三拍
5'd 4: time_delay = 28'd4500000;//一拍
5'd 6: time_delay = 28'd6750000;//一拍半
5'd 8: time_delay = 28'd9000000;//两拍
5'd12: time_delay = 28'd1200000;//三拍
5'd16: time_delay = 28'd18000000;//四拍
5'd24: time_delay = 28'd24000000;//八拍
default:time_delay = 28'd0;
endcase
end
else if(flag == 3'd2) begin
case(tcon)//相思,一小节三拍,拍速为100拍/分钟
5'd 1: time_delay = 28'd1800000;//四分之一拍
5'd 2: time_delay = 28'd3600000;//半拍
5'd 3: time_delay = 28'd5400000;//四分之三拍
5'd 4: time_delay = 28'd7200000;//一拍
5'd 6: time_delay = 28'd10800000;//一拍半
5'd 8: time_delay = 28'd14400000;//两拍
5'd12: time_delay = 28'd21600000;//三拍
5'd16: time_delay = 28'd28800000;//四拍
5'd24: time_delay = 28'd57600000;//八拍
default:time_delay = 28'd0;
endcase
end
else if(flag == 3'd3) begin
case(tcon)//大鱼,一小节四拍,拍速为80拍/分钟
5'd 1: time_delay = 28'd2250000;//四分之一拍
5'd 2: time_delay = 28'd4500000;//半拍
5'd 3: time_delay = 28'd6750000;//四分之三拍
5'd 4: time_delay = 28'd9000000;//一拍
5'd 6: time_delay = 28'd13500000;//一拍半
5'd 8: time_delay = 28'd18000000;//两拍
5'd12: time_delay = 28'd27000000;//三拍
5'd16: time_delay = 28'd36000000;//四拍
5'd24: time_delay = 28'd72000000;//八拍
default:time_delay = 28'd0;
endcase
end
end
//当蜂鸣器使能时,计数器按照计数终值(分频系数)计数
always@(posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
time_cnt <= 1'b0;
end else if(!tone_en) begin
time_cnt <= 1'b0;
end else if(!s_s) begin
time_cnt <= 1'b0;
end else if(time_cnt>=time_end) begin
time_cnt <= 1'b0;
end else begin
time_cnt <= time_cnt + 1'b1;
end
end
//根据计数器的周期,翻转蜂鸣器控制信号
always@(posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
piano_out <= 1'b0;
end else if(tone==5'd0) begin
piano_out <= 1'b0;
end else if(time_cnt==time_end) begin
piano_out <= ~piano_out; //蜂鸣器控制输出翻转,两次翻转为1Hz
end else begin
piano_out <= piano_out;
end
end
always@(posedge clk_in or negedge rst_n_in) begin//音符和节拍控制
if(!rst_n_in) begin
tone <= 1'b0;
tcon <= 1'b0;
end else if(!tone_en) begin
tone <= tone;
tcon <= tcon;
end else begin
tone <= note[num];
tcon <= beat[num];
end
end
always@(posedge clk_in or negedge rst_n_in) begin//用标志位控制暂停和开始
if(!rst_n_in) begin
s_s <= 1'b0; end
else if(start_stop) begin
s_s <= ~s_s;end
else
begin s_s <= s_s; end
end
always@(posedge clk_in or negedge rst_n_in) begin //时间控制,上一首或者下一首切换歌曲(手动或者自动)
if(!rst_n_in) begin
cnt_delay <= 1'b0; num <= 1'b0; flag <= 3'd1; end
else if(!tone_en) begin
cnt_delay <= cnt_delay; end
else if(chose_up) begin
case(flag)
3'd1: begin flag <= 3'd3;num <= 10'd435; end
3'd2: begin flag <= 3'd1;num <= 1'b0; end
3'd3: begin flag <= 3'd2;num <= 10'd215; end
default:begin flag <= 3'd1;num <= 1'b0; end
endcase
end
else if(chose_down) begin//按键消抖后会输出一个相反的脉冲,不用!chose_up,下面chose_down同理
case(flag)
3'd1: begin flag <= 3'd2;num <= 10'd215; end
3'd2: begin flag <= 3'd3;num <= 10'd435; end
3'd3: begin flag <= 3'd1;num <= 1'b0; end
default:begin flag <= 3'd1;num <= 1'b0; end
endcase
end
else if(!s_s) begin
cnt_delay <= cnt_delay; end
else if(cnt_delay >= time_delay) begin
cnt_delay <= 1'b0;
case(num)
10'd 0: begin flag <= 3'd1;num <= num+1'b1; end
10'd215: begin flag <= 3'd2;num <= num+1'b1; end
10'd435: begin flag <= 3'd3;num <= num+1'b1; end
10'd553: begin flag <= 3'd1;num <= 1'b0; end
default: begin num <= num+1'b1; end
endcase
end
else begin cnt_delay <= cnt_delay + 1'b1; end
end
always@(posedge rst_n_in) begin//音符表
//奇迹再现
note[ 0] = {5'd 0};
note[ 1] = {5'd 6};
note[ 2] = {5'd 6};
//第一小节
note[ 3] = {5'd 6};
note[ 4] = {5'd 8};
note[ 5] = {5'd13};
note[ 6] = {5'd12};
note[ 7] = {5'd12};
note[ 8] = {5'd11};
note[ 9] = {5'd 0};
//第二小节
note[ 10] = {5'd10};
note[ 11] = {5'd11};
note[ 12] = {5'd10};
note[ 13] = {5'd10};
note[ 14] = {5'd 9};
note[ 15] = {5'd 8};
note[ 16] = {5'd 9};
//第三小节
note[ 17] = {5'd 6};
note[ 18] = {5'd 8};
note[ 19] = {5'd13};
note[ 20] = {5'd12};
note[ 21] = {5'd12};
note[ 22] = {5'd11};
note[ 23] = {5'd 0};
//第四小节
note[ 24] = {5'd10};
note[ 25] = {5'd11};
note[ 26] = {5'd10};
note[ 27] = {5'd 9};
note[ 28] = {5'd 9};
note[ 29] = {5'd 6};
//第五小节
note[ 30] = {5'd 6};
note[ 31] = {5'd 8};
note[ 32] = {5'd13};
note[ 33] = {5'd12};
note[ 34] = {5'd12};
note[ 35] = {5'd11};
note[ 36] = {5'd 0};
note[ 37] = {5'd10};
//第六小节
note[ 38] = {5'd10};
note[ 39] = {5'd11};
note[ 40] = {5'd10};
note[ 41] = {5'd10};
note[ 42] = {5'd 9};
note[ 43] = {5'd 8};
note[ 44] = {5'd 9};
//第七小节
note[ 45] = {5'd 6};
note[ 46] = {5'd 8};
note[ 47] = {5'd13};
note[ 48] = {5'd12};
note[ 49] = {5'd12};
note[ 50] = {5'd11};
note[ 51] = {5'd 0};
//第八小节
note[ 52] = {5'd10};
note[ 53] = {5'd11};
note[ 54] = {5'd11};
note[ 55] = {5'd13};
note[ 56] = {5'd13};
note[ 57] = {5'd13};
note[ 58] = {5'd13};
note[ 59] = {5'd13};
//第九小节
note[ 60] = {5'd 0};
note[ 61] = {5'd 8};
note[ 62] = {5'd 6};
note[ 63] = {5'd 7};
note[ 64] = {5'd 8};
note[ 65] = {5'd 0};
//第十小节
note[ 66] = {5'd 9};
note[ 67] = {5'd 8};
note[ 68] = {5'd 7};
note[ 69] = {5'd 7};
note[ 70] = {5'd 8};
//十一小节
note[ 71] = {5'd 0};
note[ 72] = {5'd 8};
note[ 73] = {5'd 6};
note[ 74] = {5'd 7};
note[ 75] = {5'd 8};
note[ 76] = {5'd 0};
//十二小节
note[ 77] = {5'd10};
note[ 78] = {5'd 9};
note[ 79] = {5'd 9};
note[ 80] = {5'd 9};
note[ 81] = {5'd10};
//十三小节
note[ 82] = {5'd 0};
note[ 83] = {5'd 8};
note[ 84] = {5'd 5};
note[ 85] = {5'd 7};
note[ 86] = {5'd 8};
note[ 87] = {5'd 0};
//十四小节
note[ 88] = {5'd10};
note[ 89] = {5'd 8};
note[ 90] = {5'd 8};
note[ 91] = {5'd 8};
note[ 92] = {5'd 9};
note[ 93] = {5'd 7};
//十五小节
note[ 94] = {5'd 7};
//十六小节
note[ 95] = {5'd21};
note[ 96] = {5'd19};
note[ 97] = {5'd16};
note[ 98] = {5'd15};
note[ 99] = {5'd15};
//十七小节
note[100] = {5'd 0};
note[101] = {5'd 8};
note[102] = {5'd 6};
note[103] = {5'd 7};
note[104] = {5'd 8};
note[105] = {5'd 0};
//十八小节
note[106] = {5'd 9};
note[107] = {5'd 8};
note[108] = {5'd 7};
note[109] = {5'd 7};
note[110] = {5'd 8};
//十九小节
note[111] = {5'd 0};
note[112] = {5'd 8};
note[113] = {5'd 6};
note[114] = {5'd 7};
note[115] = {5'd 8};
note[116] = {5'd 0};
//二十小节
note[117] = {5'd10};
note[118] = {5'd 9};
note[119] = {5'd 9};
note[120] = {5'd 9};
note[121] = {5'd10};
//二十一小节
note[122] = {5'd 0};
note[123] = {5'd 9};
note[124] = {5'd 5};
note[125] = {5'd 7};
note[126] = {5'd 8};
note[127] = {5'd 0};
//二十二小节
note[128] = {5'd10};
note[129] = {5'd 8};
note[130] = {5'd 8};
note[131] = {5'd 8};
note[132] = {5'd 9};
note[133] = {5'd 7};
//二十三小节
note[134] = {5'd 7};
note[135] = {5'd12};
note[136] = {5'd 9};
note[137] = {5'd13};
note[138] = {5'd 9};
note[139] = {5'd17};
//二十四小节
note[140] = {5'd17};
note[141] = {5'd10};
note[142] = {5'd11};
//二十五小节
note[143] = {5'd 8};
note[144] = {5'd 8};
note[145] = {5'd 8};
note[146] = {5'd10};
note[147] = {5'd10};
//二十六小节
note[148] = {5'd10};
note[149] = {5'd 9};
note[150] = {5'd 0};
note[151] = {5'd 5};
note[152] = {5'd 5};
//二十七小节
note[153] = {5'd10};
note[154] = {5'd10};
note[155] = {5'd10};
note[156] = {5'd 9};
note[157] = {5'd 9};
//二十八小节
note[158] = {5'd 9};
note[159] = {5'd 8};
note[160] = {5'd 8};
note[161] = {5'd 7};
note[162] = {5'd 6};
//二十九小节
note[163] = {5'd 6};
note[164] = {5'd 8};
note[165] = {5'd 8};
note[166] = {5'd 7};
note[167] = {5'd 5};
//三十小节
note[168] = {5'd 5};
note[169] = {5'd 8};
note[170] = {5'd 0};
note[171] = {5'd 8};
note[172] = {5'd 8};
//三十一小节
note[173] = {5'd 9};
note[174] = {5'd 6};
note[175] = {5'd 7};
note[176] = {5'd 8};
note[177] = {5'd 7};
//三十二小节
note[178] = {5'd 7};
//三十三小节
note[179] = {5'd 8};
note[180] = {5'd 8};
note[181] = {5'd 8};
note[182] = {5'd10};
note[183] = {5'd10};
//三十四小节
note[184] = {5'd10};
note[185] = {5'd 9};
note[186] = {5'd 0};
note[187] = {5'd 5};
note[188] = {5'd 5};
//三十五小节
note[189] = {5'd10};
note[190] = {5'd10};
note[191] = {5'd10};
note[192] = {5'd 9};
note[193] = {5'd 9};
//三十六小节
note[194] = {5'd 9};
note[195] = {5'd 8};
note[196] = {5'd 8};
note[197] = {5'd 7};
note[198] = {5'd 6};
//三十七小节
note[199] = {5'd 6};
note[200] = {5'd 8};
note[201] = {5'd 8};
note[202] = {5'd 7};
note[203] = {5'd 5};
//三十八小节
note[204] = {5'd 5};
note[205] = {5'd 8};
note[206] = {5'd 0};
note[207] = {5'd 8};
note[208] = {5'd 8};
//三十九小节
note[209] = {5'd 8};
note[210] = {5'd 6};
note[211] = {5'd 7};
note[212] = {5'd 8};
note[213] = {5'd 7};
//四十小节
note[214] = {5'd 7};
//相思
//第一小节
note[215] = {5'd13};
note[216] = {5'd10};
note[217] = {5'd13};
note[218] = {5'd14};
note[219] = {5'd15};
//第二小节
note[220] = {5'd16};
note[221] = {5'd15};
note[222] = {5'd14};
//第三小节
note[223] = {5'd13};
note[224] = {5'd12};
//第四小节
note[225] = {5'd10};
note[226] = {5'd12};
//第五小节
note[227] = {5'd13};
note[228] = {5'd10};
note[229] = {5'd13};
note[230] = {5'd14};
note[231] = {5'd15};
//第六小节
note[232] = {5'd16};
note[233] = {5'd15};
note[234] = {5'd14};
//第七小节
note[235] = {5'd13};
note[236] = {5'd12};
//第八小节
note[237] = {5'd13};
//第九小节
note[238] = {5'd 0};
note[239] = {5'd 0};
note[240] = {5'd 0};
//第十小节
note[241] = {5'd13};
note[242] = {5'd 9};
note[243] = {5'd 9};
note[244] = {5'd 8};
//十一小节
note[245] = {5'd10};
note[246] = {5'd 0};
note[247] = {5'd 8};
//十二小节
note[248] = {5'd 9};
note[249] = {5'd 9};
note[250] = {5'd 8};
note[251] = {5'd 9};
note[252] = {5'd10};
//十三小节
note[253] = {5'd10};
note[254] = {5'd 6};
note[255] = {5'd13};
//十四小节
note[256] = {5'd13};
note[257] = {5'd 9};
note[258] = {5'd 9};
note[259] = {5'd 8};
//十五小节
note[260] = {5'd10};
note[261] = {5'd 0};
note[262] = {5'd 8};
//十六小节
note[263] = {5'd 9};
note[264] = {5'd13};
note[265] = {5'd 9};
//十七小节
note[266] = {5'd 9};
note[267] = {5'd10};
//十八小节
note[268] = {5'd13};
note[269] = {5'd10};
note[270] = {5'd 9};
note[271] = {5'd 8};
//十九小节
note[272] = {5'd 9};
note[273] = {5'd 0};
//二十小节
note[274] = {5'd 8};
note[275] = {5'd 9};
note[276] = {5'd10};
//二十一小节
note[277] = {5'd10};
note[278] = {5'd 6};
note[279] = {5'd 6};
//二十二小节
note[280] = {5'd13};
note[281] = {5'd10};
note[282] = {5'd13};
//二十三小节
note[283] = {5'd14};
note[284] = {5'd10};
note[285] = {5'd14};
//二十四小节
note[286] = {5'd15};
note[287] = {5'd16};
//二十五小节
note[288] = {5'd14};
note[289] = {5'd14};
note[290] = {5'd14};
//二十六小节
note[291] = {5'd14};
//二十七小节
note[292] = {5'd10};
note[293] = {5'd13};
note[294] = {5'd13};
note[295] = {5'd10};
//二十八小节
note[296] = {5'd10};
note[297] = {5'd14};
note[298] = {5'd14};
note[299] = {5'd 0};
note[300] = {5'd10};
//二十九小节
note[301] = {5'd16};
note[302] = {5'd15};
note[303] = {5'd14};
note[304] = {5'd13};
note[305] = {5'd12};
note[306] = {5'd13};
//三十小节
note[307] = {5'd13};
note[308] = {5'd10};
note[309] = {5'd10};
note[310] = {5'd 0};
//三十一小节
note[311] = {5'd10};
note[312] = {5'd13};
note[313] = {5'd13};
note[314] = {5'd10};
//三十二小节
note[315] = {5'd14};
note[316] = {5'd13};
note[317] = {5'd 0};
note[318] = {5'd10};
//三十三小节
note[319] = {5'd 9};
note[320] = {5'd 8};
note[321] = {5'd 9};
//三十四小节
note[322] = {5'd10};
note[323] = {5'd 0};
//三十五小节
note[324] = {5'd10};
note[325] = {5'd13};
note[326] = {5'd13};
note[327] = {5'd10};
//三十六小节
note[328] = {5'd10};
note[329] = {5'd14};
note[330] = {5'd14};
note[331] = {5'd 0};
note[332] = {5'd10};
//三十七小节
note[333] = {5'd16};
note[334] = {5'd15};
note[335] = {5'd14};
note[336] = {5'd13};
note[337] = {5'd12};
note[338] = {5'd13};
//三十八小节
note[339] = {5'd13};
note[340] = {5'd10};
note[341] = {5'd10};
note[342] = {5'd 0};
//三十九小节
note[343] = {5'd10};
note[344] = {5'd13};
note[345] = {5'd13};
note[346] = {5'd10};
//四十小节
note[347] = {5'd17};
note[348] = {5'd16};
note[349] = {5'd17};
//四十一小节
note[350] = {5'd15};
note[351] = {5'd14};
//四十二小节
note[352] = {5'd13};
note[353] = {5'd13};
//四十三小节
note[354] = {5'd10};
note[355] = {5'd13};
note[356] = {5'd13};
note[357] = {5'd10};
//四十四小节
note[358] = {5'd10};
note[359] = {5'd14};
note[360] = {5'd14};
note[361] = {5'd 0};
note[362] = {5'd10};
//四十五小节
note[363] = {5'd16};
note[364] = {5'd15};
note[365] = {5'd14};
note[366] = {5'd13};
note[367] = {5'd12};
note[368] = {5'd13};
//四十六小节
note[369] = {5'd13};
note[370] = {5'd10};
note[371] = {5'd 0};
//四十七小节
note[372] = {5'd10};
note[373] = {5'd13};
note[374] = {5'd13};
note[375] = {5'd10};
//四十八小节
note[376] = {5'd14};
note[377] = {5'd13};
note[378] = {5'd 0};
note[379] = {5'd10};
//四十九小节
note[380] = {5'd 9};
note[381] = {5'd 8};
note[382] = {5'd 9};
//五十小节
note[383] = {5'd10};
note[384] = {5'd 0};
//五十一小节
note[385] = {5'd10};
note[386] = {5'd13};
note[387] = {5'd13};
note[388] = {5'd10};
//五十二小节
note[389] = {5'd10};
note[390] = {5'd14};
note[391] = {5'd14};
note[392] = {5'd 0};
note[393] = {5'd10};
//五十三小节
note[394] = {5'd16};
note[395] = {5'd15};
note[396] = {5'd14};
note[397] = {5'd13};
note[398] = {5'd12};
note[399] = {5'd12};
//五十四小节
note[400] = {5'd13};
note[401] = {5'd10};
note[402] = {5'd 0};
//五十五小节
note[403] = {5'd10};
note[404] = {5'd13};
note[405] = {5'd13};
note[406] = {5'd10};
//五十六小节
note[407] = {5'd17};
note[408] = {5'd16};
note[409] = {5'd17};
//五十七小节
note[410] = {5'd15};
note[411] = {5'd14};
//五十八小节
note[412] = {5'd13};
//五十九小节
note[413] = {5'd13};
//六十小节
note[414] = {5'd10};
note[415] = {5'd13};
note[416] = {5'd13};
note[417] = {5'd10};
//六十一小节
note[418] = {5'd17};
note[419] = {5'd16};
note[420] = {5'd17};
//六十二小节
note[421] = {5'd15};
//六十三小节
note[422] = {5'd14};
note[423] = {5'd13};
//六十四小节
note[424] = {5'd13};
note[425] = {5'd10};
note[426] = {5'd13};
note[427] = {5'd14};
note[428] = {5'd15};
//六十五小节
note[429] = {5'd16};
note[430] = {5'd15};
note[431] = {5'd14};
//六十六小节
note[432] = {5'd13};
note[433] = {5'd12};
//六十七小节
note[434] = {5'd13};
//大鱼
//第一小节
note[435] = {5'd 6};
note[436] = {5'd 8};
note[437] = {5'd 8};
note[438] = {5'd 9};
note[439] = {5'd 9};
note[440] = {5'd10};
note[441] = {5'd10};
note[442] = {5'd12};
note[443] = {5'd13};
//第二小节
note[444] = {5'd12};
note[445] = {5'd10};
note[446] = {5'd 9};
//第三小节
note[447] = {5'd 6};
note[448] = {5'd 8};
note[449] = {5'd 8};
note[450] = {5'd 9};
note[451] = {5'd 9};
note[452] = {5'd10};
note[453] = {5'd10};
//第四小节
note[454] = {5'd 6};
note[455] = {5'd 5};
//第五小节
note[456] = {5'd 6};
note[457] = {5'd 8};
note[458] = {5'd 8};
note[459] = {5'd 9};
note[460] = {5'd 9};
note[461] = {5'd10};
note[462] = {5'd10};
note[463] = {5'd12};
note[464] = {5'd13};
//第六小节
note[465] = {5'd12};
note[466] = {5'd10};
note[467] = {5'd 9};
//第七小节
note[468] = {5'd 9};
note[469] = {5'd10};
note[470] = {5'd 6};
note[471] = {5'd 9};
note[472] = {5'd10};
note[473] = {5'd 6};
note[474] = {5'd 5};
//第八小节
note[475] = {5'd 6};
note[476] = {5'd 6};
note[477] = {5'd 8};
//第九小节
note[478] = {5'd 9};
note[479] = {5'd 8};
note[480] = {5'd 6};
note[481] = {5'd 6};
note[482] = {5'd 8};
//第十小节
note[483] = {5'd 9};
note[484] = {5'd 8};
note[485] = {5'd10};
note[486] = {5'd10};
note[487] = {5'd12};
//十一小节
note[488] = {5'd13};
note[489] = {5'd13};
note[490] = {5'd12};
note[491] = {5'd10};
note[492] = {5'd 9};
note[493] = {5'd 8};
//十二小节
note[494] = {5'd 9};
note[495] = {5'd10};
note[496] = {5'd 6};
note[497] = {5'd 8};
//十三小节
note[498] = {5'd 9};
note[499] = {5'd 8};
note[500] = {5'd 6};
note[501] = {5'd 6};
note[502] = {5'd 8};
//十四小节
note[503] = {5'd 9};
note[504] = {5'd 8};
note[505] = {5'd10};
//十五小节
note[506] = {5'd 9};
note[507] = {5'd10};
note[508] = {5'd 6};
note[509] = {5'd 9};
note[510] = {5'd10};
note[511] = {5'd 6};
note[512] = {5'd 5};
//十六小节
note[513] = {5'd 6};
note[514] = {5'd10};
note[515] = {5'd12};
//十七小节
note[516] = {5'd15};
note[517] = {5'd14};
note[518] = {5'd10};
note[519] = {5'd10};
note[520] = {5'd 9};
//十八小节
note[521] = {5'd 8};
note[522] = {5'd 8};
note[523] = {5'd 9};
note[524] = {5'd10};
note[525] = {5'd10};
note[526] = {5'd 9};
//十九小节
note[527] = {5'd 8};
note[528] = {5'd13};
note[529] = {5'd15};
note[530] = {5'd14};
note[531] = {5'd13};
note[532] = {5'd12};
note[533] = {5'd 9};
//二十小节
note[534] = {5'd10};
note[535] = {5'd10};
note[536] = {5'd12};
//二十一小节
note[537] = {5'd15};
note[538] = {5'd14};
note[539] = {5'd10};
note[540] = {5'd10};
note[541] = {5'd 9};
//二十二小节
note[542] = {5'd 8};
note[543] = {5'd 8};
note[544] = {5'd 9};
note[545] = {5'd10};
//二十三小节
note[546] = {5'd 9};
note[547] = {5'd10};
note[548] = {5'd 6};
note[549] = {5'd 9};
note[550] = {5'd10};
note[551] = {5'd 6};
note[552] = {5'd 5};
//二十四小节
note[553] = {5'd 6};
end
always@(posedge rst_n_in) begin//节拍表
//奇迹再现
beat[ 0] = {5'd 2};
beat[ 1] = {5'd 2};
beat[ 2] = {5'd 4};
//第一小节
beat[ 3] = {5'd 2};
beat[ 4] = {5'd 2};
beat[ 5] = {5'd 2};
beat[ 6] = {5'd 2};
beat[ 7] = {5'd 2};
beat[ 8] = {5'd 2};
beat[ 9] = {5'd 4};
//第二小节
beat[ 10] = {5'd 4};
beat[ 11] = {5'd 2};
beat[ 12] = {5'd 2};
beat[ 13] = {5'd 2};
beat[ 14] = {5'd 2};
beat[ 15] = {5'd 2};
beat[ 16] = {5'd 2};
//第三小节
beat[ 17] = {5'd 2};
beat[ 18] = {5'd 2};
beat[ 19] = {5'd 2};
beat[ 20] = {5'd 2};
beat[ 21] = {5'd 2};
beat[ 22] = {5'd 2};
beat[ 23] = {5'd 4};
//第四小节
beat[ 24] = {5'd 2};
beat[ 25] = {5'd 2};
beat[ 26] = {5'd 2};
beat[ 27] = {5'd 2};
beat[ 28] = {5'd 6};
beat[ 29] = {5'd 2};
//第五小节
beat[ 30] = {5'd 2};
beat[ 31] = {5'd 2};
beat[ 32] = {5'd 2};
beat[ 33] = {5'd 2};
beat[ 34] = {5'd 2};
beat[ 35] = {5'd 2};
beat[ 36] = {5'd 2};
beat[ 37] = {5'd 2};
//第六小节
beat[ 38] = {5'd 4};
beat[ 39] = {5'd 2};
beat[ 40] = {5'd 2};
beat[ 41] = {5'd 2};
beat[ 42] = {5'd 2};
beat[ 43] = {5'd 2};
beat[ 44] = {5'd 2};
//第七小节
beat[ 45] = {5'd 2};
beat[ 46] = {5'd 2};
beat[ 47] = {5'd 2};
beat[ 48] = {5'd 2};
beat[ 49] = {5'd 2};
beat[ 50] = {5'd 2};
beat[ 51] = {5'd 4};
//第八小节
beat[ 52] = {5'd 2};
beat[ 53] = {5'd 2};
beat[ 54] = {5'd 2};
beat[ 55] = {5'd 2};
beat[ 56] = {5'd 2};
beat[ 57] = {5'd 2};
beat[ 58] = {5'd 1};
beat[ 59] = {5'd 3};
//第九小节
beat[ 60] = {5'd 4};
beat[ 61] = {5'd 2};
beat[ 62] = {5'd 2};
beat[ 63] = {5'd 2};
beat[ 64] = {5'd 2};
beat[ 65] = {5'd 4};
//第十小节
beat[ 66] = {5'd 4};
beat[ 67] = {5'd 2};
beat[ 68] = {5'd 2};
beat[ 69] = {5'd 2};
beat[ 70] = {5'd 6};
//十一小节
beat[ 71] = {5'd 4};
beat[ 72] = {5'd 2};
beat[ 73] = {5'd 2};
beat[ 74] = {5'd 2};
beat[ 75] = {5'd 2};
beat[ 76] = {5'd 4};
//十二小节
beat[ 77] = {5'd 4};
beat[ 78] = {5'd 2};
beat[ 79] = {5'd 2};
beat[ 80] = {5'd 2};
beat[ 81] = {5'd 6};
//十三小节
beat[ 82] = {5'd 4};
beat[ 83] = {5'd 2};
beat[ 84] = {5'd 2};
beat[ 85] = {5'd 2};
beat[ 86] = {5'd 2};
beat[ 87] = {5'd 4};
//十四小节
beat[ 88] = {5'd 4};
beat[ 89] = {5'd 2};
beat[ 90] = {5'd 2};
beat[ 91] = {5'd 2};
beat[ 92] = {5'd 4};
beat[ 93] = {5'd 2};
//十五小节
beat[ 94] = {5'd16};
//十六小节
beat[ 95] = {5'd 2};
beat[ 96] = {5'd 2};
beat[ 97] = {5'd 2};
beat[ 98] = {5'd 2};
beat[ 99] = {5'd 8};
//十七小节
beat[100] = {5'd 4};
beat[101] = {5'd 2};
beat[102] = {5'd 2};
beat[103] = {5'd 2};
beat[104] = {5'd 2};
beat[105] = {5'd 4};
//十八小节
beat[106] = {5'd 4};
beat[107] = {5'd 2};
beat[108] = {5'd 2};
beat[109] = {5'd 2};
beat[110] = {5'd 6};
//十九小节
beat[111] = {5'd 4};
beat[112] = {5'd 2};
beat[113] = {5'd 2};
beat[114] = {5'd 2};
beat[115] = {5'd 2};
beat[116] = {5'd 4};
//二十小节
beat[117] = {5'd 4};
beat[118] = {5'd 2};
beat[119] = {5'd 2};
beat[120] = {5'd 2};
beat[121] = {5'd 6};
//二十一小节
beat[122] = {5'd 4};
beat[123] = {5'd 2};
beat[124] = {5'd 2};
beat[125] = {5'd 2};
beat[126] = {5'd 2};
beat[127] = {5'd 4};
//二十二小节
beat[128] = {5'd 4};
beat[129] = {5'd 2};
beat[130] = {5'd 2};
beat[131] = {5'd 2};
beat[132] = {5'd 4};
beat[133] = {5'd 2};
//二十三小节
beat[134] = {5'd 4};
beat[135] = {5'd 2};
beat[136] = {5'd 2};
beat[137] = {5'd 2};
beat[138] = {5'd 4};
beat[139] = {5'd 2};
//二十四小节
beat[140] = {5'd12};
beat[141] = {5'd 2};
beat[142] = {5'd 2};
//二十五小节
beat[143] = {5'd 4};
beat[144] = {5'd 4};
beat[145] = {5'd 4};
beat[146] = {5'd 2};
beat[147] = {5'd 2};
//二十六小节
beat[148] = {5'd 2};
beat[149] = {5'd 6};
beat[150] = {5'd 4};
beat[151] = {5'd 2};
beat[152] = {5'd 2};
//二十七小节
beat[153] = {5'd 4};
beat[154] = {5'd 4};
beat[155] = {5'd 4};
beat[156] = {5'd 2};
beat[157] = {5'd 2};
//二十八小节
beat[158] = {5'd 2};
beat[159] = {5'd 6};
beat[160] = {5'd 4};
beat[161] = {5'd 2};
beat[162] = {5'd 2};
//二十九小节
beat[163] = {5'd 2};
beat[164] = {5'd 6};
beat[165] = {5'd 4};
beat[166] = {5'd 2};
beat[167] = {5'd 2};
//三十小节
beat[168] = {5'd 2};
beat[169] = {5'd 6};
beat[170] = {5'd 4};
beat[171] = {5'd 2};
beat[172] = {5'd 2};
//三十一小节
beat[173] = {5'd 4};
beat[174] = {5'd 4};
beat[175] = {5'd 2};
beat[176] = {5'd 4};
beat[177] = {5'd 2};
//三十二小节
beat[178] = {5'd16};
//三十三小节
beat[179] = {5'd 4};
beat[180] = {5'd 4};
beat[181] = {5'd 4};
beat[182] = {5'd 2};
beat[183] = {5'd 2};
//三十四小节
beat[184] = {5'd 2};
beat[185] = {5'd 6};
beat[186] = {5'd 4};
beat[187] = {5'd 2};
beat[188] = {5'd 2};
//三十五小节
beat[189] = {5'd 4};
beat[190] = {5'd 4};
beat[191] = {5'd 4};
beat[192] = {5'd 2};
beat[193] = {5'd 2};
//三十六小节
beat[194] = {5'd 2};
beat[195] = {5'd 6};
beat[196] = {5'd 4};
beat[197] = {5'd 2};
beat[198] = {5'd 2};
//三十七小节
beat[199] = {5'd 2};
beat[200] = {5'd 6};
beat[201] = {5'd 4};
beat[202] = {5'd 2};
beat[203] = {5'd 2};
//三十八小节
beat[204] = {5'd 2};
beat[205] = {5'd 6};
beat[206] = {5'd 4};
beat[207] = {5'd 2};
beat[208] = {5'd 2};
//三十九小节
beat[209] = {5'd 4};
beat[210] = {5'd 4};
beat[211] = {5'd 2};
beat[212] = {5'd 4};
beat[213] = {5'd 2};
//四十小节
beat[214] = {5'd24};
//相思
//第一小节
beat[215] = {5'd 2};
beat[216] = {5'd 2};
beat[217] = {5'd 2};
beat[218] = {5'd 2};
beat[219] = {5'd 4};
//第二小节
beat[220] = {5'd 4};
beat[221] = {5'd 4};
beat[222] = {5'd 4};
//第三小节
beat[223] = {5'd 8};
beat[224] = {5'd 4};
//第四小节
beat[225] = {5'd 8};
beat[226] = {5'd 4};
//第五小节
beat[227] = {5'd 2};
beat[228] = {5'd 2};
beat[229] = {5'd 2};
beat[230] = {5'd 2};
beat[231] = {5'd 4};
//第六小节
beat[232] = {5'd 4};
beat[233] = {5'd 4};
beat[234] = {5'd 4};
//第七小节
beat[235] = {5'd 8};
beat[236] = {5'd 4};
//第八小节
beat[237] = {5'd 12};
//第九小节
beat[238] = {5'd 4};
beat[239] = {5'd 4};
beat[240] = {5'd 4};
//第十小节
beat[241] = {5'd 4};
beat[242] = {5'd 4};
beat[243] = {5'd 2};
beat[244] = {5'd 2};
//十一小节
beat[245] = {5'd 8};
beat[246] = {5'd 2};
beat[247] = {5'd 2};
//十二小节
beat[248] = {5'd 4};
beat[249] = {5'd 2};
beat[250] = {5'd 2};
beat[251] = {5'd 2};
beat[252] = {5'd 2};
//十三小节
beat[253] = {5'd 2};
beat[254] = {5'd 2};
beat[255] = {5'd 8};
//十四小节
beat[256] = {5'd 4};
beat[257] = {5'd 4};
beat[258] = {5'd 2};
beat[259] = {5'd 2};
//十五小节
beat[260] = {5'd 8};
beat[261] = {5'd 2};
beat[262] = {5'd 2};
//十六小节
beat[263] = {5'd 4};
beat[264] = {5'd 6};
beat[265] = {5'd 2};
//十七小节
beat[266] = {5'd 4};
beat[267] = {5'd 8};
//十八小节
beat[268] = {5'd 4};
beat[269] = {5'd 4};
beat[270] = {5'd 2};
beat[271] = {5'd 2};
//十九小节
beat[272] = {5'd 8};
beat[273] = {5'd 4};
//二十小节
beat[274] = {5'd 4};
beat[275] = {5'd 6};
beat[276] = {5'd 2};
//二十一小节
beat[277] = {5'd 2};
beat[278] = {5'd 2};
beat[279] = {5'd 8};
//二十二小节
beat[280] = {5'd 4};
beat[281] = {5'd 4};
beat[282] = {5'd 4};
//二十三小节
beat[283] = {5'd 4};
beat[284] = {5'd 4};
beat[285] = {5'd 4};
//二十四小节
beat[286] = {5'd 4};
beat[287] = {5'd 8};
//二十五小节
beat[288] = {5'd 6};
beat[289] = {5'd 2};
beat[290] = {5'd 4};
//二十六小节
beat[291] = {5'd12};
//二十七小节
beat[292] = {5'd 2};
beat[293] = {5'd 2};
beat[294] = {5'd 6};
beat[295] = {5'd 2};
//二十八小节
beat[296] = {5'd 2};
beat[297] = {5'd 2};
beat[298] = {5'd 4};
beat[299] = {5'd 2};
beat[300] = {5'd 2};
//二十九小节
beat[301] = {5'd 2};
beat[302] = {5'd 2};
beat[303] = {5'd 2};
beat[304] = {5'd 2};
beat[305] = {5'd 2};
beat[306] = {5'd 2};
//三十小节
beat[307] = {5'd 2};
beat[308] = {5'd 2};
beat[309] = {5'd 4};
beat[310] = {5'd 4};
//三十一小节
beat[311] = {5'd 2};
beat[312] = {5'd 2};
beat[313] = {5'd 6};
beat[314] = {5'd 2};
//三十二小节
beat[315] = {5'd 4};
beat[316] = {5'd 4};
beat[317] = {5'd 2};
beat[318] = {5'd 2};
//三十三小节
beat[319] = {5'd 4};
beat[320] = {5'd 4};
beat[321] = {5'd 4};
//三十四小节
beat[322] = {5'd 8};
beat[323] = {5'd 4};
//三十五小节
beat[324] = {5'd 2};
beat[325] = {5'd 2};
beat[326] = {5'd 6};
beat[327] = {5'd 2};
//三十六小节
beat[328] = {5'd 2};
beat[329] = {5'd 2};
beat[330] = {5'd 4};
beat[331] = {5'd 2};
beat[332] = {5'd 2};
//三十七小节
beat[333] = {5'd 2};
beat[334] = {5'd 2};
beat[335] = {5'd 2};
beat[336] = {5'd 2};
beat[337] = {5'd 2};
beat[338] = {5'd 2};
//三十八小节
beat[339] = {5'd 2};
beat[340] = {5'd 2};
beat[341] = {5'd 4};
beat[342] = {5'd 4};
//三十九小节
beat[343] = {5'd 2};
beat[344] = {5'd 2};
beat[345] = {5'd 6};
beat[346] = {5'd 2};
//四十小节
beat[347] = {5'd 4};
beat[348] = {5'd 6};
beat[349] = {5'd 2};
//四十一小节
beat[350] = {5'd 8};
beat[351] = {5'd 4};
//四十二小节
beat[352] = {5'd12};
beat[353] = {5'd12};
//四十三小节
beat[354] = {5'd 2};
beat[355] = {5'd 2};
beat[356] = {5'd 6};
beat[357] = {5'd 2};
//四十四小节
beat[358] = {5'd 2};
beat[359] = {5'd 2};
beat[360] = {5'd 4};
beat[361] = {5'd 2};
beat[362] = {5'd 2};
//四十五小节
beat[363] = {5'd 2};
beat[364] = {5'd 2};
beat[365] = {5'd 2};
beat[366] = {5'd 2};
beat[367] = {5'd 2};
beat[368] = {5'd 2};
//四十六小节
beat[369] = {5'd 4};
beat[370] = {5'd 4};
beat[371] = {5'd 4};
//四十七小节
beat[372] = {5'd 2};
beat[373] = {5'd 2};
beat[374] = {5'd 6};
beat[375] = {5'd 2};
//四十八小节
beat[376] = {5'd 4};
beat[377] = {5'd 4};
beat[378] = {5'd 2};
beat[379] = {5'd 2};
//四十九小节
beat[380] = {5'd 4};
beat[381] = {5'd 4};
beat[382] = {5'd 4};
//五十小节
beat[383] = {5'd 8};
beat[384] = {5'd 4};
//五十一小节
beat[385] = {5'd 2};
beat[386] = {5'd 2};
beat[387] = {5'd 6};
beat[388] = {5'd 2};
//五十二小节
beat[389] = {5'd 2};
beat[390] = {5'd 2};
beat[391] = {5'd 4};
beat[392] = {5'd 2};
beat[393] = {5'd 2};
//五十三小节
beat[394] = {5'd 3};
beat[395] = {5'd 1};
beat[396] = {5'd 2};
beat[397] = {5'd 2};
beat[398] = {5'd 2};
beat[399] = {5'd 2};
//五十四小节
beat[400] = {5'd 4};
beat[401] = {5'd 4};
beat[402] = {5'd 4};
//五十五小节
beat[403] = {5'd 2};
beat[404] = {5'd 2};
beat[405] = {5'd 6};
beat[406] = {5'd 2};
//五十六小节
beat[407] = {5'd 4};
beat[408] = {5'd 6};
beat[409] = {5'd 2};
//五十七小节
beat[410] = {5'd 8};
beat[411] = {5'd 4};
//五十八小节
beat[412] = {5'd12};
//五十九小节
beat[413] = {5'd12};
//六十小节
beat[414] = {5'd 2};
beat[415] = {5'd 2};
beat[416] = {5'd 6};
beat[417] = {5'd 2};
//六十一小节
beat[418] = {5'd 4};
beat[419] = {5'd 6};
beat[420] = {5'd 2};
//六十二小节
beat[421] = {5'd12};
//六十三小节
beat[422] = {5'd 4};
beat[423] = {5'd 8};
//六十四小节
beat[424] = {5'd 2};
beat[425] = {5'd 2};
beat[426] = {5'd 2};
beat[427] = {5'd 2};
beat[428] = {5'd 4};
//六十五小节
beat[429] = {5'd 4};
beat[430] = {5'd 4};
beat[431] = {5'd 4};
//六十六小节
beat[432] = {5'd 8};
beat[433] = {5'd 4};
//六十七小节
beat[434] = {5'd12};
//大鱼
//第一小节
beat[435] = {5'd 2};
beat[436] = {5'd 2};
beat[437] = {5'd 2};
beat[438] = {5'd 2};
beat[439] = {5'd 2};
beat[440] = {5'd 2};
beat[441] = {5'd 2};
beat[442] = {5'd 1};
beat[443] = {5'd 1};
//第二小节
beat[444] = {5'd 6};
beat[445] = {5'd 2};
beat[446] = {5'd 8};
//第三小节
beat[447] = {5'd 2};
beat[448] = {5'd 2};
beat[449] = {5'd 2};
beat[450] = {5'd 2};
beat[451] = {5'd 2};
beat[452] = {5'd 2};
beat[453] = {5'd 4};
//第四小节
beat[454] = {5'd 4};
beat[455] = {5'd12};
//第五小节
beat[456] = {5'd 2};
beat[457] = {5'd 2};
beat[458] = {5'd 2};
beat[459] = {5'd 2};
beat[460] = {5'd 2};
beat[461] = {5'd 2};
beat[462] = {5'd 2};
beat[463] = {5'd 1};
beat[464] = {5'd 1};
//第六小节
beat[465] = {5'd 6};
beat[466] = {5'd 2};
beat[467] = {5'd 8};
//第七小节
beat[468] = {5'd 2};
beat[469] = {5'd 2};
beat[470] = {5'd 4};
beat[471] = {5'd 2};
beat[472] = {5'd 2};
beat[473] = {5'd 2};
beat[474] = {5'd 2};
//第八小节
beat[475] = {5'd12};
beat[476] = {5'd 2};
beat[477] = {5'd 2};
//第九小节
beat[478] = {5'd 6};
beat[479] = {5'd 2};
beat[480] = {5'd 4};
beat[481] = {5'd 2};
beat[482] = {5'd 2};
//第十小节
beat[483] = {5'd 6};
beat[484] = {5'd 2};
beat[485] = {5'd 4};
beat[486] = {5'd 2};
beat[487] = {5'd 2};
//十一小节
beat[488] = {5'd 4};
beat[489] = {5'd 2};
beat[490] = {5'd 2};
beat[491] = {5'd 2};
beat[492] = {5'd 2};
beat[493] = {5'd 4};
//十二小节
beat[494] = {5'd 4};
beat[495] = {5'd 8};
beat[496] = {5'd 2};
beat[497] = {5'd 2};
//十三小节
beat[498] = {5'd 6};
beat[499] = {5'd 2};
beat[500] = {5'd 4};
beat[501] = {5'd 2};
beat[502] = {5'd 2};
//十四小节
beat[503] = {5'd 4};
beat[504] = {5'd 4};
beat[505] = {5'd 8};
//十五小节
beat[506] = {5'd 2};
beat[507] = {5'd 2};
beat[508] = {5'd 4};
beat[509] = {5'd 2};
beat[510] = {5'd 2};
beat[511] = {5'd 2};
beat[512] = {5'd 2};
//十六小节
beat[513] = {5'd12};
beat[514] = {5'd 2};
beat[515] = {5'd 2};
//十七小节
beat[516] = {5'd 6};
beat[517] = {5'd 2};
beat[518] = {5'd 4};
beat[519] = {5'd 2};
beat[520] = {5'd 2};
//十八小节
beat[521] = {5'd 4};
beat[522] = {5'd 2};
beat[523] = {5'd 2};
beat[524] = {5'd 4};
beat[525] = {5'd 2};
beat[526] = {5'd 2};
//十九小节
beat[527] = {5'd 4};
beat[528] = {5'd 2};
beat[529] = {5'd 2};
beat[530] = {5'd 2};
beat[531] = {5'd 2};
beat[532] = {5'd 2};
beat[533] = {5'd 2};
//二十小节
beat[534] = {5'd12};
beat[535] = {5'd 4};
beat[536] = {5'd 4};
//二十一小节
beat[537] = {5'd 6};
beat[538] = {5'd 2};
beat[539] = {5'd 4};
beat[540] = {5'd 2};
beat[541] = {5'd 2};
//二十二小节
beat[542] = {5'd 4};
beat[543] = {5'd 2};
beat[544] = {5'd 2};
beat[545] = {5'd 8};
//二十三小节
beat[546] = {5'd 2};
beat[547] = {5'd 2};
beat[548] = {5'd 4};
beat[549] = {5'd 2};
beat[550] = {5'd 2};
beat[551] = {5'd 2};
beat[552] = {5'd 2};
//二十四小节
beat[553] = {5'd16};
end
endmodule
c.OLED驱动模块
本模块通过驱动SSD1306来控制OLED的显示。在OLED上会显示当前曲子的名字和当前曲子的剩余播放时间。本项目使用的OLED显示屏代码主要来自于电子森林的案例分享,对其进行了一定修改。
module OLED12832
(
input clk, //12MHz系统时钟
input rst_n, //系统复位,低有效
input [2:0] flag, //确定当前播放歌曲,通过Beeper块中的flag标志位控制同步切换
input tone_en, //OLED使能信号
input [127:0] time_1,
input [127:0] time_2,
output reg oled_csn, //OLCD液晶屏使能
output reg oled_rst, //OLCD液晶屏复位
output reg oled_dcn, //OLCD数据指令控制
output reg oled_clk, //OLCD时钟信号
output reg oled_dat //OLCD数据信号
);
localparam INIT_DEPTH = 16'd25; //LCD初始化的命令的数量
localparam IDLE = 6'h1, MAIN = 6'h2, INIT = 6'h4, SCAN = 6'h8, WRITE = 6'h10, DELAY = 6'h20;
localparam HIGH = 1'b1, LOW = 1'b0;
localparam DATA = 1'b1, CMD = 1'b0;
reg [7:0] cmd [24:0];
reg [63:0] mem [56:0];
reg [7:0] y_p, x_ph, x_pl;
reg [127:0] char;
reg [127:0] choice [3:0];
reg [7:0] num, char_reg;
reg [4:0] cnt_main, cnt_init, cnt_scan, cnt_write;
reg [15:0] num_delay, cnt_delay, cnt;
reg [5:0] state, state_back;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;
y_p <= 1'b0; x_ph <= 1'b0; x_pl <= 1'b0;
num <= 1'b0; char <= 1'b0; char_reg <= 1'b0;
num_delay <= 16'd5; cnt_delay <= 1'b0; cnt <= 1'b0;
oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
state <= IDLE; state_back <= IDLE;end
else begin
case(state)
IDLE:begin
cnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;
y_p <= 1'b0; x_ph <= 1'b0; x_pl <= 1'b0;
num <= 1'b0; char <= 1'b0; char_reg <= 1'b0;
num_delay <= 16'd5; cnt_delay <= 1'b0; cnt <= 1'b0;
oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
state <= MAIN; state_back <= MAIN;
end
MAIN:begin
if(cnt_main>=5'd4)
cnt_main<=5'd1;
else
cnt_main <= cnt_main + 1'b1;
case(cnt_main)
5'd0: begin state<=INIT; end
5'd1: begin y_p <= 8'hb0; x_ph <= 8'h10; x_pl <= 8'h00;num <= 5'd16;char<=choice[0];state <= SCAN;end
5'd2: begin y_p <= 8'hb1; x_ph <= 8'h10; x_pl <= 8'h00;num <= 5'd16;char<=choice[1];state <= SCAN;end
5'd3: begin y_p <= 8'hb2; x_ph <= 8'h10; x_pl <= 8'h00;num <= 5'd16;char<=choice[2];state <= SCAN;end
5'd4: begin y_p <= 8'hb3; x_ph <= 8'h10; x_pl <= 8'h00;num <= 5'd16;char<=choice[3];state <= SCAN;end
default: state <= IDLE;
endcase
end
INIT:begin //初始化状态
case(cnt_init)
5'd0: begin oled_rst <= LOW; cnt_init <= cnt_init + 1'b1; end //复位有效
5'd1: begin num_delay <= 16'd25000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end //延时大于3us
5'd2: begin oled_rst <= HIGH; cnt_init <= cnt_init + 1'b1; end //复位恢复
5'd3: begin num_delay <= 16'd25000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end //延时大于220us
5'd4: begin
if(cnt>=INIT_DEPTH) begin //当25条指令及数据发出后,配置完成
cnt <= 1'b0;
cnt_init <= cnt_init + 1'b1;
end else begin
cnt <= cnt + 1'b1; num_delay <= 16'd5;
oled_dcn <= CMD; char_reg <= cmd[cnt]; state <= WRITE; state_back <= INIT;
end
end
5'd5: begin cnt_init <= 1'b0; state <= MAIN; end //初始化完成,返回MAIN状态
default: state <= IDLE;
endcase
end
SCAN:begin //刷屏状态,从RAM中读取数据刷屏
if(cnt_scan == 5'd11) begin
if(num) cnt_scan <= 5'd3;
else cnt_scan <= cnt_scan + 1'b1;
end else if(cnt_scan == 5'd12) cnt_scan <= 1'b0;
else cnt_scan <= cnt_scan + 1'b1;
case(cnt_scan)
5'd 0: begin oled_dcn <= CMD; char_reg <= y_p; state <= WRITE; state_back <= SCAN; end //定位列页地址
5'd 1: begin oled_dcn <= CMD; char_reg <= x_pl; state <= WRITE; state_back <= SCAN; end //定位行地址低位
5'd 2: begin oled_dcn <= CMD; char_reg <= x_ph; state <= WRITE; state_back <= SCAN; end //定位行地址高位
5'd 3: begin num <= num - 1'b1;end
5'd 4: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][63:56];state <= WRITE; state_back <= SCAN; end
5'd 5: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][55:48];state <= WRITE; state_back <= SCAN; end
5'd 6: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][47:40];state <= WRITE; state_back <= SCAN; end
5'd 7: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][39:32];state <= WRITE; state_back <= SCAN; end
5'd 8: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][31:24];state <= WRITE; state_back <= SCAN; end
5'd 9: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][23:16];state <= WRITE; state_back <= SCAN; end
5'd10: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][15:8];state <= WRITE; state_back <= SCAN; end
5'd11: begin oled_dcn <= DATA; char_reg<=mem[char[(num*8)+:8]][7:0];state <= WRITE; state_back <= SCAN; end
5'd12: begin state <= MAIN; end
default: state <= IDLE;
endcase
end
WRITE:begin //WRITE状态,将数据按照SPI时序发送给屏幕
if(cnt_write >= 5'd17) cnt_write <= 1'b0;
else cnt_write <= cnt_write + 1'b1;
case(cnt_write)
5'd 0: begin oled_csn <= LOW; end //9位数据最高位为命令数据控制位
5'd 1: begin oled_clk <= LOW; oled_dat <= char_reg[7]; end //先发高位数据
5'd 2: begin oled_clk <= HIGH; end
5'd 3: begin oled_clk <= LOW; oled_dat <= char_reg[6]; end
5'd 4: begin oled_clk <= HIGH; end
5'd 5: begin oled_clk <= LOW; oled_dat <= char_reg[5]; end
5'd 6: begin oled_clk <= HIGH; end
5'd 7: begin oled_clk <= LOW; oled_dat <= char_reg[4]; end
5'd 8: begin oled_clk <= HIGH; end
5'd 9: begin oled_clk <= LOW; oled_dat <= char_reg[3]; end
5'd10: begin oled_clk <= HIGH; end
5'd11: begin oled_clk <= LOW; oled_dat <= char_reg[2]; end
5'd12: begin oled_clk <= HIGH; end
5'd13: begin oled_clk <= LOW; oled_dat <= char_reg[1]; end
5'd14: begin oled_clk <= HIGH; end
5'd15: begin oled_clk <= LOW; oled_dat <= char_reg[0]; end //后发低位数据
5'd16: begin oled_clk <= HIGH; end
5'd17: begin oled_csn <= HIGH; state <= DELAY; end //
default: state <= IDLE;
endcase
end
DELAY:begin //延时状态
if(cnt_delay >= num_delay) begin
cnt_delay <= 16'd0; state <= state_back;
end else cnt_delay <= cnt_delay + 1'b1;
end
default:state <= IDLE;
endcase
end
end
always@(posedge clk or negedge rst_n)//字幕选择数据
begin
if(!tone_en) begin
choice[0] = 128'h0000_0000_0000_0000_0000_0000_0000_0000;
choice[1] = 128'h0000_0000_0000_0000_0000_0000_0000_0000;
choice[2] = 128'h0000_0000_0000_0000_0000_0000_0000_0000;
choice[3] = 128'h0000_0000_0000_0000_0000_0000_0000_0000; end
else if(!rst_n) begin
choice[0] = 128'h0102_0000_0506_0000_090a_0000_0d0e_0000;
choice[1] = 128'h0304_0000_0708_0000_0b0c_0000_0f10_0000;
choice[2] = time_1;
choice[3] = time_2; end
else if(flag==3'd1) begin
choice[0] = 128'h0102_0000_0506_0000_090a_0000_0d0e_0000;
choice[1] = 128'h0304_0000_0708_0000_0b0c_0000_0f10_0000;
choice[2] = time_1;
choice[3] = time_2; end
else if(flag==3'd2) begin
choice[0] = 128'h1112_0000_1516_0000_0000_0000_0000_0000;
choice[1] = 128'h1314_0000_1718_0000_0000_0000_0000_0000;
choice[2] = time_1;
choice[3] = time_2; end
else if(flag==3'd3) begin
choice[0] = 128'h191a_0000_1d1e_0000_0000_0000_0000_0000;
choice[1] = 128'h1b1c_0000_1f20_0000_0000_0000_0000_0000;
choice[2] = time_1;
choice[3] = time_2; end
else begin
choice[0] = 128'h0000_0000_0000_0000_0000_0000_0000_0000;
choice[1] = 128'h0000_0000_0000_0000_0000_0000_0000_0000;
choice[2] = 128'h0000_0000_0000_0000_0000_0000_0000_0000;
choice[3] = 128'h0000_0000_0000_0000_0000_0000_0000_0000; end
end
//OLED配置指令数据
always@(posedge rst_n)
begin
cmd[ 0] = {8'hae};
cmd[ 1] = {8'h00};
cmd[ 2] = {8'h10};
cmd[ 3] = {8'h00};
cmd[ 4] = {8'hb0};
cmd[ 5] = {8'h81};
cmd[ 6] = {8'hff};
cmd[ 7] = {8'ha1};
cmd[ 8] = {8'ha6};
cmd[ 9] = {8'ha8};
cmd[10] = {8'h1f};
cmd[11] = {8'hc8};
cmd[12] = {8'hd3};
cmd[13] = {8'h00};
cmd[14] = {8'hd5};
cmd[15] = {8'h80};
cmd[16] = {8'hd9};
cmd[17] = {8'h1f};
cmd[18] = {8'hda};
cmd[19] = {8'h00};
cmd[20] = {8'hdb};
cmd[21] = {8'h40};
cmd[22] = {8'h8d};
cmd[23] = {8'h14};
cmd[24] = {8'haf};
end
//16*16点阵字库数据
always@(posedge rst_n)
begin
mem[ 0] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};//空
mem[ 1] = {8'h40,8'h40,8'h44,8'h44,8'h64,8'h54,8'h4C,8'h47};//奇
mem[ 2] = {8'h4C,8'h54,8'h64,8'hC4,8'h44,8'h40,8'h40,8'h00};
mem[ 3] = {8'h00,8'h00,8'h00,8'h1E,8'h12,8'h12,8'h12,8'h12};
mem[ 4] = {8'h1E,8'h40,8'h80,8'h7F,8'h00,8'h00,8'h00,8'h00};
mem[ 5] = {8'h40,8'h40,8'h42,8'hCC,8'h00,8'h08,8'hC8,8'h08};//迹
mem[ 6] = {8'hF8,8'h09,8'h0E,8'hF8,8'h08,8'h48,8'h88,8'h00};
mem[ 7] = {8'h00,8'h40,8'h20,8'h1F,8'h20,8'h51,8'h48,8'h46};
mem[ 8] = {8'h41,8'h48,8'h50,8'h4F,8'h40,8'h40,8'h41,8'h00};
mem[ 9] = {8'h02,8'h02,8'hF2,8'h92,8'h92,8'h92,8'h92,8'hFE};//再
mem[ 10] = {8'h92,8'h92,8'h92,8'h92,8'hF2,8'h02,8'h02,8'h00};
mem[ 11] = {8'h04,8'h04,8'hFF,8'h04,8'h04,8'h04,8'h04,8'h07};
mem[ 12] = {8'h04,8'h04,8'h44,8'h84,8'h7F,8'h04,8'h04,8'h00};
mem[ 13] = {8'h04,8'h84,8'h84,8'hFC,8'h84,8'h84,8'h00,8'hFE};//现
mem[ 14] = {8'h02,8'h02,8'hF2,8'h02,8'h02,8'hFE,8'h00,8'h00};
mem[ 15] = {8'h20,8'h60,8'h20,8'h1F,8'h10,8'h90,8'h40,8'h23};
mem[ 16] = {8'h18,8'h06,8'h01,8'h7E,8'h80,8'h83,8'hE0,8'h00};
mem[ 17] = {8'h10,8'h10,8'h10,8'hD0,8'hFF,8'h90,8'h10,8'h00};//相
mem[ 18] = {8'hFE,8'h22,8'h22,8'h22,8'h22,8'hFE,8'h00,8'h00};
mem[ 19] = {8'h08,8'h04,8'h03,8'h00,8'hFF,8'h00,8'h03,8'h00};
mem[ 20] = {8'hFF,8'h42,8'h42,8'h42,8'h42,8'hFF,8'h00,8'h00};
mem[ 21] = {8'h00,8'h00,8'hFE,8'h92,8'h92,8'h92,8'h92,8'hFE};//思
mem[ 22] = {8'h92,8'h92,8'h92,8'h92,8'hFE,8'h00,8'h00,8'h00};
mem[ 23] = {8'h40,8'h38,8'h01,8'h00,8'h3C,8'h40,8'h40,8'h42};
mem[ 24] = {8'h4C,8'h40,8'h40,8'h70,8'h05,8'h08,8'h30,8'h00};
mem[ 25] = {8'h20,8'h20,8'h20,8'h20,8'h20,8'h20,8'h20,8'hFF};//大
mem[ 26] = {8'h20,8'h20,8'h20,8'h20,8'h20,8'h20,8'h20,8'h00};
mem[ 27] = {8'h80,8'h80,8'h40,8'h20,8'h10,8'h0C,8'h03,8'h00};
mem[ 28] = {8'h03,8'h0C,8'h10,8'h20,8'h40,8'h80,8'h80,8'h00};
mem[ 29] = {8'h40,8'h20,8'hF0,8'h28,8'h24,8'h27,8'h24,8'hE4};//鱼
mem[ 30] = {8'h24,8'h34,8'h2C,8'h20,8'hE0,8'h00,8'h00,8'h00};
mem[ 31] = {8'h40,8'h40,8'h4F,8'h49,8'h49,8'h49,8'h49,8'h4F};
mem[ 32] = {8'h49,8'h49,8'h49,8'h49,8'h4F,8'h40,8'h40,8'h00};
mem[ 33] = {8'h00,8'hE0,8'h10,8'h08,8'h08,8'h10,8'hE0,8'h00};//0
mem[ 34] = {8'h00,8'h0F,8'h10,8'h20,8'h20,8'h10,8'h0F,8'h00};
mem[ 35] = {8'h00,8'h00,8'h10,8'h10,8'hF8,8'h00,8'h00,8'h00};//1
mem[ 36] = {8'h00,8'h00,8'h20,8'h20,8'h3F,8'h20,8'h20,8'h00};
mem[ 37] = {8'h00,8'h70,8'h08,8'h08,8'h08,8'h08,8'hF0,8'h00};//2
mem[ 38] = {8'h00,8'h30,8'h28,8'h24,8'h22,8'h21,8'h30,8'h00};
mem[ 39] = {8'h00,8'h30,8'h08,8'h08,8'h08,8'h88,8'h70,8'h00};//3
mem[ 40] = {8'h00,8'h18,8'h20,8'h21,8'h21,8'h22,8'h1C,8'h00};
mem[ 41] = {8'h00,8'h00,8'h80,8'h40,8'h30,8'hF8,8'h00,8'h00};//4
mem[ 42] = {8'h00,8'h06,8'h05,8'h24,8'h24,8'h3F,8'h24,8'h24};
mem[ 43] = {8'h00,8'hF8,8'h88,8'h88,8'h88,8'h08,8'h08,8'h00};//5
mem[ 44] = {8'h00,8'h19,8'h20,8'h20,8'h20,8'h11,8'h0E,8'h00};
mem[ 45] = {8'h00,8'hE0,8'h10,8'h88,8'h88,8'h90,8'h00,8'h00};//6
mem[ 46] = {8'h00,8'h0F,8'h11,8'h20,8'h20,8'h20,8'h1F,8'h00};
mem[ 47] = {8'h00,8'h18,8'h08,8'h08,8'h88,8'h68,8'h18,8'h00};//7
mem[ 48] = {8'h00,8'h00,8'h00,8'h3E,8'h01,8'h00,8'h00,8'h00};
mem[ 49] = {8'h00,8'h70,8'h88,8'h08,8'h08,8'h88,8'h70,8'h00};//8
mem[ 50] = {8'h00,8'h1C,8'h22,8'h21,8'h21,8'h22,8'h1C,8'h00};
mem[ 51] = {8'h00,8'hF0,8'h08,8'h08,8'h08,8'h10,8'hE0,8'h00};//9
mem[ 52] = {8'h00,8'h01,8'h12,8'h22,8'h22,8'h11,8'h0F,8'h00};
mem[ 53] = {8'h00,8'h00,8'h00,8'h00,8'hC0,8'h38,8'h04,8'h00};// /
mem[ 54] = {8'h00,8'h60,8'h18,8'h07,8'h00,8'h00,8'h00,8'h00};
mem[ 55] = {8'h00,8'h00,8'h00,8'hC0,8'hC0,8'h00,8'h00,8'h00};//:
mem[ 56] = {8'h00,8'h00,8'h00,8'h30,8'h30,8'h00,8'h00,8'h00};
end
endmodule
d.计时模块
本模块利用晶振进行计时,确定当前播放的曲子的剩余时间,并在OLED上进行显示。
module timer(
input clk,
input rst,
input tone_en,
input start_stop,
input [2:0] flag,//通过Beeper块中的flag标志位控制同步切换
output reg [127:0] out_1,
output reg [127:0] out_2
);
reg [3:0] second_ge;
reg [3:0] second_shi;
reg [1:0] minute;
reg ss;
reg [2:0] flag_pre;//存储前一步的flag状态,与现在flag相比较,如果发生变化则切换计时
reg [23:0]count;
always@(posedge clk or negedge rst) begin
if(!tone_en) begin
count <= count;
end
else if(!rst) begin
minute <= 2'd1;
second_ge <= 1'b0;
second_shi <= 1'b0;
flag_pre <= 3'd1;
count <= 1'b0; end
else if(flag_pre != flag) begin
case(flag)
3'd1: begin second_ge <= 1'b0;second_shi <= 1'b0;minute <= 2'd1; end
3'd2: begin second_ge <= 4'd2;second_shi <= 1'b0;minute <= 2'd2; end
3'd3: begin second_ge <= 4'd2;second_shi <= 4'd1;minute <= 2'd1; end
endcase
flag_pre <= flag;
count <= 1'b0;
end
else if(!ss) begin
count <= count;
end
else if((count >= 24'd12000000)&&(second_ge == 4'd0)&&(second_shi != 4'd0)) begin
second_ge <= 4'd9;
second_shi <= second_shi - 1'b1;
count <= 1'b0;
end
else if((count >= 24'd12000000)&&(second_ge == 4'd0)&&(second_shi == 4'd0)&&(minute !=2'd0)) begin
second_ge <= 4'd9;
second_shi <= 4'd5;
minute <= minute - 1'b1;
count <= 1'b0;
end
else if((count >= 24'd12000000)&&(second_ge == 4'd0)&&(second_shi == 4'd0)&&(minute ==2'd0)) begin
second_ge <= 1'b0;
second_shi <= 1'b0;
minute <= 1'b0;
count <= 1'b0; end
else if(count >= 24'd12000000) begin
count <= 1'b0;
second_ge <= second_ge - 1'b1; end
else begin count <= count + 1'b1; end
end
always@(posedge clk or negedge rst) begin
if(!rst) begin
ss <= 1'b0; end
else if(start_stop) begin
ss <= ~ss;end
else
begin ss <= ss; end
end
always@(posedge clk) begin //将时间译码,显示到OLED上
case(minute)
2'd0: begin out_1[127:120] <= 8'h21;
out_2[127:120] <= 8'h22; end
2'd1: begin out_1[127:120] <= 8'h23;
out_2[127:120] <= 8'h24; end
2'd2: begin out_1[127:120] <= 8'h25;
out_2[127:120] <= 8'h26; end
default:begin out_1[127:120] <= 8'h00;
out_2[127:120] <= 8'h00; end
endcase
out_1[119:112] <= 8'h37;
out_2[119:112] <= 8'h38;
case(second_shi)
4'd0: begin out_1[111:104] <= 8'h21;
out_2[111:104] <= 8'h22; end
4'd1: begin out_1[111:104] <= 8'h23;
out_2[111:104] <= 8'h24; end
4'd2: begin out_1[111:104] <= 8'h25;
out_2[111:104] <= 8'h26; end
4'd3: begin out_1[111:104] <= 8'h27;
out_2[111:104] <= 8'h28; end
4'd4: begin out_1[111:104] <= 8'h29;
out_2[111:104] <= 8'h2a; end
4'd5: begin out_1[111:104] <= 8'h2b;
out_2[111:104] <= 8'h2c; end
default:begin out_1[111:104] <= 8'h00;
out_2[111:104] <= 8'h00; end
endcase
case(second_ge)
4'd0: begin out_1[103:96] <= 8'h21;
out_2[103:96] <= 8'h22; end
4'd1: begin out_1[103:96] <= 8'h23;
out_2[103:96] <= 8'h24; end
4'd2: begin out_1[103:96] <= 8'h25;
out_2[103:96] <= 8'h26; end
4'd3: begin out_1[103:96] <= 8'h27;
out_2[103:96] <= 8'h28; end
4'd4: begin out_1[103:96] <= 8'h29;
out_2[103:96] <= 8'h2a; end
4'd5: begin out_1[103:96] <= 8'h2b;
out_2[103:96] <= 8'h2c; end
4'd6: begin out_1[103:96] <= 8'h2d;
out_2[103:96] <= 8'h2e; end
4'd7: begin out_1[103:96] <= 8'h2f;
out_2[103:96] <= 8'h30; end
4'd8: begin out_1[103:96] <= 8'h31;
out_2[103:96] <= 8'h32; end
4'd9: begin out_1[103:96] <= 8'h33;
out_2[103:96] <= 8'h34; end
default:begin out_1[103:96] <= 8'h00;
out_2[103:96] <= 8'h00; end
endcase
out_1[95:0] <= 96'h0000_0000_0000_0000_0000_0000;
out_2[95:0] <= 96'h0000_0000_0000_0000_0000_0000;
end
endmodule
e.按键消抖模块
本模块使用了电子森林的案例,不多做阐述。
module debounce (clk,rst,key,key_pulse);
parameter N = 1; //要消除的按键的数量
input clk;
input rst;
input [N-1:0] key; //输入的按键
output [N-1:0] key_pulse; //按键动作产生的脉冲
reg [N-1:0] key_rst_pre; //定义一个寄存器型变量存储上一个触发时的按键值
reg [N-1:0] key_rst; //定义一个寄存器变量储存储当前时刻触发的按键值
wire [N-1:0] key_edge; //检测到按键由高到低变化是产生一个高脉冲
//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
always @(posedge clk or negedge rst)
begin
if (!rst) begin
key_rst <= {N{1'b1}}; //初始化时给key_rst赋值全为1,{}中表示N个1
key_rst_pre <= {N{1'b1}};
end
else begin
key_rst <= key; //第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre
key_rst_pre <= key_rst; //非阻塞赋值。相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值
end
end
assign key_edge = key_rst_pre & (~key_rst);//脉冲边沿检测。当key检测到下降沿时,key_edge产生一个时钟周期的高电平
reg [17:0] cnt; //产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器
//产生20ms延时,当检测到key_edge有效是计数器清零开始计数
always @(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 18'h0;
else if(key_edge)
cnt <= 18'h0;
else
cnt <= cnt + 1'h1;
end
reg [N-1:0] key_sec_pre; //延时后检测电平寄存器变量
reg [N-1:0] key_sec;
//延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec <= {N{1'b1}};
else if (cnt==18'h3ffff)
key_sec <= key;
end
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec_pre <= {N{1'b1}};
else
key_sec_pre <= key_sec;
end
assign key_pulse = key_sec_pre & (~key_sec);
endmodule
四、项目完成情况
本项目完成了音乐播放、曲名显示、曲子切换、按键消抖等全部功能,为了确保每一首曲子时长在一分钟以上,附带了计时功能。具体展示见视频。
五、项目总结
由于是初学verlog,代码在可读性方面还有待加强,许多地方过于冗杂了。
附件下载
music_player_impl1.jed
music_player.rar
团队介绍
中南大学,电子信息工程系
团队成员
李正豪
中南大学,电子信息工程专业
评论
0 / 100
查看更多
猜你喜欢
制作基于ICE40_FPGA_PICO利用PWM驱动蜂鸣器可以播放、切换曲子并显示中文曲名的音乐播放器使用ICE40_FPGA_PICO开发板,用PWM驱动无源蜂鸣器发出不同的音调,然后对音调的节拍时间进行统计,然后用SPI的方式驱动0.96英寸的oled,把中文曲名和时间显示在上面,可以使用消抖后的按键K1复位,K2进行切歌。
mosu
1702
基于iCE40UP5K的FPGA学习平台利用PWM制作的音乐播放器在超低功耗的ICE FPGA开发板上利用PWM波实现了音乐播放的效果,同时WS2812彩灯在不停的闪烁
爆肝儿
1124
基于小脚丫FPGA(Lattice MXO2-C)实现电子琴设计本项目基于小脚丫FPGA(Lattice MXO2-C)实现电子琴设计,最多可以同时按下六个按键不失真,音程为三个八度,支持蜂鸣器和扬声器演奏,可以存入多首歌曲,选择播放上一曲或者下一曲
zhiwu
1274