查看原文
其他

大神教你DIY | 如何用一块FPGA开发板制作音乐盒?!

相信大家已经在网上见识过很多“民间大神”们的天才(奇葩)手工DIY了,一些简简单单的材料在他们的捣鼓下,瞬间华丽转身,变废为宝。今天,我们为大家整理了一位手工大神的DIY心得——如何利用FPGA开发板DIY一个音乐盒,也就是如何使我们的FPGA播放声音和音乐!


下面开始吧....


首先需生成单个音调,然后慢慢地做更有趣的事情,如制作警报声和播放曲调。

 

需要准备的硬件


该项目使用的是一个Pluto的FPGA开发板,还有一个扬声器和一个1kΩ的电阻。



更加直观的展示是下面这样的:



本次DIY的音乐盒分为4个部分:


1.简单的哔哔声

2.警报声

3.音调

4.曲子


简单的哔哔声


FPGA可以轻松实现二进制计数器。例如,在回滚之前,16位计数器将从0到65535(65536个不同的值)计数。Pluto板具有一个25MHz的时钟振荡器,因此我们可以轻松构建一个25MHz时钟16位自动计数器。其最高位切换频率为25000000/65536 = 381Hz。


其Verilog HDL的代码如下:

module music(clk, speaker);

input clk;

output speaker;

 

// 首先创建一个16位二级制计数器

 

reg [15:0] counter;

always @(posedge clk) counter <= counter+1;

 

// 使用计数器的最高有效位来驱动扬声器

 

assign speaker = counter[15];

endmodule

 

详细讲解的话就是,“clk”在25MHz下运行,“counter [0]”看起来像是一个12.5MHz信号(它以25MHz的频率进行更新变化,变化的值为0 1 0 1 ......因此看起来像12.5MHz信号),“counter [1]“是6.125MHz信号,依此类推。


由于我们使用计数器的最高有效位(第15位)来驱动输出,因此“扬声器”输出会产生一个完美的381Hz方波信号。

 

“A”音符(440Hz)

如果要获得这些随机频率的话,为什么不尝试生成一个440Hz的信号呢。440Hz正是“A”音符的频率。但并不是将25MHz除以65536,而是除以56818。


代码如下:

module music(clk, speaker);

input clk;

output speaker;

 

reg [15:0] counter;

always @(posedge clk) if(counter==56817) counter <= 0; else counter <= counter+1;

 

assign speaker = counter[15];

endmodule

 

但是我们的实现存在问题。虽说如预期的那样,频率为440Hz,但输出占空比并不再是50%。低电平从计数器= 0变为计数器= 32767(当计数器的第15位为低电平时),然后是从32768到56817的高电平。这使得“扬声器”仅在42%的时间内处于高电平。获得50%占空比的最简单方法是添加一个将输出分为相同两份步骤。首先,我们除以28409(而不是56818)然后除以2。


代码如下:

module music(clk, speaker);

input clk;

output speaker;

 

reg [14:0] counter;

always @(posedge clk) if(counter==28408) counter<=0; else counter <= counter+1;

 

reg speaker;

always @(posedge clk) if(counter==28408) speaker <= ~speaker;

endmodule

 

添加一个参数

这里的代码基本相同。添加了一个名为“clkdivider”的新参数,使得计数器变为“倒计时”计数器 - 只是看你偏向于正向计数还是倒计时了。


代码如下:

module music(clk, speaker);

input clk;

output speaker;

parameter clkdivider = 25000000/440/2;

 

reg [14:0] counter;

always @(posedge clk) if(counter==0) counter <= clkdivider-1; else counter <= counter-1;

 

reg speaker;

always @(posedge clk) if(counter==0) speaker <= ~speaker;

endmodule

 

警报声


救护车警报声

我们可以在两个音调之间循环。我们首先用一个24位计数器的“音调”来产生一个较慢的方波。其MSB(最高有效位)“tone[23]”是一1.5Hz的频率进行变换的。


然后我们就可以用这个最高有效位切换到另一个计数器,从而在两个频率之间切换。


代码如下:

module music(clk, speaker);

input clk;

output speaker;

