Etch-A-Sketch - Ece
Personal tools

Etch-A-Sketch

From Ece

Jump to: navigation, search

Contents

Final Proposal

Note: this proposal is an expansion of the first draft created in Phase 1.

Objective

Our goal is to make an on-screen Etch-A-Sketch using two encoders as inputs.

Team Members & Team Name

Team Etch-A-Sketch is:

  • Khanh Bui - Coordinator
  • Jeff Brantley - Recorder
  • Terrence Shannon - Checker

Introduction

An optical rotary quadrature encoder provides a way to track both the direction and degree of rotation of a shaft. The device consists of a shaft connected to a disc with radial slots cut out of it. In the encoder housing, at the perimeter of the disc, an LED shines light through the slots onto a pair of photodiodes or phototransistors. As the shaft turns, the slots passing over the LED cause electrical pulses to be generated and output at regular rotational intervals, thus allowing a connected device, such as an FPGA, to track the amount of rotation. The pair of phototransistors allow the connected device to determine the rotation direction as well, by tracking the order of the pulses generated.

Concept

A pair of knobs (attached to encoders) will be used with a VGA monitor to produce an enhanced version of the classic Etch-A-Sketch toy. One knob will move a drawing cursor horizontally, and the other will move it vertically. The screen will display the sketching canvas, as well as a panel across the top. One side of the panel will display different cursor options: draw red, draw green, draw blue, erase, and lift pen (no draw). The other side will display helpful messages to the user.

Required Parts

Update: all ordered parts were received on 4/2/07.

  • Spartan-3 Development Board
  • Grayhill Optical Encoder - Series 62P
    • Part Number: 62P22-L0
    • Package: Series 62P - Low torque, no pushbutton
    • Voltage Supply: 5 Vdc +/-.25 Vdc
    • Datasheet: Series 62P
    • Unit Price: $3.71
    • Quantity Required: 2
    • Delivered: 4/2/07
  • Kilo International Knob - DD Series
    • Part Number: DD-90-4-6MM
    • Package: .236" (6mm) shaft diameter, .925" (23.50mm) knob diameter, black matte color
    • Datasheet: DD Series
    • Unit Price: $5.13
    • Quantity Required: 2
    • Delivered: 4/2/07

Proposed Work

  1. Terrence will develop a module that translates the encoder inputs to screen coordinates or cursor selection, depending on the current mode (drawing mode or cursor-choosing mode).
  2. Terrence will develop a module that stores the current mode by toggling a flip-flop on every press and release of a connected button, ignoring the switch bounce that occurs.
  3. Jeff will develop a module that draws the sketch area, producing the correct RGB outputs based on the pixel being drawn, the current cursor location and type, and the contents of an internally maintained RAM that stores the past cursor movements (i.e. the drawing itself).
  4. Khanh will develop a module that draws the top panel of icons and messages based on the current mode, the current cursor choice, and the current pixels being drawn. In addition to RGB outputs, this module will have an output to indicate when it is currently drawing, allowing it to control the select line of the next module.
  5. Terrence will develop a multiplexer module to choose between the RGB outputs of the previous two modules. Its select line will be driven by the previous module.

See Fig. 1 for a schematic showing how the modules will work together.

phase1-toplevel.jpg

Figure 1 - Top-level block schematic of proposed design (first draft).

Modules

Pre-existing Modules

These modules were provided by the constructor during the course of the semester.

VGA Synchronization (vga_sync)

This module handles the synchronization of VGA signals, turning on the vertical and horizontal sync lines with the proper timing, and providing the currently drawn pixels to other modules that actually choose what color to draw a given pixel. This module is useful for resolutions of 640x480 and 128x96.

  • Inputs:
    • clk -- 50MHz clock signal
  • Outputs:
    • h_sync -- VGA horizontal synchronization signal
    • v_sync -- VGA vertical synchronization signal
    • video_on -- Turns on when drawing occurs, and turns off during the VGA "blanking" time.
    • pixel_row -- The row (0-479) of the currently drawn pixel.
    • pixel_column -- The column (0-639) of the currently drawn pixel.
    • subpixel_row -- Same as pixel_row, but increments every five pixels, giving a 96-pixel resolution.
    • subpixel_column -- Same as pixel_column, but increments every five pixels, giving a 128-pixel resolution.
VGA Buffer (vga_buffer)

