Microprocessor Notes V.1

For this project you will simulate and implement a simple four-bit microprocessor, named the 471X.  This machine is not intended to serve as a commercially available microprocessor, but rather is a simplified design for the purpose of teaching design principles.  We start by presenting what is called the assembly language programmer's view, also called the programmer's view, or computer architecture.  In writing assembly code, the programmer is at least aware of the following hardware features:

AC - Accumulator
A four bit register used to store intermediate results
PC - Program Counter
A four bit register used to refer to the next instruction in memory
ZF - Zero Flag Register
A single bit register that indicates a previous zero result
M( ) - Memory
Random access memory with 16 memory locations, each 4 bits wide
X - Index register
A register used to address memory
DSW - Data Switches
Four data input switches
LEDS - Display LEDs
Four data indicator LEDs

Address $C is used for input and output operations.  Address $C does not refer to an actual memory location, but input and output devices.  A read from address $C reads values from input switches.  A write to address $C assigns values to a register that controls LEDs. 

Source Code and Hand Assembly

Assembly language provides the means by which a programmer writes a program to manipulate the objects visible in the programmer's view of the hardware.  Assembly language is symbolic and provides the programmer a certain convenience over raw machine code.  Program assembly is a process of converting symbolic code to raw machine code.  In general terms, a semicolon ';' indicates the start of a comment.  A comment ends at the end of the text line.  Other than comment lines, a line has three fields:

Directives are commands that direct the action of assembling a program.  The directive ORG is used to set the current address value.  The prefix % indicates binary and $ indicates hexadecimal.  The directive DN is used to allocate a memory location for each value in the following list.  In the following example, the values $2, $A, and $3 are assigned to addresses $5, $6, and $7, respectively. The label Adx1 is assigned the address value $5.  The label Adx2 is assigned the address value $7. 

       ORG %0101
Adx1:  DN  $2, $A
Adx2:  DN  %0011

There are four so-called addressing modes.  In performing an instruction, the address used to access data in memory, to perform a read or write, is referred to as the effective address or EA.  With immediate addressing, data is stored in memory immediately after the opcode.  With direct addressing the effective address is the nibble in memory after the opcode.  With indexed addressing the X register contains the effective address, so the instruction is only one nibble long.  Implied addressing instructions do not access memory, hence do not have an effective address.  In the following summary table, it is assumed that A is the address of an instruction opcode.  EA is the corresponding effective address.

Addressing modes summary
Name  Mode  EA  Instruction Nibbles
Implied Imp - None - 1
Immediate Imm A+1 2
Direct Dir M(A+1) 2
Indexed Ind X 1

The following table lists all the supported instructions.  The 'Instruction' column lists the instructions in symbolic form.  Square brackets [ ] are used to imply direct addressing or indexed addressing.  The presence of X indicates indexed addressing.  An instruction having an operand, but not in square brackets uses immediate addressing.  The remaining instructions use implied addressing.

Instruction Summary
Instructions   Mode   Encoding   Description   Z-flag
lda val Imm %0000 val Load register A ±
lda [addx] Dir %0001 addx Load register A ±
lda [X] Ind %0010 Load register A ±
cla Imp %0011 Clear register A (load zero) 1
ada val Imm %0100 val Add a value to register A ±
ada [addx] Dir %0101 addx Add a value to register A ±
ada [X] Ind %0110 Add a value to register A ±
jmp addx Imm %0111 addx Load addx into PC ( jump ) --
ldx val Imm %1000 val Load register X ±
ldx [addx] Dir %1001 addx Load register X ±
stx [addx] Dir %1010 Store register X --
inx Imp %1011 Increment value in X ±
and val Imm %1100 val Bitwise AND with register A ±
sta [addx] Dir %1101 addx Store Register A to memory --
sta [X] Ind %1110 Store Register A to memory --
jmz addx Imm %1111 addx Load addx into PC when ZF = 1 --

The 'Z-flag' column summarizes how the Z flag is affected by each instruction result.  The symbols '±', '1', and '--' indicate that a change may occur, the Z flag will become high, or there will be no change.  The following example program summarizes details presented thus far.  In the following we will hand assemble the program into an executable form.

; first.asm - a first example
        ORG  $0
Start:  lda  [Val1]  ; Get a value
        ada  $2      ; add to it
        sta  [Val2]  ; store result
Done:   jmp  Done    ; done for now

        ORG  $A
Val1:   DN   %0101   ; one value
Val2:   DN   %0000   ; another value

We use a list file as a vehicle to hand assemble the code.  A list file is produced by inserting addresses and other data to the left of the source code.  The values inserted are written in hexadecimal.  The first value in a line is the address of the instruction opcode.  Each address is followed by an instruction nibble or nibbles.  To produce the corresponding list file, perform two passes.  Start by inserting the encoding for each instruction, but write a blank for each label reference. 

; first.asm - a first example
       ORG  $0
