A Logisim simpleCPUv1a

Home

To better understand how a processor works we need to be able to visualise its internal operations, how the Fetch, Decode and Execute phases are implemented in hardware, how data flows through this hardware as an instruction is executed. One way of doing this is to have lots of LEDs :), as seen on bread-board version of the SimpleCPUv1a: (Link). This is not the most reliable, or practical method, as over time wires have the habit of falling out :(, however, fortunately we live in an age of open-source software, so we have access to a range of digital simulation tools: (Link). One commonly used program used to teach digital logic design is Logisim (Link) and the later updated version Logisim-evolution (Link). These software packages are specifically designed for education/teaching and aim to simplify their operation and allow a user to observe how signals change within the hardware as it operates. This is in contrast with industrial software packages such as Xilinx ISE (Link), (Download), where more specialised software features are needed to ensure timing closer of digital designs i.e. that when a design is implemented in actual hardware it will operated as intended. These additional software tools are essential when implementing designs in hardware e.g. FPGA (Link), however, this does come with the cost of increased software complexity, which is not always desirable when teaching the basics. Below is a brief description of the key features of Logisim taken from its home page:

"Logisim is an educational tool for designing and simulating digital logic circuits. With its simple toolbar interface and simulation of circuits as you build them, it is simple enough to facilitate learning the most basic concepts related to logic circuits. With the capacity to build larger circuits from smaller subcircuits, and to draw bundles of wires with a single mouse drag, Logisim can be used (and is used) to design and simulate entire CPUs for educational purposes." - http://www.cburch.com/logisim/

Therefore, i decided to try out some of these free educational digital logic simulators, to see if these could help support simpleCPU teaching. I decided to start with Logisim i.e. the original version, shown in figure 1. Why this version, rather than the newer Logisim-evolution, simple, the older version was simpler to install :). Soooo say hello to the newest addition to the simpleCPU family, the Logisim simpleCPUv1a, if you would like to download a copy please use this link: (Link), you can also download the test program used to initialise its memory here: (Link).

Figure 1 : Logisim

Table of Contents

Software
SimpleCPU v1a
Multiplexers
Arithmetic and Logic Unit
Registers and counters
Control logic
Memory
Computer and testing

Software

To install Logisim in Linux, well in my version of Linux Mint, its a simple matter of running the command:

sudo apt-get install logisim

A big advantage of using Logisim is that there is a large online community, as its used in a number of schools and universities, you only need to do a quick Google and you will find examples and advice for most questions. In addition to that there are also a number of nice video tutorials on Youtube, therefore, there is a short learning curve when compared to other software packages. Personally, i found it quick to pickup, however, below is a list of things i stumbled over when learning this software:

For teaching, for simple circuits such as the simpleCPUv1a, Logisim makes sense, as you get a very good overview of the system state through the colour changes in the schematics (circuits), you quickly see what signals are active on each clock cycle etc. However, for larger designs that require longer simulation runs, or more complex testing i.e. a mix of low-level hardware and high-level simulation models you will need to use a different software package, but i should add Logisim was never designed for such tasks, so this is an unfair comment, rather its just something to keep in mind.

SimpleCPU version 1a

Figure 2 : simpleCPU version 1a block diagram

This Logisim implementation of the simpleCPUv1a follows the same design approach as the previous Xilinx implementations i.e. functionality is broken down into a series of sub-components, which are then used to build larger components, which in turn form the key building blocks of the processor's architecture, as shown in figure 2.

Multiplexers

Figure 3 : multiplexer - MUX_2_8

Rather than implementing this components from basic logic gates i.e. AND, OR and NOT (Link) i decided to build this component as a separate circuit using the predefined bit-multiplexer. However, Logisim does also allow you to customise the multiplexer primitive component (plexer library folder) i.e. you can define a byte multiplexer, without having to draw this circuit. The reason why i decided to implement this component this way was that i was playing around with the splitter component (wiring library folder), to help me understand how busses are split into bits, and how bits are joined into busses, otherwise the built in component would be the better solution i.e. less components to simulate.

Arithmetic and Logic Unit

Figure 4 : ALU