This module buffers VGA outputs from drawing modules, using the video_on signal of the vga_sync module to determine its output timing.

  • Inputs:
    • clk -- 50MHz clock signal
    • red_in, green_in, blue_in -- RGB inputs to be buffered
    • video_on -- Signal to determine when VGA is on or is blanking.
  • Outputs:
    • red_out, green_out, blue_out -- Buffered RGB signals to send to monitor.
Video ROM (vid_rom)

This module is used within the canvas_draw module to store the drawing as it is entered. It is an IP core that contains two bits of storage per address, allowing the storage of one of four colors for each pixel at a resolution of 128x96.

  • Inputs:
    • clk -- 50MHz clock signal
    • addr -- Address of memory location to read or write.
    • din -- The data to be written to a memory location. In this case, this will be one of four colors options.
    • we -- Write enable line, which must be asserted in order to write to a memory location.
  • Outputs:
    • dout -- The data stored in a specified memory location.
Character ROM (char_rom)

This module contains a basic set of alphanumeric and punctuation characters, each occupying an 8-pixel square on the screen. It can be read only on a pixel-by-pixel basis to determine which pixels in an 8x8 grid are part of the character.

  • Inputs:
    • char_addr -- The address of the desired character, multiplied by eight.
    • char_row -- The row of the desired pixel to check.
    • char_col -- The column of the desired pixel to check.
  • Outputs:
    • out_pixel -- Tells whether the specified pixel is part of the 8x8 representation of the specified character.

Modules to be Developed

These modules will be developed Team Etch-A-Sketch.

Button-Driven Toggle Flip Flop (debounce_tff)

This module debounces a button press and release, toggling a flip flop upon each release. It is used in this design to store the current mode -- drawing or choosing a cursor.

  • Inputs:
    • clk -- 50MHz clock signal
    • button -- Signal from non-debounced button.
  • Outputs:
    • q -- The current state of the internal flip flop.
  • Verification:
    • Setup -- Connect the button input to a button, and the q output to the clock input of an 8-bit rotating shifter, whose parallel output drives the 8 LEDs on the development board. Ground all data input pins of the shifter except one. Connect a second button to the shifter's load input.
    • Test -- Press and release the first button while holding down the shifter load button, which should trigger a clock edge on the shifter, loading in a single '1'. Release the shifter load button. Now, every subsequent press and release of the first button should toggle the input at the shifter clock. Thus, every other press and release should shift the single '1', which can be observed on the LEDs.
    • Alternately, it might be possible to use an oscilloscope to capture the output of this module following a press and release of an attached button.
Knob Decode (knob_decode)
Chooser code Cursor type
000 White/Erased
001 Red
010 Green
011 Blue
100 Lift Pen
Table 1 - Cursor Choice Encoding

This module senses the rotation of two rotary optical quadrature encoder. When in drawing mode is detected, it translates one encoder as a horizontal position, and the other as a vertical position, corresponding to on-screen pixels at a 128x96 resolution. In chooser mode, the horizontal-input knob is translated as one of five cursor choices. The horizontal position shall be constrained to the pixel width of the canvas, and the vertical position shall be constrained to the pixel height of the canvas (not including the panel at the top of the screen). However, the cursor choice rolls over, cycling infinitely through the cursor choices.

  • Inputs:
    • clk -- 50MHz clock signal
    • left_a -- Channel A of the left encoder.
    • left_b -- Channel B of the left encoder.
    • right_a -- Channel A of the right encoder.
    • right_b -- Channel B of the right encoder.
    • chooser_on -- Indicates whether the system is in chooser mode, thus determining how to interpret the encoder inputs.
  • Outputs:
    • pen_x -- The x-coordinate of the cursor in terms of on-screen pixels, at a 128x96 screen resolution.
    • pen_y -- The y-coordinate of the cursor in terms of on-screen pixels, at a 128x96 screen resolution, but constrained so that it cannot overlap with the panel area.
    • chooser -- Which cursor mode (out of five) is currently selected. See Table 1.
  • Verification:
    • Setup -- Connect the encoder channels in appropriately as inputs. Connect a switch to the chooser_on input. Using the seg_decode previously provided by the instructor, drive the left two seven-segment displays on the development board with pen_x, and the right two displays with pen_y. Connect the chooser output to the three rightmost LEDs on the board.
    • Test -- With the switch low, turn the encoders. Each encoder should cause the hex numbers displayed to increment or decrement within the constrained pixel ranges. With the switch high, the encoder that controlled pen_x should cause a binary increment or decrement to be displayed on the three LEDs, rolling back around at the ends of the five-value range. Based on the switch position, either the seven-segment displays should change, or the LEDs should change, but never both at the same time.
