Department of Electrical Engineering
Columbia University
EE E3082.  Digital Electronics Laboratory
Laboratory 5.  Electric piano design using Xilinx FPGAs, Part I


In this design, you will implement an electric piano using field programmable gate arrays (FPGAs).  The LSI and MSI gates used to implement the digital logic of the previous labs are largely chips of the past.  Digital logic today is implemented in CMOS on VLSI chips -- either programmable microprocessors or microcontroller, application-specific integrated circuits (custom VLSI chips with more limited programmability), or FPGAs, which can be customized to perform specific logic functions through a kind of once at start-up programming.  FPGAs are often used to "prototype" designs before committing to an expensive ASIC implementation.

Digital logic today is generally designed not as a netlist of gates but as a logic description that is captured in a hardware description language (HDL).  The two most popular HDLs are Verilog and VHDL, the latter of which we use extensively at Columbia.

In Labs 5 and 6, you will learn how "real" digital design is done using VHDL, implemented on a fairly state-of-the-art FPGA.  The design we have chosen for this exercise is an electric piano.  By using a piezoelectric speaker, which has a fairly high impedance, we can drive it directly from the FPGA.  This is a similar approach to what is done on the musical greeting cards.  The VHDL description is synthesized to logic and mapped to the gates of the FPGA.

If you are interest in some music theory, please check out the following links:

  1. Piano Overview
  2. Music Theory of a Piano



The schematic of the design is shown below.  This is captured in the file piano.vhd, which you will find in /usr/cad/xilinx/s3_kit_cd/designs/piano/src. You should copy the contents of this directory to your home directory; for example, to copy everything to a new directory on your desktop, you can do the following:

mkdir ~/Desktop/piano_lab
cp /usr/cad/xilinx/s3_kit_cd/designs/piano/src ~/Desktop/piano_lab -r

The design consists of the following components:

User Interface

The user interface (contained in piano.vhd) translates signals from off-chip into a selection to be fed into your note decoder. The current reference design uses the pushbuttons and switches on the Xilinx board as "keys" of the piano.

P  How are the notes encoded on the switches?

Clock Divider

The clock divider is implemented as a loadable binary counter.  The VHDL source is contained in the file clk_dvd.vhd

P  If CLK is a 50 MHz input clock, sketch the waveforms on CLK_OUT and ONE_SHOT for EN = '1' and DIV = X"32" (32 in hex, which is equal to 50 in decimal representation). You should also sketch the toggle and trigger waveforms; you can trace these signals one cycle at a time to determine their behavior.

The design uses good synchronous design practice in whcih the output of your clock divider is used as a clock enable.  The entire design functions from a signel clock, the timing and distribution of which can be carefully controlled.

Note Decoder

In this part of the design,  we create a decoder that takes as input a binary encoded note, and outputs a binary encoded clock divider to be used with your clock divider ratio. The logic for this part of the design is contained in note_gen.vhd.

Here you can see the divider as a function of the output frequency for a 16-bit clock divider with 1MHz clock input. I chose 1MHz as the clock frequency because it gives fidelity in the audio frequency range (20Hz -> 20kHz) given the 16-bit granularity.

For a 1MHz input, calculate the output frequency as a function of divider value. Combining what you calculate with the table at the top of this document, verify the values used for the note decoder to define the notes of the piano.

7-Segment Display State Machine

In order to save pins the output for each digit of the four-digit 7-segment display is time multiplexed. This means you can only change the value of one of the digits at one time.

By constantly scanning the value of the digits with a low-rate clock you can achieve a persistance of vision similar to a television. Too slow a scan-rate will cause a noticable flicker, however.

This figure from the "Spartan-3 Starter Kit Board User Guide" shows how you will scan each digit in time. Notice that the AN signals are active low.

In this figure you see all the control signals used for the 7-segment display. The design mplements a 7-segment decoder that translates a binary-encoded number into the segments needed for that number.

P Study the implementation in seven_seg.vhd and explain how the design functions.


We will lean how to synthesize this design to the Xilinx FPGAs to implement the piano.


First we will get familiar with FPGA, Xilinx Design Tools and S3 Starter Board

First open the "Programmable Logic Design Quick Start Handbook".

    $ cd /usr/cad/xilinx/s3_kit_cd/files 
    $ acroread BeginnnersBook-screen.pdf &

