Introduction: VHDL Etch-a-Sketch

For our CPE 133 Final Project at Cal Poly, San Luis Obispo, we built a Etch-a-Sketch using VHDL on the Diligant nexys 3 board. A nexys 3 board that can build logic circuits without worrying about complex external interfaces, and more advanced students can build complete digital systems, including controllers, CODECs, and embedded processors. We utilized the nexys 3 to process the data, the board's buttons as inputs, and a VGA 640X400 resolution screen to show the game. We built various lower level modules that Incorporated reading the player inputs, and then putting them into the game logic to calculate the next move and entering that next move into memory, and finally entering the data into a game display driver which translated our data into colors on the screen. Here is a detailed description on how we designed our project.

Step 1: Hardware Preparation

This is the hardware we used:
  1. VGA 640X400 resolution screen
  2. Diligent: Nexys 3 Board
  3. VGA cable

Step 2: Software Preparation

The ISE Design Suite is a tool used for assembling and writing the VHDL files. The ISE Design Suite also generates the bit file to write to the Nexys 3 board. Digilent Adept is used to write the bit file to the fpga board.

Step 3: Black Box Diagram

The most important step to starting a digital design project is to come up with a black box diagram. This should be as detailed as possible so that you know exactly what modules you need and how you plan on connecting them.

The highest level modules that we used are:

  • GameMem driver
    • interfacing with the RAM and how it choose the address
  • GameLogic driver
    • describes how the game works
  • VGA controller
    • controls the timing for the VGA display and says what pixel to paint on
  • VGA encoder
    • outputs the rgb values
  • 2 clk dividers
    • divides the clocks into usable frequencies for the VGA controller
  • move input process
    • encodes the players inputs from the four directional buttons on the Nexys 3

What follows is a basic description of each module and some of the reasoning behind why they function. If you wish to use the example code then you will need to use the same names for the ports of IP generated ports as used in the examples.

Step 4: Building the Move Input Process

The move input process converts the signals from the button press and encodes in into our move values where the up button encodes "00", right button encodes "01", down button encodes "10", and the left button encodes "11". This process is built in the top level structural module.

An example of this can be found in the VGA line structural file.

Step 5: Building the GameMem Driver

  • This driver controls the memory module created in Isim
    • This module controls the address passed to memory, preventing erroneous writes to memory when the display encoder needs to read from memory to the display while the game logic tries to write to memory.
      • Check the priority signal if it is a logic high then only use the address from the display logic and set write enable to low.(see the example code address_select for an example);
  • The game memory driver uses an ip core for the ram, to create this follow these steps:
    • Select the new source option and add an ip core gen
    • Set the width and depth
      • Width is the size of each binary value in memory and length is the number of memory slots needed. We used more slots than needed so that we could get the right address length to make calculating the addresses easier.
      • Create a .coe file or use the one we provided. This file sets the initial values for the memory block.
      • Select the option for reset pins

Step 6: Building the GameLogic Driver

  • This block tracks what the current location of the point being draw and the next position that it will be drawn into.
    • The main operating principle behind this module is to update the address for the current location with each rising edge of the game speed clk.
      • With each rising edge the current location gets the calculated address.
      • The calculated address is based off the move in from the encoding process in the top level block and the current location.
        • This current location is created by adding 1 for a move right, subtracting one for a move left, subtracting 80 for a move up, and adding 80 for a move down.

Step 7: Building the VGA Controller

  • This is the sync module that provides the timing. We used a module provided by Digilent on there nexys 2 page found here under the title VGA controler reference design: http://www.digilentinc.com/Products/Detail.cfm?Na...
  • The module used is the vga_controler_640_60.
    • This module provides the timing signals and pixel location needed to interface with the vga device.

Step 8: Building the VGA Encoder

  • This module takes the location of the current pixel from the vga_control module and the data from memory. It calculates the location of the pixel in memory and what needs to be written at that point.
    • The IEEE.STD_LOGIC_UNSIGNED.ALL library will need to be included in this module to allow the arithmetic with the signals x and y. The signals of of x and y are first divide the signals by eight, then multiply y by 80 and add it to x.
      • Why this works… The data for the display can be seen as a long list, the address is the location and the data at the address is what needs to go to the display. If place (0,0) is the upper left corner of the screen and we increment by one place to the right then. If you choose a point, the point directly below it is the value of that point plus 80, so any point is the value of x plus 80 for each row below the first.
    • Pass the RGB values from memory into the signals out of your encoding module for R,G,and B.
      • Data in memory is stored in a three bit number formatted as (RGB) so if memory passes (110) then R gets 1, G gets 1, and B gets 0;
    • This module also passes a value to control the memory module. This signal “priority” is just the inverse of the blanking signal sent from the vga_control module.

Step 9: Building the Two Clock Dividers

The clock dividers are made using the IP CORE Gen. This is a system that takes your inputs and what frequency you want for your clock and various other inputs and writes a code for you of the clock divider.

To get make a clock divider:

  • locate the IP CORE GEN
  • locate the Clocking Wizard
  • set the output frequencies to 100 MHz, 25 MHz, and 100 MHz respectively
  • ports:
    • in: clk_in
    • out: clk25, clk100, clkgame

The clkgame is a 3.33 Hz clk and you can adjust later to adjust how fast you want the line to move. The lower the frequency, the slower the line will move.

Step 10: How to Assemble All of the Files

  1. Download all files from this page and from the Diligent Website
  2. Open Xilinx ISE Design Suite
  3. Create a new project
  4. Set proper board properties for the nexys 3 as pictured above
  5. Add the following files by hitting the add source button
    1. Click Generate Programming File

    Step 11: How to Run the Program

    1. Open Diligent Adept
    2. Connect the board to the computer
    3. Locate the bit file of the final project
    4. Click program

    Step 12: Enjoy!

    The game will begin immediately after programming the board. The game instructions are listed below.

    Step 13: Game Instructions

    The goal of the game is to draw the coolest piece of art possible using lines. So be creative and enjoy!

    To work the buttons, you need to press and hold to move the line in the desired direction. If no buttons are pushed the line will automatically travel towards the right. When the line reaches either the left or right side of the screen, it will loop around to the opposite side. If the line reaches either the top or bottom, it will continue to travel, off the screen, in that direction until it overflows, so try to avoid going off the top and bottom.