Canvas Drawer (canvas_draw)

This module stores the actual drawing in a video memory, based on the sequence of pen locations passed to it, as well as the pen/cursor type chosen. It also is used to draw the actual canvas, outputting the RGB values for each pixel based on the memory contents. Additionally, it draws the correct cursor at the full 640x480 resolution. See Figure 2 below for a sample depiction.

  • Inputs:
    • clk - 50MHz clock signal
    • px_row -- Row of the pixel currently being drawn (at 640x480 resolution).
    • px_col -- Column of the pixel currentlny being drawn (at 640x480 resolution).
    • subpx_row -- Row of the pixel currentlny being drawn (at 128x96 resolution).
    • subpx_col -- Column of the pixel currentlny being drawn (at 128x96 resolution).
    • pen_x -- Current x-coordinate of the pen.
    • pen_y -- Current y-coordinate of the pen.
    • pen_choice -- Current choice of cursor.
    • clear -- Synchronous clear. (Note: the clearing takes one screen-drawing cycle to erase the entire memory).
  • Outputs:
    • r, g, b -- RGB value of the currently-drawn pixel.
  • Verification:
    • Setup -- Connect the module to the vga_sync and vga_buf modules in order to display to a VGA monitor. Connect the clear input to a button. Drive pen_x, pen_y, and pen_choice with 8-bit registers, and drive the registers' data lines with the development board's switches. Designate the remaining buttons as clock inputs to the three registers.
    • Test -- Test the module's drawing ability by registering pen locations and pen choices via the switches and buttons. Note that the module will be able to draw on even the topmost part of the screen, but that this is okay, since the panel_draw module will dominate the VGA output of the overall design whenever these pixels are being drawn.
Panel Drawer (panel_draw)
Chooser code Message
Chooser Off BTN3: Choose cursor, BTN0: Clear canvas
000 Cursor: Erase, Press BTN3 to select
001 Cursor: Draw Red, Press BTN3 to select
010 Cursor: Draw Green, Press BTN3 to select
011 Cursor: Draw Blue, Press BTN3 to select
100 Cursor: Lift Pen, Press BTN3 to select
Table 2 - Panel Messages


phase2-screen-small.jpg

Figure 2 - Sample output with canvas and panel. Enlarge.

This module will draw a panel at the top of the screen, displaying the cursor options as five colored rectangles, with a rectangular outline around the current choice. Also, helpful messages will be displayed, telling the user which button to press to enter cursor-choosing mode or to choose a cursor, which button to press to clear the canvas (see Table 2). When cursor-choosing mode is on, it will display a description (e.g. "Draw red" or "Draw green") of the selected cursor. See a depiction of the panel in Figure 2.

  • Inputs:
    • clk -- 50MHz clock signal
    • px_row -- Row of the pixel currently being drawn (at 640x480 resolution).
    • px_col -- Column of the pixel currently being drawn (at 640x480 resolution).
    • chooser -- Current cursor choice.
    • chooser_on -- Indicates whether or not the system is in chooser mode.
  • Outputs:
    • r, g, b -- RGB value of the currently drawn pixel
    • drawing_panel -- Turns on whenever the panel is currently being drawn. It is used for driving a mux select line to select itself for display to the monitor.
  • Verification:
    • Setup -- Connect this module to the vga_sync and vga_buf modules in order to display to a VGA monitor. Connect the rightmost three switches to the module's chooser input, and another switch to the chooser_on input. Splice a multiplexer into the path from this module's g output the vga_buf module's green_in input. Use this module's drawing_panel output as the multiplexer's select input, such that it can select between the g output and a logic '1'.
    • Test -- The panel should be displayed properly, with the selection rectangle and the messages changing based on the switch inputs. Because of the multiplexer circuit, the area of the screen that does not belong to the panel should be displayed as solid green.
VGA Multiplexer (vga_mux)