Read these chapters:

Next open the "Spartan-3 Starter Kit Board User Guide"

    $ cd /usr/cad/xilinx/s3_kit_cd/files/starterkit
    $ acroread s3_board_ug.pdf &

Find the exact part number number and package type of the FPGA used on the board.

EXAMPLE: Part number "xc3s4000fg900-4" is decoded as:

    part: xc3s4000 -- A large Spartan-3
    package: fg900 -- 900 pin ball grid package
    speed grade: -4

You will need to tell the tools exactly what part you are designing for in the next step.


Let's now get started with the ISE tools.

Create a new project

  1. Open ISE by typing ise& at the command line; if the window does not come up within 10 seconds, you may need to first SSH into your machine by typing ssh -Y machine_name at the command prompt (for example, ssh -Y
  2. Create a new HDL project.
  3. Give it a descriptive but short name, no spaces.
  4. Choose the exact part you found in the User Guide from the previous step. The part is a -4 speed grade. This information is also laser etched to the top of the part package, albeit hard to read.

We'll add source files later. Select NEXT for the next two steps. You should now have the Project Navigator window available.

Add the source files

  1. Project -> Add Source
  2. Choose piano.vhd, seven_seg.vhd, clk_dvd.vhd, and note_gen.vhd (all are VHDL design files).

Attach the Constraints file

  1. Project -> Add Source
  2. Choose s3board.ucf
  3. Attach to your top level module piano. This provides timing information as well as assigning the pins of the FPGA to match the connectors on the board.

Set Constraint File Option

Normally the tools will not let you set a constraint on a NET that does not exist. You will not use many of the signals on the board that are in the constraint file.

  1. Click on your top level VHDL in the Sources window.
  2. Right Click Implement Design in the Processess window and choose Properties.
  3. Turn on Allow Unmatched LOC Constraints

Adding your code

Note the following rules that have been followed:

Add the rest of the VHDL code to your design

If you want to add VHDL to your design (you will need to do this later), ISE includes a feature called Language Templates

  1. In ISE Click on the target device (X3S...)
  2. Choose Edit -> Language Templates
  3. Scroll to VHDL -> Synthesis Constructs -> Coding Examples -> Posedge -> w/ Asynchronous Active High Reset

    This is the template you should use for adding a FF in your device. Remember that in synchronous design each FF must have a reset.

  4. As an example of how to use the template, <clock> should be replaced with your clock signal name, for instance CLK.

Simulating your design in ModelSim

It is important to debug the design first in a simulator.  Place and Route and implementation takes a very long time, and the only way to debug on the board is by setting LEDs and/or using an oscilloscope or logic analyzer. Extensive simulation is really necessary to verify functionality and debug errors.

  1. Read : "Advanced tips for using ModelSim with Project Navigator"
  2. Note: If  the simulator does not come up for some reason, set
                Edit --> Preferences
                [Integrated Tools]
                Model Tech Simulator --> /usr/cad/modelsim/linux/vsim
To simulate your design, you will create a VHDL file called a testbench.  This will instantiate the device-under-test (DUT), 
generate the clocks, and provide other stimulus to your design for testing.

Create Test Bench

  1. Project -> New Source
  2. VHDL Test Bench
  3. Give your Test Bench a Name : piano_tb
  4. Select your top level design piano as your source file.
  5. Finish

Add test stimulus to your testbench

The following is a basic testbench template.

-- *** Test Bench - User Defined Section ***

    -- 50MHz system Clock Generation
    clk_gen: PROCESS 
        CLK_IN <= '0';
        wait for 10 ns;
        CLK_IN <= '1';
        wait for 10 ns;
    -- End clock generation addition

    tb : PROCESS

     -- System Reset - Sets reset to push_button # 0
     pb_in(0) <= '1';
     wait for 100 ns;
     pb_in(0) <= '0';
     -- end system reset addition.

     wait; -- will wait forever

-- *** End Test Bench - User Defined Section ***
P Add additional stimulus to test for various values of pb_in and switch_in..

Make sure you save the test bench (Ctrl-S)


  1. Click on your new Test Bench in "Sources in Project" window
  2. Modelsim Simulator -> Simulate Behavioral Model.

P Save some waveforms from your simulation to demonstrate the functionality of the design.  Use the ksnapshot tool for screenshots. Use gimp to scale the image if necessary.