$0 1   Start:  lda  [Val1]  ; Get a value
$2 4 2         ada  $2      ; add to it
$4 D           sta  [Val2]  ; store result
$6 7   Done:   jmp  Done    ; done for now

       ORG  $A
$A B   Val1:   DN   %1011   ; one value
$B 0   Val2:   DN   %0000   ; another value

Blanks are filled in during the second pass.  The following is the result of the second pass.

; first.asm - a first example
       ORG  $0
$0 1 A Start:  lda  [Val1]  ; Get a value
$2 4 2         ada  $2      ; add to it
$4 D B         sta  [Val2]  ; store result
$6 7 6 Done:   jmp  Done    ; done for now

       ORG  $A
$A B   Val1:   DN   %1011   ; one value
$B 0   Val2:   DN   %0000   ; another value

We find that the labels are assigned the following address values:

The resultant binary file is a simple hexadecimal listing of the memory contents, in the listing file. The first column contains an addresses.  The second column contains the value stored at each corresponding address.  Program execution is assumed to start at address zero.  The following hexadecimal file is produced from the above example.  The last line in the file is called the 'End-of-file' record, which indicates the end of the file. 

0  0
1  A
2  4
3  2
4  D
5  B
6  7
7  6
A  B
B  0
FF 0

This second program is an example that you will use in your report write-ups.  The program is written to use each addressing mode at least once, and each of the jump instructions, once.

; test.asm - a counting test program
        ORG  $0
Start:  ldx  $C      ; I/O address
        lda  [$C]    ; read switches
Top:    sta  [X]     ; write LEDs
        ada  $F      ; subtract one
        jmz  Start   ; branch on zero
        jmp  Top     ; repeat loop

The Execution History

The assembly language programmer is aware of the registers, memory, memory mapped I/O, instructions, and the behavior of the instructions.  Assembly language is different from microcode in that the programmer is less aware of how the processor is actually implemented.  A so called execution history provides a list a register and memory values, before each is instruction actually executed.  An execution history is useful to the assembly language programmer as it provides a familiar view of the hardware.  The 'Previous' column indicates the prior instruction.

       Execution History

PC  AC   X  Z-flag M[Val2] Previous
$0  ??  ??     ?     $0    -none-
$2  $B  ??     0     $0    lda [Val1]
$4  $D  ??     0     $0    ada $2
$6  $D  ??     0     $D    sta [Val2]
$6  $D  ??     0     $D    jmp Done

Let's make two casual observations.  The example program never actually assigns a value to the X register.  Also, the last instruction causes an endless loop, this serves as a good place to stop the execution history.

The Simulator Program

The first project associated with the 471X processor involves writing a high level computer program that will simulate the microprocessor behavior.  Your simulator reads its initial memory from a file using the format described earlier.  Your simulator provides an interactive interface, reporting the register and memory contents before each instruction executes, and providing the user an opportunity to set the input switch values.  Your simulator might accept input values for each instruction, or allow the user to change the switch input value.  Your program also needs some mechanism to quit.  The user might enter a special value or command to quit execution.

Each microprocessor design has a prescribed set of steps that it follows to fetch an opcode, manage operand data, and execute the instruction.  In this regard a microprocessor is very much like a state machine.  In addition to the programmer visible registers, the microprocessor has two special internal registers.

IR - Instruction Register
A four bit latch register.  In using latches, data is immediately available.
TR - Temporary Register
A four bit register for intermediate data

Write your simulator so that in reading the source code, it is clearly organized in a manner, to match the steps illustrated in the following state diagram.  The following table provides further detail of how the fetch-execute cycle is performed.  The Move data step requires a comment.  Instructions that only involve reading data from memory (lda, ada, jmp, ldx, and, jmz) are called Rd type.  Instructions that eventually write data to memory (stx, sta) are called Wr type.

Figure 1: Fetch-execute cycle
  1. Fetch opcode step

  2. Read operand step

  3. Move data step

  4. Execute the instruction

First Report Outline

In writing your report, feel free to use your browser to copy figures from this document.  The following list should help you get started in in writing the report for the simulation part of this project:
Test and Results

Implementing the Design

When a computer engineer refer to the architecture of a computer, he or she means the view that an assembly language programmer sees.  An analogy is that the architecture of a piano is what the musician interacts with, namely the keys and foot pedals.  The details of how the piano is constructed, called the implementation is a different issue.  Consider that once the skill of piano playing is learned, a musician can play any piano.  Likewise, one microprocessor architecture can have any number of implementations.

The figure below outlines our processor data path.  The figure is said to be implementation oriented as it illustrates aspects unique to this design.  Here is where we take the cover off and expose details not visible to the assembly language programmer.  One detail is that the so-called program counter (PC) is not a counter at all.  While the PC is used with counting, it is the arithmetic logic unit (ALU) that increments the PC value each time.  The PC itself is just an ordinary register. 

Figure 2: Processor data path

The following outlines the major components in the data path.