A slight departure from the original design (Link), can you spot the differences in figure 4? Logisim supports ADD and SUB primitive components, so i used these to save a bit of drawing time :) i.e. rather than implementing an ADDSUB component from raw logic gates: half-adder, full-adder, ripple-adder etc, as we did in the FPGA implementation. I did implement the bitwise-AND component, as shown in figure 5.

Figure 5 : bitwise AND - AND_2_8

Registers and ring counter

Figure 6 : Register - 4bit

Figure 7 : Register - 8bit

Figure 8 : Register - 16bit

I took the same basic approach as for the FPGA implementation (Link), building a 4bit register from D-type flip-flops, then using this to produce the 8bit and 16bit registers, as shown in figures 6 - 8. You may ask: why didn't you use the Logisim built in register component (memory library folder), well, i confess i did not spot it :), yes that would have been a better solution, but can be argued this approach shows design considerations / component reuse etc.

Figure 9 : Program counter

The program counter (PC) shown in figure 9, and the ring-counter shown in figure 10, are also base on the same designs as the FPGA (Link). The PC again uses the built-in ADD component. Logisim does support a primitive binary counter component, however, i don't think this can be setup as a loadable counter as needed in the PC. is

Figure 10 : Ring counter

Control logic

Figure 11 : control logic

The control logic shown in figure 11 is slightly different to that used in the FPGA (Link), as i spotted that i had "on purpose" duplicated some logic :), not sure how i missed that, but there was some redundant logic, so i removed it for this implementation. The onehot decoder shown in figure 12 and the zero detect logic shown in figure 13 remain that same.

Figure 12 : onehot decoder

Figure 13 : zero detect

Memory

Figure 14 : memory

I thought this one could be a pain i.e. that i would need to use tri-state buffers as used in the bread-board version of the simpleCPU (Link), but Logisim does support dual port memory, shown in figure 14, so all was fine. I only had one small misunderstand regarding the control pins: str, clk, ld, but was good after reading the documentation. To initialise this memory you can simply use a text file i.e. right-click on it and select Load image. This allows you to select a text file, the format used is just a sequential list of values i.e. start from address 0 onwards, as shown below (middle section removed to save space). Note, you can also manually change values in memory by selecting Edit contents.

v2.0 raw
0001
0003
0007
000F
001F
003F
007F
00FF
1001
1003

...

705E
3000
904B
00FF
1001
A04E
00FF
3000
A051
8052
00FF
1001

To generate this machine-code i could have updated the python based assembler (Link), however, decided to take the easier option and write some shell script to adjust one of the existing object file formats i.e. the .mem file, script shown below:

#!/bin/sh
echo "v2.0 raw" > data

cat code.mem | while read line
do
  data=`echo $line | cut -d' ' -f2 | rev`
  echo $data >> data
done

Compter

Figure 15 : computer

Initially i had the simpleCPUv1a and the memory in a top level schematic/circuit, however, this meant that all you could see whilst simulating were the busses, which wasn't that informative. Therefore, i moved the memory onto the same circuit as the processor, as shown in figure 15. To further aid in the visualisation of data on the processor i added lots of LEDs :). To test this simulation model i used the normal test code as shown below. A short video of Logisim running this code is available here: (Link)(Youtube), do double check the ACC value against the values listed in the comments, i think it looks ok, but as always you never find all the bugs when you are looking, they always pop out of the woodwork later :).

###################
# INSTRUCTION-SET #
###################

# INSTR   IR15 IR14 IR13 IR12 IR11 IR10 IR09 IR08 IR07 IR06 IR05 IR04 IR03 IR02 IR01 IR00
# MOVE    0    0    0    0    X    X    X    X    K    K    K    K    K    K    K    K
# ADD     0    0    0    1    X    X    X    X    K    K    K    K    K    K    K    K
# SUB     0    0    1    0    X    X    X    X    K    K    K    K    K    K    K    K
# AND     0    0    1    1    X    X    X    X    K    K    K    K    K    K    K    K

# LOAD    0    1    0    0    X    X    X    X    A    A    A    A    A    A    A    A
# STORE   0    1    0    1    X    X    X    X    A    A    A    A    A    A    A    A
# ADDM    0    1    1    0    X    X    X    X    A    A    A    A    A    A    A    A
# SUBM    0    1    1    1    X    X    X    X    A    A    A    A    A    A    A    A

