fpga4fun.com - where FPGAs are fun.
Home
Welcome
Information


FPGA projects
Music box
Pong game
R/C servos
Text LCD module
Quadrature decoder
PWM and one-bit DAC
Debouncer
LED displays
Crossing clock domains
External contributions

FPGA interface projects
RS-232
JTAG
I2C
EPP
SPI
CNC steppers

FPGA advanced projects
Graphic LCD panel
Digital oscilloscope
10BASE-T interface
PCI interface
Spoc CPU core

Hands-on
A simple oscilloscope


FPGA introduction
What are FPGAs?
How FPGAs work
FPGA pins
Clocks and global lines
Download cables
Configuration
Learn more

FPGA software
Design software
Pin assignment
Design-entry/HDL
Simulation/HDL
Synthesis and P&R

FPGA electronic
SMD technology
Crystals and oscillators

HDL info
HDL tutorials
Verilog tips
VHDL tips

Quick-start guides
ISE
Quartus

Site
News
FPGA links
HDL tutorials
Forum


Music box - part 2

Ambulance siren
Let's alternate 2 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 between 2 frequencies for the main counter, and that alternates between the 2 tones. 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 need 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 "speaker" from 765Hz to 1525Hz. That gives us a 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


>>> NEXT: Music box - part 3 >>>



This page was last updated on August 09 2006.