The AC, PC, TR, X, and Z registers are parallel loadable.  When enabled, each register loads new data following a rising clock edge.  The instruction register IR is similar but is constructed with transparent latches. 
Multi-Way Multiplexer
Figure 3 illustrates the basic unit used in a three way multiplexer, using a one-hot selection encoding ( S[1:3] ).  The multiplexer is easily changed to accommodate two selections and can be duplicated for various bus widths.  With all selection lines low, the output is low.

Figure 3: Three way multiplexer
Arithmetic Logic Unit
The arithmetic logic unit (ALU) performs the following operations.  The ALU produces a combinational logic signal Zres that is high whenever the ALU output Z is zero.  The ZF register loads the value Zres to reflect the result of certain instructions.

Data Busses
A memory system with separate read and write data busses is used.  With only 16 system addresses, it is hard to justify constructing a single true data bus.  Our memory system is constructed using on-chip resources in the FPGA.  The bus DataBus1 conveys data from the memory system and DataBus2 conveys data being written to the memory system. 

Using the Data Path

After a brief moment of reflection consider how the data path is actually used.  The components are directed by a state machine to perform the fetch-execute cycle, described earlier.  This behavior is neatly expressed in an event table.  Lets reconsider the program 'first.asm'.

; first.asm - a first example
       ORG  $0
$0 1 A Start:  lda  [Val1]  ; Get a value
$2 4 2         ada  $2      ; add to it
$4 D B         sta  [Val2]  ; store result
$6 7 6 Done:   jmp  Done    ; done for now

       ORG  $A
$A B   Val1:   DN   %1011   ; one value
$B 0   Val2:   DN   %0000   ; another value

An event table lists the settled values in a sequential logic circuit, for each clock period.  A blank entry indicates no assignment.  Hence, a value is written when an assignment is made, even if the assignment does not produce a change in value.  In reading an event table, it is important to keep in mind what signals are produced by registers and what other signals are produced by latches or combinational logic.  The state of a register constructed with flip-flops updates its state following a rising-clock edge.  A transparent latch however reflects its current input when enabled. 

Time State    PC  IR  TR  AC M[Val2]  Comments

 0T+ Fetch    $0  $1  ??  ??   $0     lda  [Val1]
 1T+ Operand  $1               
 2T+ Move     $2      $A       
 3T+ Execute          $B       
 4T+ Fetch        $4      $B          ada  $2
 5T+ Operand  $3               
 6T+ Execute  $4      $2       
 7T+ Fetch        $D      $D          sta  [Val2]
 8T+ Operand  $5               
 9T+ Move     $6      $B       
10T+ Fetch        $7           $D     jmp  Done
11T+ Operand  $7               
12T+ Execute  $8      $6       
13T+ Fetch    $6  $7                  jmp  Done
14T+ Operand  $7               
15T+ Execute  $8      $6       
      -- The Cycle Repeats --

The write to memory address $B requires mention, it is assumed here that synchronous memory based on flip-flops is being used. 

State Machine Encoding

For this project, design the fetch-execute cycle as a one-hot encoded state machine.  Use the state variables Q1, Q2, Q3, and Q4, expressed as the ordered quad Q(1:4), with the following state assignment:
State Name      Encoding Q(1:4)
Fetch Operand  =     1000
Get Operand    =     0100
Move Data      =     0010
Execute        =     0001

To design the state machine we will use an intermediary logic circuit, referred to as the instruction decoder that receives the instruction register (IR) value and produces five flags:

Producing Control Signals

Each component in the data path has signal lines used to control its behavior.  Each parallel loadable register has an enable that enables the parallel load behavior.  Each multiplexer has select inputs used to control which signal is passed.  The ALU has control lines used to select an ALU function.  Once the data path and fetch-execucte cycle state machine are designed, the remainder of the project involves designing the logic that produces all the needed control lines.  Consider the PC register as one example, its control line is named PC_ENA. 

PC_ENA = Q1 + Q2 + Q4 · IR3' · IR2 · IR1 · IR0
                 + Q4 · IR3 · IR2 · IR1 · IR0 · ZF

Alternatively, you can use a logic network using a binary decoder to produce control lines.  Such an approach produces equivalent logic.


Final Report Outline

The following outline is for the implementation phase of the project.  In writing your report, feel free to use your browser to copy figures from this document.  The following list should help you get started in in writing the report for the simulation part of this project:
Test and Results


EE336 Final Project Sign Off Sheet

After demonstrating the final version of your project, make sure to have a member of the teaching staff sign and date the following:

Student Name:

Demonstrated the final project:

Copyright Notice

This lab handout is written for the EE336 class - Digital Devices.  Copyright is reserved by the author, but copies of this document may be made for educational use as-is, provided that this statement remains attached.

Original Author: Jonathan Hill (jmhill@mail.hartford.edu)
Copyright Date: Thu Mar 13 16:44:20 EST 2003
Last Modified By: Jonathan Hill (jmhill@mail.hartford.edu)
Last Modified Date: Thu May 1 17:20:50 EDT 2003