This module is a multiplexer that is used for choosing between two 3-bit signals, which are, in this case, RGB signals to be produced by two drawing modules.

  • Inputs:
    • vga_a, vga_b -- The two RGB inputs.
    • select -- A select line to choose between the RGB inputs.
  • Outputs:
    • r, g, b -- The chosen RGB value.
  • Verification:
    • Setup -- Connect the inputs to seven of the development board switches; three switches drive vga_a, three switches drive vga_b, and one switch drives select. Connect the outputs to three of the development board LEDs.
    • Test -- Set differnt values on the switch groups for vga_a and vga_b. Confirm that moving the select switch up and down causes the LEDs to display one of the two values asserted on the other switches.

Expected Deliverables

The knobs/encoders, when turned, will produce horizontal and vertical lines on the VGA monitor's screen. A press of one button will switch into cursor-choosing mode, and one of the knobs will control the selection of a different cursor mode. Another press of that button will switch to drawing mode. A second button, when pressed, will clear the drawing screen. In the eraser and lift pen modes, the cursor will move in the same fashion as when drawing, but the cursor will instead erase or preserve any parts of the drawing it passes over.

Module Details

These five modules were developed for our design.

Button-Driven Toggle Flip Flop (debounce_tff.v)

  • Interface
    The interface is essentially the same as was specified in the proposal.
  • Functional Description
    This module toggles the output q on every debounced button press. The output, q, is used to indicate the mode of operation, either drawing or chooser.
  • Detailed Design
    This module is implemented in Verilog using one functional segment.
    • Debounce
    This segment prevents multiple edge detections from one button press.
    • Button Press
    This segment detects a button press and toggles the output of the flip-flop.
  • Module Files
    • Full Project -- Contains a full project configured for the Digilent board.
    • Source Only -- Contains the basic files from which a project can be built.
    • Important Files
      • debounce_tff.v -- The verilog file for this module
      • tff_test.sch -- The top-level schematic used to verify this module

Knob Decode (knob_decode.v)

  • Interface
    The interface is essentially the same as was specified in the proposal, with one modification. The input clk has been added in order to detect changes in the encoder outputs.
  • Functional Description
    This module converts knob turns into movements along each axis. Each encoder has two outputs. Based on the changes in these signals, this module converts this to clockwise or counterclockwise movements. The clockwise and counterclockwise movements are then used to move positive or negative for each encoder.
  • Detailed Design
    This module is implemented in Verilog, and is divided into several functional segments:
    • Clock
    This segment consists of one always blocks, which compensate for encoder output delays. This is accomplished by creating a counter. On every positive clock edge, this counter is incremented. A specific bit of the counter is then routed to the remaining modules to function as their clock signal.
    • Left Encoder
    This segment controls the movement along the x-axis. As the knob is turned, the encoder outputs cycle through a four position pattern. Using this pattern, the module can detect clockwise or counterclockwise movments. Also as the knob is turned, a boundary check is performed to ensure the user cannot move beyond the boudaries set in previous modulels (0 - 127).
    • Right Encoder
    This segment controls the movement along the y-axis, and is essentially the same as the previous segment in all other respects. However, the boundary check is performed for 10-95.
    • Chooser
    This segment modifies the function of the right encoder. Whenever chooser_on is high the right encoder is used to cycle through four chooser options. The same functional logic is used to detect positive or negative turns, but the boundary check is also different for this segment (0 - 4). When chooser_on is low, the right encoder knob behaves as described above.
  • Module Files
    • Full Project -- Contains a full project configured for the Digilent board.
    • Sources Only -- Contains the basic files from which a project can be built.
    • Important files:
      • knob_decode.v -- The Verilog code for this module.
      • knobdecode.sch -- The top-level schematic used to verify this module.

