fpga4fun.comwhere FPGAs are fun

Music box 2 - Ambulance siren

Let's alternate between two tones. We first use a 24 bits counter "tone" to produce a slow square wave. The MSB bit "tone[23]" toggles with a frequency of about 1.5Hz.
Then we use this bit to switch another counter between two frequencies. Here comes the ambulance!

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-1 : clkdivider/2-1); else counter <= counter-1;

reg speaker;
always @(posedge clk) if(counter==0) speaker <= ~speaker;
endmodule
Police siren

That becomes serious now. We want to generate a ramp that sounds like a police siren.
We start with my "tone" counter. We use only 23 bits to make it twice as fast (MSB toggles at around 3Hz).

Then here comes the trick to get an up-ramp. We extract bits 15 through bit 21 of the tone counter, like that: tone[21:15]. This gives us 7 bits, that go from 0 to 127 at some medium speed. After it reaches 127, it rolls back to 0 and up again.
To get a down-ramp. We invert the same bits, like that: (~tone[21:15]). This gives us 7 bits again, that go down from 127 to 0.
To switch between the up-ramp and the down-ramp, we use tone[22]. As soon as the up-ramp hits 127, we switch to the down-ramp, until it goes to 0, and then back to the up-ramp...

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

// That means
// "if tone[22]=1 then ramp=tone[21:15] else ramp=~tone[21:15]"

If this ramp business does not make sense to you, we have a more detailed explanation here.

So "ramp" value goes from 7'b0000000 to 7'b1111111. To get a usable value to produce a sound, we pad it with the 2 bits '01' up front, and the 6 bits '000000' in the back.

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

This way, "clkdivider" have a value ranging from 15'b010000000000000 to 15'b011111111000000, or in hex 15'h2000 to 15'h3FC0, or in decimal 8192 to 16320. With a 25MHz input clock, that produces a sound from 765Hz to 1525Hz for an high pitch siren.

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
High-speed pursuit

Now let's go in high-speed pursuit. The siren is sometimes slow, sometimes fast.
So "tone[21:15]" gives us a fast ramp, while "tone[24:18]" gives us a slow one.

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};

The complete code looks like this.

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