parameter clkdivider = 25000000/440/2;

 

reg [23:0] tone;

always @(posedge clk) tone <= tone+1;

 

reg [14:0] counter;

always @(posedge clk) if(counter==0) counter <= (tone[23] ? clkdivider-: clkdivider/2-1); else counter <= counter-1;

 

reg speaker;

always @(posedge clk) if(counter==0) speaker <= ~speaker;

endmodule

 

警车警报声

我们接下来生成一个听起来像是警笛的斜波。


首先从“音调”计数器开始。我们只用23位使其比原来快两倍(MSB以3Hz的频率进行变化)。

 

然后我们生成一个上升的斜波。我们将音调计数器的15位到21位提取出来,比如tone[21:15]。这就给到了我们7位,也就是是说以某个中等的速度从0计数到127,。一旦计数到127,又从127回到0。


要想获得下降的斜波,我们可以将这些同样的位倒转过来,比如~tone[21:15]。又给到了7位,但是这是从127数到0的。


要想在上升斜波和下降斜波之间转换,我们使用的是tone[22]。一旦上升斜波达到127,就切换到下降斜波,知道计数变为0为止,然后又回到上升谐波…


代码如下:

wire [6:0] ramp = (tone[22] ? tone[21:15] : ~tone[21:15]);

 

// 这也就意味着

// "如果 tone[22]=1 那么斜波等于tone[21:15] 否则斜波等于~tone[21:15]"

 

如果你没理解这个斜波的比喻的话没关系,我们换一种说法来讲。


假设我有一个6位十进制计数器,从000000计数到199999。这个计数器是自动计数的,每毫秒计数一次(1秒内计算1000次),但达到199999之后,又回到0,然后继续计数。以这种速度的话,计数器每200秒又回到初始状态。

 