Canvas Drawer (canvas_draw.v)

  • Interface
    The interface is essentially the same as was specified in the proposal, with one modification. The input vs has been added in order to detect the vertical synchronization signal from vga_sync.
  • Functional Description
    This module stores and displays the actual drawing. As the pen coordinates and pen choice change, corresponding color codes are written to corresponding locations in the vid_rom module. Additionally, this module draws the cursor at the appropriate location, according to the current pen location and pen choice.
  • Detailed Design
    This module is implemented in Verilog, and is divided into seven functional segments:
    • Subpixel Correction
    This segment consists of two always blocks, which compensate for delays associated with the vid_rom module. A three-clock-cycle delay was discovered during development, meaning that this segment must anticipate when data is needed from the ROM, and provide an adjusted address. It does so by using a counter to track how long vga_sync has been drawing a subpixel, and applying the next subpixel column address to the vid_rom during the three clock cycles (which correspond to three counter values) preceding vga_sync's transition to a new subpixel. Additionally, whenever a subpx_col value greater than 127 is received, a value of 0 is applied for the column portion of the vid_rom address, in order to anticipate the beginning of the next row.
    • ROM Write Enable
    This segment controls when the write enable line of the vid_rom is asserted. It works in conjunction with the following two segments, asserting write enable either when the clearing flag is asserted, or during the vertical reset if the pen is in a drawing mode, and not lift pen mode.
    • Clear Signals
    Clearing the screen involves writing a 00 (white) to every location in vid_rom, which is easily accomplished during a single screen draw. Whenever a clear input is detected, a flag is set to indicate a clear has been requested. During the vertical reset time, this flag is cleared, but the clearing flag is set, and will remain set until the next vertical reset. Additionally, a clear is desired at power-on to clear the contents of the vid_rom. A single flag, cleared in an initial block, is examined and set once at power-on, causing the first flag above to be set, resulting in a clear of the vid_rom.
    • ROM Address
    The appropriate address must be given to the vid_rom depending on whether its contents are being read for a screen draw, or if new drawing input is being recorded. Whenever the vs input is asserted, the subpx_row and an adjustment of the subpx_col (see Subpixel Correction above) are applied to the vid_rom address input. During a vertical reset (vs is low), the pen coordinates are applied as the address to allow the drawing input information to be written.
    • ROM Data In
    This segment asserts the lower two bits of pen_choice (the two bits with the color information) to the vid_rom data input, except when the clearing flag is on, at which time it asserts 00 at the input.
    • Decode ROM Data Out
    This segment decodes the two-bit color codes stored in the vid_rom into RGB values.
    • Cursor and Drawing Display
    This segment consists of an if-else statement structure to draw the cursor when necessary, and display the vid_rom contents otherwise. First it checks for whether lift pen is asserted or not. If it is, an X is drawn over the subpixel corresponding to the pen location, but otherwise a box is drawn. In each case, the pen location is tested against the currently-drawn location to see if they match, and whether the particular pixel being drawn is part of the cursor. If it is, a black pixel is drawn; otherwise, the color stored in the vid_rom is drawn. For all other subpixel locations, the vid_rom contents are used.
  • Module Files
    • Full Project -- Contains a full project configured for the Digilent board.
    • Sources Only -- Contains the basic files from which a project can be built.
    • Important files:
      • canvas_draw.v -- The Verilog code for this module.
      • CanvasDrawTest.sch -- The top-level schematic used to verify this module.
      • vid_rom.* -- Files needed for the vid_rom IP core.
      • vga_sync.v -- Provided vga_sync module
      • vga_buffer.v -- Provided vga_buffer module

Panel Drawer (panel_draw.v)

  • Interface
    The interface is essentially the same as was specified in the proposal.
  • Functional Description
    This module draws the information panel located at the top of the monitor. It will display the currently selected cursor as well as information regarding how to operate the choosing mechanism. Drawings will be dependent upon the px_row, px_col, chooser, and chooser_on inputs.
  • Detailed Design
    This module is implemented in Verilog using a series of if, else-if statements and is divided into several functional segments:
    • Cursors
    This segment determines the range in which to draw the available cursor modes. These include, Erase, Red, Green, Blue, and Lift Pen. It will draw the appropriate boxes, as shown in Figure 2. Actual placement of the boxes will be dependent upon the px_row and px_col inputs.
    • Selection
    This segment will determine which cursor mode is currently selected. It will draw a rectangular box around the appropriate box drawn from the Cursor Mode segment.
    • Chooser On
    This segment will detect when the chooser_on input is high or low.
    • Display Instructions
    This segment will display appropriate messages as stated in Table 2 and will work in conjunction with the Chooser On segment. It will send the char_rom module an address an will display an appropriate letter depending on the px_col and px_row's current values.
    • Draw Panel
    This segment will assign the Draw_Panel output a 1 when the px_col input is within its appropriate range. Otherwise a 0 will be assigned and the Canvas Drawer will be muxed into the vga buffer.
  • Module Files
    • Full Project -- Contains a full project configured for the Digilent board.
    • Sources Only -- Contains the basic files from which a project can be built.
    • Important files:
      • canvas_draw.v -- The Verilog code for this module.
      • paneldraw_top.sch -- The top-level schematic used to verify this module.
      • char_rom.vhd -- Provided char_rom module
      • vga_sync.v -- Provided vga_sync module
      • vga_buffer.v -- Provided vga_buffer module