# JUMPU   1    0    0    0    X    X    X    X    A    A    A    A    A    A    A    A
# JUMPZ   1    0    0    1    X    X    X    X    A    A    A    A    A    A    A    A
# JUMPNZ  1    0    1    0    X    X    X    X    A    A    A    A    A    A    A    A
# JUMPC   1    0    1    1    X    X    X    X    A    A    A    A    A    A    A    A        -- NOT IMPLEMENTED

########
# CODE #
########

start:
  move 1            # acc = 1
  move 3            # acc = 3
  move 7            # acc = 7
  move 15           # acc = 15    F
  move 31           # acc = 31   1F
  move 63           # acc = 63   3F
  move 127          # acc = 127  7F
  move 255          # acc = 255  FF 

  add 1             # acc = 0     0
  add 3             # acc = 3     3
  add 7             # acc = 10    A
  add 15            # acc = 25   19
  add 31            # acc = 56   38
  add 63            # acc = 119  77  
  add 127           # acc = 246  F6
  add 255           # acc = 245  F5

  sub 1             # acc = 244  F4 
  sub 3             # acc = 241  F1
  sub 7             # acc = 234  EA
  sub 15            # acc = 219  DB
  sub 31            # acc = 188  BC
  sub 63            # acc = 125  7D
  sub 127           # acc = 254  FE
  sub 255           # acc = 255  FF

  and 255           # acc = 255  FF
  and 127           # acc = 127  7F
  and 63            # acc = 63   3F
  and 31            # acc = 31   1F
  and 15            # acc = 15    F
  and 7             # acc = 7     7
  and 3             # acc = 3     3
  and 1             # acc = 1     1

  move 1            # acc = 1     1
  store A           # M[87] = 1
  move 3            # acc = 3     3
  store B           # M[88] = 3
  move 7            # acc = 7     7
  store C           # M[89] = 7
  move 15           # acc = 15    F
  store D           # M[90] = 15
  move 31           # acc = 31    1F
  store E           # M[91] = 31
  move 63           # acc = 63    3F
  store F           # M[92] = 63
  move 127          # acc = 127   7F      
  store G           # M[93] = 127
  move 255          # acc = 255   FF
  store H           # M[94] = 255

  load A            # acc = M[87] = 1     1
  load B            # acc = M[88] = 3     3
  load C            # acc = M[89] = 7     7
  load D            # acc = M[90] = 15    F
  load E            # acc = M[91] = 31   1F
  load F            # acc = M[92] = 63   3F
  load G            # acc = M[93] = 127  7F
  load H            # acc = M[94] = 255  FF

  addm A            # acc = 0     0
  addm B            # acc = 3     3
  addm C            # acc = 10    A
  addm D            # acc = 25   19 
  addm E            # acc = 56   38
  addm F            # acc = 119  77
  addm G            # acc = 246  F6
  addm H            # acc = 245  F5

  subm A            # acc = 244  F4
  subm B            # acc = 241  F1
  subm C            # acc = 234  EA
  subm D            # acc = 219  DB
  subm E            # acc = 188  BC
  subm F            # acc = 125  7D
  subm G            # acc = 254  FE
  subm H            # acc = 255  FF

  and 0             # acc = 0
  jumpz b1          # TAKEN
  move 255          # set acc to 255 if error

b1:
  add 1             # acc = 1
  jumpnz b2         # TAKEN
  move 255          # set acc to 255 if error

b2:
  and 0             # acc = 0
  jumpnz b3         # FALSE
  jumpu b4          # unconditional jump
b3:
  move 255          # set acc to 255 if error

b4:
  add 1             # acc = 1
  jumpz b5          # FALSE
  jumpu b6          # unconditional jump
b5:
  move 255          # set acc to 255 if error

b6:
  jumpu start       # jump back to start

A:
  .data 0
B:
  .data 0
C:
  .data 0
D:
  .data 0
E:
  .data 0
F:
  .data 0
G:
  .data 0
H:
  .data 0

WORK IN PROGRESS

Creative Commons Licence

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

Contact email: mike@simplecpudesign.com

Back