Lectures‎ > ‎

Week12

The Ultimate Guide to Project05

Here are some additional notes on the components you need to build, the components you need to use, and a general overview of how it should all fit together.

Advice: please try to do everything yourself following the Project05 description, the notes from class, the Digital manual, and this guide. If you get help from other students you won't be challenging yourself to really learn how everything works. Plus, once you get used to Digital and thinking in terms of digital logic, it is really fun.

First, your animation circuit will consist of a top-level circuit. I called my "animation_main.dig". In this top-level circuit you should have the following components:
  • A 16-bit Counter (you build from scratch)
  • A ROM for your images (use the Digital ROM)
  • An 8-to-1 1bit multiplexor for selecting individual bits from a row (you build from scratch)
  • A Graphic RAM component for displaying the animation (use the Digital Graphics RAM)
  • A Control Component (you build from scratch)

The 16-bit Counter

The 16-bit counter is built from a 16-bit Adder and 16-bit Register. The counter should have a CLK and CLR input and a COUNT output (note you will want your COUNT output to come directly from the 16-bit register and not from the Adder output like we did in class. This is because you want the counter to start at 0. 

You build the 16-bit Adder as a Ripple Carry Adder from 1-bit Full Adders. You can make an 16-bit adder using 16 Full Adders, or your can build it using four 4-bit Adders. Your 16-bit Adder can have a Carry In (Cin) and a Carry Out (Cout), but you will set the Cin to 0 in your counter and you can ignore Cout. The 16-bit Register is made from 16 D Flip-Flops. Each D Flip-Flop is made using a D Latch and the D Latch is made using an SR Latch. Your D Latch should have CLK and CLR  (clear) inputs in addition to D input and Q output. 

Make sure you test subcomponents before putting them into other components. Note I've found the following tips helpful in creating symbols in Digital:
  • Order and orient your inputs and outputs in the canvas as you would like them to appear in the final symbol when you add it to another circuit.
  • You can use the "Edit->Circuit specific settings" to change the width and height of the final symbol, which can make it easier to to see the names of the inputs and outputs
    • Use the "Basic" tab to set the width of the symbol.
    • Use the "Advanced" tab and select "Shape" to be "Layout" and then you can change the height as well. This will also force the symbol to use the "Layout" mode when you bring it in to other circuits.

The Image ROM

We are going to use the Digital ROM component in order to store our images. For the basic requirement of 4 8x8 image in which we are creating black and white images you will need a ROM configured with 8 data bits and 5 address bits. The data bits determines the size of a row. The 5 address bits determines the number of rows the ROM will have. In our case, we need 4 images with 8 rows each. This means we need 4 x 8 = 32 rows. To represent 32 different values, we need 5 bits because 2^5 = 32. To construct your images you can do it by hand as follows:
  • For each image, write down the binary representation of each row of the image. Use a 1 to represent a black pixel and 0 to represent a white pixel. Note, colors are possible, but that will be extra credit (see below for more info).
  • For each row of the image, convert the 8-bit binary value to a hexadecimal value.
  • Use the hexadecimal when editing the contents of the ROM. Your row data should be in order. The first 8 rows have the 8 values for the first image, the second 8 rows have the the 8 values for the second image, and so on.
To use the ROM you need to know the following:
  • The sel input should always be set to 1. You can use a 1-bit constant value or the supply voltage.
  • The A (address) input is 5 bits and it allows you to select a row from the ROM. 0 is the first row of the first image, 1 is the second row of the first image, 8 is the first row of the second image and so on.
  • The D output is 8 bits and represents a complete image row.
  • Note the trick here is to figure out which 5 bits you need from the counter output to select a row. Hint: once you selected a row you will need to use some subset of the counter bits to select an individual pixel value from the row (and a row has 8 bits).
Here is an example set of images I created for my animation:

0b00000000 0x00
0b00000000 0x00
0b00000000 0x00
0b00011000 0x18
0b00011000 0x18
0b00000000 0x00
0b00000000 0x00
0b00000000 0x00

0b00000000 0x00
0b00000000 0x00
0b00111100 0x3C
0b00100100 0x24
0b00100100 0x24
0b00111100 0x3C
0b00000000 0x00
0b00000000 0x00

0b00000000 0x00
0b01111110 0x7E
0b01000010 0x42
0b01000010 0x42
0b01000010 0x42
0b01000010 0x42
0b01111110 0x7E
0b00000000 0x00

0b11111111 0xFF
0b10000001 0x81
0b10000001 0x81
0b10000001 0x81
0b10000001 0x81
0b10000001 0x81
0b10000001 0x81
0b11111111 0xFF


Click on the image above to see how it animates in Digital.

The 8-to-1 1-bit Multiplexor

As described above you will need to implement and use a 8-to-1 1-bit Multiplexor (MUX) to select an individual bit from the row. This means you will use a splitter to split the 8-bit value into 8 1-bit values and connect each one of these 1-bit values to one of the 8 inputs on the 8-to-1 MUX.  An 8-to-1 1-bit MUX has 8 1-bit inputs and a 3 bit selector (S). The value on S select one of the 8 input values to be the 1 bit output for the MUX.

In class, we built a 2-to-1 1-bit MUX:


It turns out you can easily build a 4-to-1 1-bit MUX using 3 2-to-1 1-bit MUXes like this:


You can then build a an 8-to-1 1-bit MUX using two 4-to-1 1-bit MUXes and a 2-to-1 1-bit MUX, but I will leave that for you to figure out.

One other hint. The row values come out such that the first pixel is in bit position 7 (8th bit), the second pixel is in bit position 6 (7th bit), and so on. To make sure you get the right bit for the right position in the Graphics RAM you can invert the S (selector) input to the MUX, which will access the bits from the row in reverse order (which is what we want).

The Graphics RAM

You can find the Digital Graphics RAM component in "Components->Memory->RAM".


We want to configure the Graphics RAM as follows:
  • Data bit: 1
  • Width in pixels: 8
  • Height in pixels: 8
Recall the Graphics RAM has two buffers. The first buffer is is addressed 0 to 63. The second buffer is addressed 64 to 127. The addresses work like this: 0 is the first pixel in the top row in the first buffer, 1 is the second pixel in top row of the first buffer, etc. 8 is the first pixel in the 2nd row of the first buffer, 9 is the second pixel in the 2nd row of the first buffer. Then 64 is the first pixel in the top row of the second buffer.

The inputs of the Graphics RAM work as follows:
  • A is 7-bit input value because it needs to represent 2^7 = 128 different values. 64 for the first buffer and 64 for the second buffer.
  • str is set high (1) to write the input value on D into the RAM. We will always set str to 1.
  • C is the clock input and this should be connected to the same clock as the the Counter in your top-level (main) circuit.
  • ld is set to high (1) to load a value from RAM. We are not going to be loading values, so you want to set ld to 0.
  • B selects which buffer to show. If B is 0 it shows the first buffer, if B is 1 is shows the second buffer.
    • If you want to write to the first buffer first, then you should show the second buffer while writing to the first buffer (this can be determined by your control unit).
  • D is both input and output, but we will only use it as input. The value represent the pixel value (0 is white, 1 is black). You can use larger data bits to use a larger value for pixels which allows you to specify colors (see the Digital manual). However, if you want to use colors your ROM contents will be quite a bit different because instead of 1 bit for each pixel, you may need 4 or 8 bits per pixel.

The Control Unit

The control unit will be used to determine how to set many of the inputs to the different components at the top-level. Here are the component inputs we need to control:
  • The A (address) input on the Image ROM
  • The S (selector) input on the 8-to-1 MUX for pixel selection
  • The A (address) and B (buffer) inputs on the Graphics RAM
All of these values can be directly determined from the Counter output. So, your control unit will have one input (the 16-bit Counter Value) and 4 outputs that control each of the inputs described above.

You can determine the control outputs by using splitters and gates. You don't need any other component. This means you really need to understand how the different parts of the counter can be used to drive the different control outputs. This will be the hardest part to figure out. You can do really cool things with the splitter.

Digital Tips

Here are some tips I've learned while using digital. I'll try to add more as I learn more:

  • When editing the content of a ROM you can expand the window so it is easier to see and access the individual values in the ROM.

Comments