VGA Multiplexer (vga_mux)

  • Interface
    The interface is essentially the same as was specified in the proposal.
  • Functional Description
    This module chooses between the canvas_vga and the panel_vga inputs based on the value of drawing_panel. As the values of each input changes, the vga_mux outputs the respective values to the vga buffer.
  • Detailed Design
    This module is implemented using verilog and contains one section.
    • Select
    This segment will determine which vga input is directed to the vga buffer. If select is high, then canvas_vga will be routed to the buffer but if select is low, then panel_vga will be directed to the buffer.
  • Module Files
    • Full Project -- Contains a full project configured for the Digilent board.
    • Full Project -- Contains the basic files from which a project can be built.
    • Important Files
      • vga_mux.v -- The verilog code for this module
      • mux_test.sch -- The top-level schematic used to verify the module

Completed Design

Final Top-Level Design

After all modules were developed, they were connected together. After some debugging (see next section), the design was complete. Figure 3 below shows the final top-level schematic.

phase4-toplevel.jpg

Figure 3 - Top-level schematic showing interconnected modules in completed design.

Etch-A-Sketch Interface

This version of the Etch-A-Sketch works like an enhancement of the original toy, using two knobs as the primary interface. See Figures 4 and 5 below for the interface and output.

  • Moving the cursor
    The cursor is indicated on the screen by either a black-bordered square filled with some color, or a black X floating over a pixel of the drawing.
    • The left knob moves the pen cursor horizontally. Turning the knob counter-clockwise moves the cursor to the left, and turning it clockwise moves the cursor to the right.
    • The right knob moves the pen cursor vertically. Turning the knob counter-clockwise moves the cursor down, and turning it clockwise moves the cursor up.
  • Choosing a Cursor Type
    • Pressing Button 3 (BTN3) once switches to cursor-choosing mode.
    • In this mode, the left knob cycles through five cursor choices:
      • Eraser: This mode causes the cursor to erase everything in its path. The cursor appears as a black square filled with white.
      • Draw Red/Green/Blue: These three cursor choices allow the user to draw red, green, or blue lines. The cursor appears as a black square filled with red, green, or blue.
      • Lift Pen: This mode allows the cursor to be moved without drawing or erasing the current drawing. The cursor appears as a black X sitting on top of a formerly-drawn pixel.
    • Pressing BTN3 a second time selects the cursor that was chosen with the left knob, and returns to drawing mode.
  • Clearing the Screen
    • Pressing Button 0 (BTN0) clears the contents of the screen.
    • When clear is used, the current position and type of cursor is preserved. Thus, if a color is selected, and then the screen is cleared, the pen immediately colors the pixel at which it is currently located.
    • To completely clear and reset the Etch-A-Sketch, the PROG button must be pressed, resetting the board.
phase4-hardware.jpg

Figure 4 - Encoders connected to development board.

phase4-monitor.jpg
Figure 5 - Sample output of drawing on monitor.

Project Files

Full Project -- Contains a full project configured for the Digilent board.

Sources Only -- Contains the basic files from which a project can be built.

Important files:

  • Pre-existing Modules
    • vga_sync.v -- VGA Synchronization (Verilog)
    • vga_buffer.v -- VGA Buffer (Verilog)
    • vid_rom.* -- Video ROM (Necessary IP Core files)
    • char_rom.vhd -- Character ROM (VHDL)
  • Modules Developed
    • debounce_ttf.v -- Button-Driven Toggle Flip Flop (Verilog)
    • knob_decode.v -- Knob Decode (Verilog)
    • canvas_draw.v -- Canvas Drawer (Verilog)
    • panel_draw.v -- Panel Drawer (Verilog)
    • vga_mux.v -- VGA Multiplexer (Verilog)
  • Top-Level
    • sketchtop.sch -- Top-level interconnection of all modules (Schematic)
    • *.sym -- Symbol files for the various modules; these are required for proper representation in the top-level schematic.
    • DigiS3.ucf -- Constraints file for the Digilent development board.

Analysis