很明显,第一位(这里称之为digit #0或者说是digit[0])增加速度是最快的。甚至无法用肉眼察觉,所以我们无法使用这一位。然后第二位(digit #1)增加速度要慢十倍,以此类推…

 

假设我们只看digit #4和digit #3(= digit[4:3])。你会发现digit[4:3]在0到99之间变化,,而且每秒增加一次。

 

因此,我们制定以下规则:如果digit[5]是0,那么我就看digit[4:3],而当digit[5]时1,那我就看其反码,比如99- digit[4:3],这样的话我们可以看出来一个从0到99再从99到0的梯度。


digits[5:3]  rampvalue

   000           00

   001           01

   ...           ..

   ...           ..

   098           98

   099           99

   100           99

   101           98

   102           97

   103           96

   ...           ..

   ...           ..

   197           02

   198           01

   199           00

   000           00

   001           01

   002           02

   ...           ..

 

所以“梯度”值从7'b0000000 计数到7'b1111111。为了获得可用的值来产生声音,我们将2位“01”放在前面,6位“000000”放在后面。


代码如下:

wire [14:0] clkdivider = {2'b01, ramp, 6'b000000};

 

这样的话,clkdivider的取值范围从15'b010000000000000到 15'b011111111000000,以16进制表示就是从15'h2000到15'h3FC0,或者是十进制的8192到16320.当以25MHz为输入时钟频率时,就可以生成一个从765Hz到1525Hz的尖锐警笛声。


代码如下:

module music(clk, speaker);

input clk;

output speaker;

 

reg [22:0] tone;

always @(posedge clk) tone <= tone+1;

 

wire [6:0] ramp = (tone[22] ? tone[21:15] : ~tone[21:15]);

wire [14:0] clkdivider = {2'b01, ramp, 6'b000000};

 

reg [14:0] counter;

always @(posedge clk) if(counter==0) counter <= clkdivider; else counter <= counter-1;

 

reg speaker;

always @(posedge clk) if(counter==0) speaker <= ~speaker;

endmodule

 

高速追捕警报声

然后我们来生成警车高速追捕的警笛声,这个警笛声时快时慢,所以我们用tone[21:15]给到一个快速的音调,再用tone[24:18]给到一个慢速的。


代码如下:

wire [6:0] fastsweep = (tone[22] ? tone[21:15] : ~tone[21:15]);

wire [6:0] slowsweep = (tone[25] ? tone[24:18] : ~tone[24:18]);

wire [14:0] clkdivider = {2'b01, (tone[27] ? slowsweep : fastsweep), 6'b000000};

 

完整代码如下:

module music(clk, speaker);

input clk;

output speaker;

 

reg [27:0] tone;

always @(posedge clk) tone <= tone+1;

 

wire [6:0] fastsweep = (tone[22] ? tone[21:15] : ~tone[21:15]);

wire [6:0] slowsweep = (tone[25] ? tone[24:18] : ~tone[24:18]);

wire [14:0] clkdivider = {2'b01, (tone[27] ? slowsweep : fastsweep), 6'b000000};

 

reg [14:0] counter;

always @(posedge clk) if(counter==0) counter <= clkdivider; else counter <= counter-1;

 

reg speaker;

always @(posedge clk) if(counter==0) speaker <= ~speaker;

endmodule

 

演奏音符


现在我们想要演奏一首曲子,所以需要来获取不同的音符,就像电子琴一样。


如果我们用6位来实现音符,那么我可以获得64个音符。每个八度一共有12个音符,所以64个音符可以实现5个八度,完全足够弹奏一首曲目了。

 

步骤1

要想实现一组音调不断升高的声音,我们用一个28位计数器来距离,提取其中6个MSB,从而给到6位的音调。


代码如下:

reg [27:0] tone;

always @(posedge clk) tone <= tone+1;

 

wire [5:0] fullnote = tone[27:22];

 

在25MHz的时钟下,每个音符持续167ms,64个音符一共需要10.6s才能演奏完成。

 

步骤2

我们将“fullnote”分成12份。这样就可以给到我们一个八度(一共有5个8度,所以我们只需要3位,从0到4)和音符(从0到11,需要4位)。


代码如下:

wire [2:0] octave;

wire [3:0] note;

divide_by12 divby12(.numer(fullnote[5:0]), .quotient(octave), .remain(note));

 

此处用了一个叫divide_by12的子模块来实现分频。细节稍后讲解。

 

步骤3

从一个八度到另一个八度,频率乘以了“2”。这个在硬件上很容易实现,我们在步骤4上进行实现。但是要从一个音符到另一个音符,频率就要乘以1.0594。这样的话就没那么容易在硬件上实现了,所以我们需要看下提前计算好的音符值。

 

我们将主时钟除以512得到音符A,除以483得到音符A#,除以456得到音符B…记住,除以一个更低的值得到的是更高的音符。


一个八度下的音符数值如下:

always @(note)

case(note)

  0: clkdivider = 512-1; // A

  1: clkdivider = 483-1; // A#/Bb

  2: clkdivider = 456-1; // B

  3: clkdivider = 431-1; // C

  4: clkdivider = 406-1; // C#/Db

  5: clkdivider = 384-1; // D

  6: clkdivider = 362-1; // D#/Eb

  7: clkdivider = 342-1; // E

  8: clkdivider = 323-1; // F

  9: clkdivider = 304-1; // F#/Gb

  10: clkdivider = 287-1; // G

  11: clkdivider = 271-1; // G#/Ab

  12: clkdivider = 0; // should never happen

  13: clkdivider = 0; // should never happen

  14: clkdivider = 0; // should never happen

  15: clkdivider = 0; // should never happen

endcase

 

always @(posedge clk) if(counter_note==0) counter_note <= clkdivider; else counter_note <= counter_note-1;

 

每当counter_note等于0时,就进入到下一个八度。

 

步骤4

现在我们要处理好不同的八度,对于最低的八度,我们将“counter_note”除以256,对于第二个八度,除以128,以此类推。


reg [7:0] counter_octave;

always @(posedge clk)

if(counter_note==0)

begin

 if(counter_octave==0)

counter_octave<=(octave==0?255:octave==1?127:octave==2?63:octave==3?31:octave==4?15:7);

 else

  counter_octave <= counter_octave-1;

end

 

reg speaker;

always @(posedge clk)if(counter_note==0&&counter_octave==0)speaker <= ~speaker;

 

完整代码如下:

module music(clk, speaker);

input clk;

output speaker;

 

reg [27:0] tone;

always @(posedge clk) tone <= tone+1;

 

wire [5:0] fullnote = tone[27:22];

 

wire [2:0] octave;

wire [3:0] note;

divide_by12 divby12(.numer(fullnote[5:0]), .quotient(octave), .remain(note));

 

reg [8:0] clkdivider;

always @(note)

case(note)

  0: clkdivider = 512-1; // A

  1: clkdivider = 483-1; // A#/Bb

  2: clkdivider = 456-1; // B

  3: clkdivider = 431-1; // C

  4: clkdivider = 406-1; // C#/Db

  5: clkdivider = 384-1; // D

  6: clkdivider = 362-1; // D#/Eb

  7: clkdivider = 342-1; // E

  8: clkdivider = 323-1; // F

  9: clkdivider = 304-1; // F#/Gb

  10: clkdivider = 287-1; // G

  11: clkdivider = 271-1; // G#/Ab

  12: clkdivider = 0; // should never happen

  13: clkdivider = 0; // should never happen

  14: clkdivider = 0; // should never happen

  15: clkdivider = 0; // should never happen

endcase

 

reg [8:0] counter_note;

always @(posedge clk) if(counter_note==0) counter_note <= clkdivider; else counter_note <= counter_note-1;

 

reg [7:0] counter_octave;

always @(posedge clk)

if(counter_note==0)

begin

 if(counter_octave==0)

  counter_octave <= (octave==0?255:octave==1?127:octave==2?63:octave==3?31:octave==4?15:7);

 else

  counter_octave <= counter_octave-1;

end

 

reg speaker;

always @(posedge clk) if(counter_note==&& counter_octave==0) speaker <= ~speaker;

endmodule

 

除以12

“除以12”的模块将一个6位的可变数值作为分子,然后将其除以定值12。这样可以获得一个三位的商(0..5)和4位的余数(0..11)。要想除以12,可以先除以4再除以3。除以4很简单:我们将分子的两位去掉,然后将其作为余数就行。所以我们只需要用6-2=4位来除以3,我们用一个查询表来实现。


module divide_by12(numer, quotient, remain);

input [5:0] numer;

output [2:0] quotient;

output [3:0] remain;

 

reg [2:0] quotient;

reg [3:0] remain_bit3_bit2;

 

assign remain = {remain_bit3_bit2, numer[1:0]}; // the first 2 bits are copied through

 

always @(numer[5:2]) // and just do a divide by "3" on the remaining bits

case(numer[5:2])

   0: begin quotient=0; remain_bit3_bit2=0; end

   1: begin quotient=0; remain_bit3_bit2=1; end

   2: begin quotient=0; remain_bit3_bit2=2; end

   3: begin quotient=1; remain_bit3_bit2=0; end

   4: begin quotient=1; remain_bit3_bit2=1; end

   5: begin quotient=1; remain_bit3_bit2=2; end

   6: begin quotient=2; remain_bit3_bit2=0; end

   7: begin quotient=2; remain_bit3_bit2=1; end

   8: begin quotient=2; remain_bit3_bit2=2; end

   9: begin quotient=3; remain_bit3_bit2=0; end

 10: begin quotient=3; remain_bit3_bit2=1; end

 11: begin quotient=3; remain_bit3_bit2=2; end

 12: begin quotient=4; remain_bit3_bit2=0; end

 13: begin quotient=4; remain_bit3_bit2=1; end

 14: begin quotient=4; remain_bit3_bit2=2; end

 15: begin quotient=5; remain_bit3_bit2=0; end

endcase

endmodule

 

一段旋律


现在我们可以弹奏一段旋律了,这个非常简单,只是看我们怎么利用ROM中的音符。

 

// 用计数器来读取ROM中我们想要播放的旋律

reg [30:0] tone;

always @(posedge clk) tone <= tone+1;

 

wire [7:0] fullnote;

music_ROM ROM(.clk(clk), .address(tone[29:22]), .note(fullnote));

 

我们还需要:

1.ROM读取结束后旋律停止

2.值为0的fullnote是一个声音很小的音符

 

所以我们改变上一个设计中的代码

always @(posedge clk) if(counter_note==&& counter_octave==0) speaker <= ~speaker;

改为

always @(posedge clk) if(counter_note==&& counter_octave==&& tone[30]==&& fullnote!=0) speaker <= ~speaker;


剩下的设计仍保持原样。


完整的代码如下,你猜得出来这是什么曲子吗?

 

完整代码

 

// 尽可能使用25MHz的时钟频率 (其它频率会

// 改变曲子的音调和速度)

 

/////////////////////////////////////////////////////

module music(

    input clk,

    output reg speaker

);

 

reg [30:0] tone;

always @(posedge clk) tone <= tone+31'd1;

 

wire [7:0] fullnote;

music_ROM get_fullnote(.clk(clk), .address(tone[29:22]), .note(fullnote));

 

wire [2:0] octave;

wire [3:0] note;

divide_by12 get_octave_and_note(.numerator(fullnote[5:0]), .quotient(octave), .remainder(note));

 

reg [8:0] clkdivider;

always @*

case(note)

     0: clkdivider = 9'd511;//A

     1: clkdivider = 9'd482;// A#/Bb

     2: clkdivider = 9'd455;//B

     3: clkdivider = 9'd430;//C

     4: clkdivider = 9'd405;// C#/Db

     5: clkdivider = 9'd383;//D

     6: clkdivider = 9'd361;// D#/Eb

     7: clkdivider = 9'd341;//E

     8: clkdivider = 9'd322;//F

     9: clkdivider = 9'd303;// F#/Gb

    10: clkdivider = 9'd286;//G

    11: clkdivider = 9'd270;// G#/Ab

    default: clkdivider = 9'd0;

endcase

 

reg [8:0] counter_note;

reg [7:0] counter_octave;

always @(posedge clk) counter_note <= counter_note==? clkdivider : counter_note-9'd1;

always @(posedge clk) if(counter_note==0) counter_octave <= counter_octave==? 8'd255 >> octave : counter_octave-8'd1;

always @(posedge clk) if(counter_note==&& counter_octave==&& fullnote!=&& tone[21:18]!=0) speaker <= ~speaker;

endmodule

 

/////////////////////////////////////////////////////

module divide_by12(

    input [5:0] numerator,  // value to be divided by 12

    output reg [2:0] quotient, 

    output [3:0] remainder

);

 

reg [1:0] remainder3to2;

always @(numerator[5:2])

case(numerator[5:2])

     0: begin quotient=0; remainder3to2=0; end

     1: begin quotient=0; remainder3to2=1; end

     2: begin quotient=0; remainder3to2=2; end

     3: begin quotient=1; remainder3to2=0; end

     4: begin quotient=1; remainder3to2=1; end

     5: begin quotient=1; remainder3to2=2; end

     6: begin quotient=2; remainder3to2=0; end

     7: begin quotient=2; remainder3to2=1; end

     8: begin quotient=2; remainder3to2=2; end

     9: begin quotient=3; remainder3to2=0; end

    10: begin quotient=3; remainder3to2=1; end

    11: begin quotient=3; remainder3to2=2; end

    12: begin quotient=4; remainder3to2=0; end

    13: begin quotient=4; remainder3to2=1; end

    14: begin quotient=4; remainder3to2=2; end

    15: begin quotient=5; remainder3to2=0; end

endcase

 

assign remainder[1:0] = numerator[1:0];  // the first 2 bits are copied through

assign remainder[3:2] = remainder3to2;  // and the last 2 bits come from the case statement

endmodule

/////////////////////////////////////////////////////

 

module music_ROM(

    input clk,

    input [7:0] address,

    output reg [7:0] note

);

 

always @(posedge clk)

case(address)

      0: note<= 8'd25;

      1: note<= 8'd27;

      2: note<= 8'd27;

      3: note<= 8'd25;

      4: note<= 8'd22;

      5: note<= 8'd22;

      6: note<= 8'd30;

      7: note<= 8'd30;

      8: note<= 8'd27;

      9: note<= 8'd27;

     10: note<= 8'd25;

     11: note<= 8'd25;

     12: note<= 8'd25;

     13: note<= 8'd25;

     14: note<= 8'd25;

     15: note<= 8'd25;

     16: note<= 8'd25;

     17: note<= 8'd27;

     18: note<= 8'd25;

     19: note<= 8'd27;

     20: note<= 8'd25;

     21: note<= 8'd25;

     22: note<= 8'd30;

     23: note<= 8'd30;

     24: note<= 8'd29;

     25: note<= 8'd29;

     26: note<= 8'd29;

     27: note<= 8'd29;

     28: note<= 8'd29;

     29: note<= 8'd29;

     30: note<= 8'd29;

     31: note<= 8'd29;

     32: note<= 8'd23;

     33: note<= 8'd25;

     34: note<= 8'd25;

     35: note<= 8'd23;

     36: note<= 8'd20;

     37: note<= 8'd20;

     38: note<= 8'd29;

     39: note<= 8'd29;

     40: note<= 8'd27;

     41: note<= 8'd27;

     42: note<= 8'd25;

     43: note<= 8'd25;

     44: note<= 8'd25;

     45: note<= 8'd25;

     46: note<= 8'd25;

     47: note<= 8'd25;

     48: note<= 8'd25;

     49: note<= 8'd27;

     50: note<= 8'd25;

     51: note<= 8'd27;

     52: note<= 8'd25;

     53: note<= 8'd25;

     54: note<= 8'd27;

     55: note<= 8'd27;

     56: note<= 8'd22;

     57: note<= 8'd22;

     58: note<= 8'd22;

     59: note<= 8'd22;

     60: note<= 8'd22;

     61: note<= 8'd22;

     62: note<= 8'd22;

     63: note<= 8'd22;

     64: note<= 8'd25;

     65: note<= 8'd27;

     66: note<= 8'd27;

     67: note<= 8'd25;

     68: note<= 8'd22;

     69: note<= 8'd22;

     70: note<= 8'd30;

     71: note<= 8'd30;

     72: note<= 8'd27;

     73: note<= 8'd27;

     74: note<= 8'd25;

     75: note<= 8'd25;

     76: note<= 8'd25;

     77: note<= 8'd25;

     78: note<= 8'd25;

     79: note<= 8'd25;

     80: note<= 8'd25;

     81: note<= 8'd27;

     82: note<= 8'd25;

     83: note<= 8'd27;

     84: note<= 8'd25;

     85: note<= 8'd25;

     86: note<= 8'd30;

     87: note<= 8'd30;

     88: note<= 8'd29;

     89: note<= 8'd29;

     90: note<= 8'd29;

     91: note<= 8'd29;

     92: note<= 8'd29;

     93: note<= 8'd29;

     94: note<= 8'd29;

     95: note<= 8'd29;

     96: note<= 8'd23;

     97: note<= 8'd25;

     98: note<= 8'd25;

     99: note<= 8'd23;

    100: note<= 8'd20;

    101: note<= 8'd20;

    102: note<= 8'd29;

    103: note<= 8'd29;

    104: note<= 8'd27;

    105: note<= 8'd27;

    106: note<= 8'd25;

    107: note<= 8'd25;

    108: note<= 8'd25;

    109: note<= 8'd25;

    110: note<= 8'd25;

    111: note<= 8'd25;

    112: note<= 8'd25;

    113: note<= 8'd27;

    114: note<= 8'd25;

    115: note<= 8'd27;

    116: note<= 8'd25;

    117: note<= 8'd25;

    118: note<= 8'd32;

    119: note<= 8'd32;

    120: note<= 8'd30;

    121: note<= 8'd30;

    122: note<= 8'd30;

    123: note<= 8'd30;

    124: note<= 8'd30;

    125: note<= 8'd30;

    126: note<= 8'd30;

    127: note<= 8'd30;

    128: note<= 8'd27;

    129: note<= 8'd27;

    130: note<= 8'd27;

    131: note<= 8'd27;

    132: note<= 8'd30;

    133: note<= 8'd30;

    134: note<= 8'd30;

    135: note<= 8'd27;

    136: note<= 8'd25;

    137: note<= 8'd25;

    138: note<= 8'd22;

    139: note<= 8'd22;

    140: note<= 8'd25;

    141: note<= 8'd25;

    142: note<= 8'd25;

    143: note<= 8'd25;

    144: note<= 8'd23;

    145: note<= 8'd23;

    146: note<= 8'd27;

    147: note<= 8'd27;

    148: note<= 8'd25;

    149: note<= 8'd25;

    150: note<= 8'd23;

    151: note<= 8'd23;

    152: note<= 8'd22;

    153: note<= 8'd22;

    154: note<= 8'd22;

    155: note<= 8'd22;

    156: note<= 8'd22;

    157: note<= 8'd22;

    158: note<= 8'd22;

    159: note<= 8'd22;

    160: note<= 8'd20;

    161: note<= 8'd20;

    162: note<= 8'd22;

    163: note<= 8'd22;

    164: note<= 8'd25;

    165: note<= 8'd25;

    166: note<= 8'd27;

    167: note<= 8'd27;

    168: note<= 8'd29;

    169: note<= 8'd29;

    170: note<= 8'd29;

    171: note<= 8'd29;

    172: note<= 8'd29;

    173: note<= 8'd29;

    174: note<= 8'd29;

    175: note<= 8'd29;

    176: note<= 8'd30;

    177: note<= 8'd30;

    178: note<= 8'd30;

    179: note<= 8'd30;

    180: note<= 8'd29;

    181: note<= 8'd29;

    182: note<= 8'd27;

    183: note<= 8'd27;

    184: note<= 8'd25;

    185: note<= 8'd25;

    186: note<= 8'd23;

    187: note<= 8'd20;

    188: note<= 8'd20;

    189: note<= 8'd20;

    190: note<= 8'd20;

    191: note<= 8'd20;

    192: note<= 8'd25;

    193: note<= 8'd27;

    194: note<= 8'd27;

    195: note<= 8'd25;

    196: note<= 8'd22;

    197: note<= 8'd22;

    198: note<= 8'd30;

    199: note<= 8'd30;

    200: note<= 8'd27;

    201: note<= 8'd27;

    202: note<= 8'd25;

    203: note<= 8'd25;

    204: note<= 8'd25;

    205: note<= 8'd25;

    206: note<= 8'd25;

    207: note<= 8'd25;

    208: note<= 8'd25;

    209: note<= 8'd27;

    210: note<= 8'd25;

    211: note<= 8'd27;

    212: note<= 8'd25;

    213: note<= 8'd25;

    214: note<= 8'd30;

    215: note<= 8'd30;

    216: note<= 8'd29;

    217: note<= 8'd29;

    218: note<= 8'd29;

    219: note<= 8'd29;

    220: note<= 8'd29;

    221: note<= 8'd29;

    222: note<= 8'd29;

    223: note<= 8'd29;

    224: note<= 8'd23;

    225: note<= 8'd25;

    226: note<= 8'd25;

    227: note<= 8'd23;

    228: note<= 8'd20;

    229: note<= 8'd20;

    230: note<= 8'd29;

    231: note<= 8'd29;

    232: note<= 8'd27;

    233: note<= 8'd27;

    234: note<= 8'd25;

    235: note<= 8'd25;

    236: note<= 8'd25;

    237: note<= 8'd25;

    238: note<= 8'd25;

    239: note<= 8'd25;

    240: note<= 8'd25;

    241: note<= 8'd0;

    242: note<= 8'd00;

    default: note <= 8'd0;

endcase

endmodule

 

关于如何使用FPGA开发板DIY音乐盒,咱们就先讲到这里,如果大家对FPGA的开发与应用感兴趣,或者自己也想尝试用FPGA开发板DIIY一些不一样的东西,可以扫描下面二维码加入“发烧友FPGA群-1”,与更多志同道合的人“大话FPGA”!

立即扫码入群

进群还有更多福利:10套FPGA精华资料、电子发烧友网站积分、VIP权限统统免费送!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存