While this design was not incredibly complex or difficult to understand on the whole, there were small, unexpected bugs that made the implementation somewhat difficult and very time-consuming. While the Button-Driven Toggle Flip Flop and the VGA Multiplexer were small and easy designs, the other three modules all required major debugging and underwent some changes from the expected design.

  • Knob Decode
    • The original plan was for this module to be sensitive to the edges of the four encoder channels. That is, there would be an always block corresponding to each rising and each falling edge of each encoder channel. Unfortunately, this could not work, since an output can only be assigned from a single always block. Thus, a clock input was added, and on each clock, the current values of the encoder channels was saved and compared to the previous values for changes.
    • The simple change just described caused multiple counts to be registered for each position change of an encoder. This was unexpected, since the encoders were advertised as being debounced. What we had not noticed was that there was a slow transition time for the signals. The datasheet guaranteed less than 30 ms. On the oscilloscope, it appeared that the transition time between 0.0 V and 3.3 V was about 3 ms.
    • The first approach to coping with slow edges was to start a counter that would count off about 3 ms after a change was detected, and then evaluate the state of the encoder after 3 ms. This way, a delay would be applied to the transition, leaving plenty of time to evaluate the channels in between transitions, in the event that the encoders were being spun very quickly. Unfortunately, this simply did not work well.
    • The second approach, originally rejected but re-offered by the TA, was to simply slow down the clock input received by the module. While it was feared this would cause the module to miss consecutive edges at high encoder speeds, the approach actually worked flawlessly.
  • Canvas Drawer
    • The first problem with this module was difficult to track down, and even more difficult to resolve. Basically, all output that was retrived from the Video ROM was shifted right on the screen by what appeared to be 1.5 pixels. By studying the VGA Synchronization module and tedious experimentation, it was determined that there was a 3-clock-cycle delay from the time an address was applied to the Video ROM until the time the new data was available from the Video ROM. Thus, a counter was used to count clock cycles between the changing of the subpixel column input, and when the next change was 3 clock cycles away, this module would apply the next subpixel column to the Video ROM's address line, so that the data would be ready by the time the next subpixel was drawn.
    • The previous corrections caused the monitor output to be no longer shifted, but now the first 1.5 pixels were instead covered up by the wrong color. Eventually it was discovered that the first subpixel column was taking on the colors stored for subpixel column 31. Further study showed that the VGA Synchronization module was incrementing subpixel column all the way through 159. The lower eight bits of the binary representations of 31 and 159 are exactly the same, and this module was only sampling the lower seven bits at the time. Thus, the module was changed to receive all nine bits, and could test for values past the drawing range of 127 columns, and adjust the Video ROM address to include a subpixel column of 0 to anticipate the beginning of the next row.
    • The second problem was noticed once the modules were interconnected. Even while the system was in chooser mode, this module was recording the new color as different cursors were scrolled over before being selected. Thus, for example, if the user was drawing in red, and then switched into chooser mode to select Lift Pen, but scrolled over green and then blue before reach Lift Pen, then the color blue would be drawn to that pixel. Adding an input for detecting chooser_on allowed for a correction of this error.
    • The third problem was also noticed after interconnection. If the encoders were spun at a reasonably quick speed, certain pixels along a line would not get recorded, leaving a broken line on the screen, sometimes with as much as a 5-pixel gap. This was simply because the module was not recording the pen inputs often enough. Instead of recording during every vertical reset, the design was altered to record the current pen input at every horizontal sync, which occurs 480 times more often. This more than accounted for the gapping problems.
  • Panel Drawer
    • This module was originally developed and tested using a Basys development board, and it caused the monitor output to be distorted. Thus, even once the module was thought to be nearly completed, it wasn't until the modules were interconnected and loaded onto the Digilent board that it became clear what changes needed to be made. Primarily, the Basys board caused adjacent rows to be offset to the left or right.
    • Because the code had grown unexpectedly large while drawing more and more figures and adding more and more letters, the code was rewritten using a looped approach to compact the code. During this rewriting and debugging phase, the few remaining bugs in the previous code were worked out.
    • When the top-level design was connected, it was noticed that this module did not need a clock input, and the input was thus removed.

With all of these changes made, the design works just as expected. The design process of developing, testing, and verifying modules independently paid off greatly, allowing the work to be more easily divided and managed. When the modules were finally connected, they worked so reliably that little effort was required to debug and finalize the complete design. Because of this, the project was a success.