Skip to content

MikroLeo project files (schematic, PCB, assembler, emulator/debugger, circuit simulation file, documentation, example of programs etc). MikroLeo is a 4-bit microcomputer developed mainly for educational purposes and distributed for free under open-source licenses.

License

Notifications You must be signed in to change notification settings

edson-acordi/4bit-microcomputer

Repository files navigation

Star Badge

MikroLeo



4-bit Didactic Microcomputer

The hardware is finished and working.
However, it needs exhaustive testing over a long period to see if the hardware will fail when operating at full speed. It implies that if the hardware fails, the maximum clock speed must be reduced, for example, to 2.5 MHz.

This project was developed mainly for educational purposes.

I hope it will be a good learning platform for anyone who likes electronics, computers and programming.

Since my first attempts, many efforts have been made to make this project real.

It is aimed at students, enthusiasts, hackers, professors and anyone who wants to understand or improve their knowledge of electronics and learn how a simple computer works. In addition, it is also an attempt to rescue the story about the beginning of the development of integrated circuits and computers on a single chip, to demonstrate the capabilities that these machines had at that time.

It is a fully open-source hardware and software project that can be built at home. Only the printed circuit board (PCB) needs to be produced by some company.

For the next steps, an important thing is to make good documentation for MikroLeo!

Support this project!
Help to promote and disseminate the knowledge.
Copyright (C) 2020-2024 MikroLeo Devs


The KiCad project files have been uploaded!

1-Download KiCad Project

2-Download Gerber Files

3-Download the schematic diagram (pdf file)

4-Download Bill of Materials (pdf file)
   └─>Components list made by @vguttmann at the Mouser Electronics store


A Python program to generate machine code has been uploaded

Python code to "compile" asm files

Windows executable (.exe) to "compile" asm files


How to transfer compiled program to MikroLeo

Download documentation (pdf file)


The Arduino program to transfer a compiled program to MikroLeo

Code (Arduino IDE)


Main Features:

  • Implements a 4 bit CPU
  • 2k x 16 Program Memory (up to 4k)
  • 2k x 4 RAM (up to 4k)
  • 4 Output Ports (16 outputs)
  • 4 Input Ports (16 inputs)
  • Single Cycle Instruction/RISC
  • Harvard Architecture
  • 3 execution modes:
    • step by step
    • 3MHz (precise time base)
    • adjustable - low clock speed ( $\approx$ 1 Hz - 200 Hz)
  • No MPU/MCU or complex chips
  • No microcode
  • No stack
  • Indirect addressing to facilitate the implementation of subroutines
  • Program memory implemented with RAM to easy programming
  • It can be programmed using physical input switches or via Arduino/Esp32
  • It accepts 300 and 600 mils memories (for those with old DIP versions)
  • Supercapacitor or battery to keep the program in RAM (for low power version)
  • Built with 74HCTxxx integrated circuits for low power consumption and compatibility with TTL circuits
  • All parts are through-hole for easy assembly
  • All control signals, registers and the program counter are available through the pin header connectors
  • Dual layer Single board with 295.9mm x 196.9mm

MikroLeo Architecture

Note that some buffers are used to allow viewing the contents of registers at any time, since this project is mainly intended for educational purposes.
Reset Vector: 0x000

The MikroLeo Instruction Set

Although MikroLeo has only 20 instructions, using the AMODE bit (b14) and the modifier bits (b13:b12), it is possible to encode 64 combinations of instructions, as can be seen below.

Instruction Set explanation and examples

In binary, the Instruction Word is coded as,

ROMH (Most significant byte of program memory):

b15 b14 b13 b12 b11 b10 b9 b8
MICRO2_IN AMODE MOD1 MOD0 MICRO3 MICRO2 MICRO1 MICRO0

ROML (Least significant byte of program memory):

b7 b6 b5 b4 b3 b2 b1 b0
MAddr3 MAddr2 MAddr1 MAddr0 Operand3 Operand2 Operand1 Operand0

$\text{\small\textcolor{brown}{- Note: b15 = bit15 ... b0 = bit0}}$

Below is more detailed information about the instruction word,

Instruction Set Description

LDI - Load with Immediate
Description: Loads the operand value into a register.
Registers: ACC, RA, RB or RC
Operation: Register <─ Operand

Instruction Word ROMH Instruction Affected Flags
0x00Xn 0x00 LDI ACC,n ZF
0x10Xn 0x10 LDI RA,n -
0x20Xn 0x20 LDI RB,n -
0x30Xn 0x30 LDI RC,n -

Note:
The operand (immediate) is represented by the letter "n".
'X' (in capital letter) means it doesn't matter.
'x' (in lowercase) is used to represent a hexadecimal number.

Examples:

Instruction Word Instruction Comment
0x0005 LDI ACC,5 Load ACC with operand n
0x1006 LDI RA,6 Load RA with operand n
0x2007 LDI RB,7 Load RB with operand n
0x300a LDI RC,10 Load ACC with operand n

The MAddr nibble is not used with this instruction, so it is left at 0.
The Instruction Word, for example, for LDI RA,6 is coded as,

0x1006
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 6
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 0
  └─────> Most significant Nibble => HiNB[b15:b12] = 1

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0001 0000 0000 0110
  ┆    ┆    ┆    └──> Operand = 6
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 0 (OPCode)
  └─────────────────> HiNB = 1 (MICRO2_IN = 0, AMODE = 0, MOD = 1)

NAND - bitwise Nand
Description: Performs the bitwise Nand operation between ACC with (Operand n, RA, RB or RAM).
The result is stored in ACC.
Operations:
ACC <─ ACC NAND Operand
ACC <─ ACC NAND Register
ACC <─ ACC NAND RAM

Instruction Word ROMH Instruction Affected Flags
0x01Xn 0x01 NAND ACC,n ZF
0x11XX 0x11 NAND ACC,RA ZF
0x21XX 0x21 NAND ACC,RB ZF
0x31mn 0x31 NAND ACC,@RAM ZF
0x71XX 0x71 NAND ACC,@R ZF

Note:
The RAM address for @RAM is pointed by RC:MAddr:LAddr.
The RAM address for @R is pointed by RC:RB:RA.
The MAddr is represented by the letter "m".

Examples:

Instruction Word Instruction Comment
0x0105 NAND ACC,5 NAND operation between the accumulator and the operand and
stores it in ACC
0x1100 NAND ACC,RA NAND operation between the accumulator and register RA and
stores it in ACC
0x2100 NAND ACC,RB NAND operation between the accumulator and register RB and
stores it in ACC
0x310a NAND ACC,@0x0a NAND the contents of the RAM address with ACC and stores it
in ACC. In this case, the RAM address = RC:0:a
0x7100 NAND ACC,@R NAND the contents of the RAM address with ACC and stores it
in ACC. In this case, the RAM address = RC:RB:RA

The Instruction Word, for example, for NAND ACC,5 is coded as,

0x0105
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 5
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 1
  └─────> Most significant Nibble => HiNB[b15:b12] = 0

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0000 0001 0000 0101
  ┆    ┆    ┆    └──> Operand = 5
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 1 (OPCode)
  └─────────────────> HiNB = 0 (MICRO2_IN = 0, AMODE = 0, MOD = 0)

LDW - Load from RAM Memory
Description: Loads the contents of RAM into ACC.
Operation: ACC <─ RAM

Instruction Word ROMH Instruction Affected Flags
0x02mn 0x02 LDW ACC,@RAM ZF
0x42XX 0x42 LDW ACC,@R ZF

Examples:

Instruction Word Instruction Comment
0x023b LDW ACC,@0x3b Loads the contents of the RAM address (RC:3:b) in ACC
0x4200 LDW ACC,@R Loads the contents of the RAM address (RC:RB:RA) in ACC

The Instruction Word, for example, for LDW ACC,@0x3b is coded as,

0x023b
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = b
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 3
  ┆└────> Third Nibble => MICRO[b11:b8] = 2
  └─────> Most significant Nibble => HiNB[b15:b12] = 0

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0000 0010 0011 1011
  ┆    ┆    ┆    └──> Operand = b
  ┆    ┆    └───────> MAddr = 3
  ┆    └────────────> MICRO = 2 (OPCode)
  └─────────────────> HiNB = 0 (MICRO2_IN = 0, AMODE = 0, MOD = 0)

LDA - Load Accumulator
Description: Loads the contents of a register into the ACC.
Registers: RA, RB or RC
Operation: ACC <─ Register

Instruction Word ROMH Instruction Affected Flags
0x13XX 0x13 LDA RA ZF
0x23XX 0x23 LDA RB ZF
0x33XX 0x33 LDA RC ZF

Note: 'X' means it doesn't matter.

Examples:

Instruction Word Instruction Comment
0x1300 LDA RA Load into ACC the content of RA
0x2300 LDA RB Load into ACC the content of RB
0x3300 LDA RC Load into ACC the content of RC

The MAddr/LAddr nibble is not used with this instruction, so it is left at 0.

The Instruction Word, for example, for LDA RA is coded as,

0x1300
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 0
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 3
  └─────> Most significant Nibble => HiNB[b15:b12] = 1

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0001 0011 0000 0000
  ┆    ┆    ┆    └──> Operand = 0 (For this instruction, it doesn't matter)
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 3 (OPCode)
  └─────────────────> HiNB = 1 (MICRO2_IN = 0, AMODE = 0, MOD = 1)

OUTA - Send to OUTA output port
Description: Sends the operand/Register or RAM value to the OUTA output port.
Operations:
OUTA <─ Operand
OUTA <─ ACC
OUTA <─ RA
OUTA <─ RAM

Instruction Word ROMH Instruction Affected Flags
0x04Xn 0x04 OUTA n -
0x14XX 0x14 OUTA ACC -
0x24XX 0x24 OUTA RA -
0x34mn 0x34 OUTA @RAM -
0x74XX 0x74 OUTA @R -

Note:
The RAM address for @RAM is pointed by RC:MAddr:LAddr.
The RAM address for @R is pointed by RC:RB:RA.
The MAddr is represented by the letter "m".

Examples:

Instruction Word Instruction Comment
0x0405 OUTA 5 Sends the operand to the OUTA port
0x1400 OUTA ACC Sends the ACC to the OUTA port.
0x2400 OUTA RA Sends the RA to the OUTA port.
0x342a OUTA @0x2a Sends the content of RAM to the OUTA port. In this case, the
RAM address = RC:2:a
0x7400 OUTA @R Sends the content of RAM to the OUTA port. In this case, the
RAM address = RC:RB:RA

The Instruction Word, for example, for OUTA ACC is coded as,

0x1400
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 0
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 4
  └─────> Most significant Nibble => HiNB[b15:b12] = 1

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0001 0100 0000 0000
  ┆    ┆    ┆    └──> Operand = 0
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 4 (OPCode)
  └─────────────────> HiNB = 1 (MICRO2_IN = 0, AMODE = 0, MOD = 0)

OUTB - Send to OUTB output port
Description: Sends the operand/Register or RAM value to the OUTB output port.
Operations:
OUTB <─ Operand
OUTB <─ ACC
OUTB <─ RA
OUTB <─ RAM

Instruction Word ROMH Instruction Affected Flags
0x05Xn 0x05 OUTB n -
0x15XX 0x15 OUTB ACC -
0x25XX 0x25 OUTB RA -
0x35mn 0x35 OUTB @RAM -
0x75XX 0x75 OUTB @R -

Note:
The RAM address for @RAM is pointed by RC:MAddr:LAddr.
The RAM address for @R is pointed by RC:RB:RA.
The MAddr is represented by the letter "m".

Examples:

Instruction Word Instruction Comment
0x0507 OUTB 7 Sends the operand to the OUTB port
0x1500 OUTB ACC Sends the ACC to the OUTB port.
0x2500 OUTB RA Sends the RA to the OUTB port.
0x35f1 OUTB @0xf1 Sends the content of RAM to the OUTB port. In this case, the
RAM address = RC:f:1
0x7500 OUTB @R Sends the content of RAM to the OUTB port. In this case, the
RAM address = RC:RB:RA

The Instruction Word, for example, for OUTB 7 is coded as,

0x0507
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 7
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 5
  └─────> Most significant Nibble => HiNB[b15:b12] = 0

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0001 0101 0000 0111
  ┆    ┆    ┆    └──> Operand = 7
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 5 (OPCode)
  └─────────────────> HiNB = 0 (MICRO2_IN = 0, AMODE = 0, MOD = 0)

OUTC - Send to OUTC output port
Description: Sends the operand/Register or RAM value to the OUTC output port.
Operations:
OUTC <─ Operand
OUTC <─ ACC
OUTC <─ RA
OUTC <─ RAM

Instruction Word ROMH Instruction Affected Flags
0x06Xn 0x06 OUTC n -
0x16XX 0x16 OUTC ACC -
0x26XX 0x26 OUTC RA -
0x36mn 0x36 OUTC @RAM -
0x76XX 0x76 OUTC @R -

Note:
The RAM address for @RAM is pointed by RC:MAddr:LAddr.
The RAM address for @R is pointed by RC:RB:RA.
The MAddr is represented by the letter "m".

Examples:

Instruction Word Instruction Comment
0x0607 OUTC 0xf Sends the operand to the OUTC port
0x1600 OUTC ACC Sends the ACC to the OUTC port.
0x2600 OUTC RA Sends the RA to the OUTC port.
0x3683 OUTC @0x83 Sends the content of RAM to the OUTC port. In this case, the
RAM address = RC:8:3
0x7600 OUTC @R Sends the content of RAM to the OUTC port. In this case, the
RAM address = RC:RB:RA

The Instruction Word, for example, for OUTC @0x83 is coded as,

0x3683
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 3
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 8
  ┆└────> Third Nibble => MICRO[b11:b8] = 6
  └─────> Most significant Nibble => HiNB[b15:b12] = 3

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0011 0110 1000 0011
  ┆    ┆    ┆    └──> Operand = 3
  ┆    ┆    └───────> MAddr = 8
  ┆    └────────────> MICRO = 6 (OPCode)
  └─────────────────> HiNB = 3 (MICRO2_IN = 0, AMODE = 0, MOD = 3)

LDR - Loads a Register with the Accumulator.
Description: Load the contents of the ACC into a register.
Registers: RA, RB or RC
Operation: Register <─ ACC

Instruction Word ROMH Instruction Affected Flags
0x17XX 0x17 LDR RA -
0x27XX 0x27 LDR RB -
0x37XX 0x37 LDR RC -

Note: 'X' means it doesn't matter.

Examples:

Instruction Word Instruction Comment
0x1700 LDR RA Load into RA the content of ACC
0x2700 LDR RB Load into RB the content of ACC
0x3700 LDR RC Load into RC the content of ACC

The MAddr/LAddr nibble is not used with this instruction, so it is left at 0.

The Instruction Word, for example, for LDR RA is coded as,

0x1700
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 0
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 7
  └─────> Most significant Nibble => HiNB[b15:b12] = 1

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0001 0111 0000 0000
  ┆    ┆    ┆    └──> Operand = 0 (For this instruction, it doesn't matter)
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 7 (OPCode)
  └─────────────────> HiNB = 1 (MICRO2_IN = 0, AMODE = 0, MOD = 1)

CMP - Compare ACC
Description: Performs the comparison between ACC with (Operand n, RA, RB or RAM).
The comparison is like a Subtraction, but it doesn't change the ACC. The comparison result can be checked by Flags.
Operations:
ACC - Operand
ACC - Register
ACC - RAM

Instruction Word ROMH Instruction Affected Flags
0x08Xn 0x08 CMP ACC,n CF,ZF
0x18XX 0x18 CMP ACC,RA CF,ZF
0x28XX 0x28 CMP ACC,RB CF,ZF
0x38mn 0x38 CMP ACC,@RAM CF,ZF
0x78XX 0x78 CMP ACC,@R CF,ZF

Note:
The RAM address for @RAM is pointed by RC:MAddr:LAddr.
The RAM address for @R is pointed by RC:RB:RA.
The MAddr is represented by the letter "m".

Examples:

Instruction Word Instruction Comment
0x0801 CMP ACC,1 Compare ACC with operand n
0x1800 CMP ACC,RA Compare ACC with register RA
0x2800 CMP ACC,RB Compare ACC with register RB
0x38c3 CMP ACC,@0xc3 Compare ACC with RAM address. In this case, the RAM
address = RC:c:3
0x7800 CMP ACC,@R Compare ACC with RAM address. In this case, the RAM
address = RC:RB:RA

The Instruction Word, for example, for CMP ACC,1 is coded as,

0x0801
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 1
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 8
  └─────> Most significant Nibble => HiNB[b15:b12] = 0

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0000 1000 0000 0001
  ┆    ┆    ┆    └──> Operand = 1
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 8 (OPCode)
  └─────────────────> HiNB = 0 (MICRO2_IN = 0, AMODE = 0, MOD = 0)

OUTD - Send to OUTD output port
Description: Sends the operand/Register or RAM value to the OUTD output port.
Operations:
OUTD <─ Operand
OUTD <─ ACC
OUTD <─ RA
OUTD <─ RAM

Instruction Word ROMH Instruction Affected Flags
0x09Xn 0x09 OUTD n -
0x19XX 0x19 OUTD ACC -
0x29XX 0x29 OUTD RA -
0x39mn 0x39 OUTD @RAM -
0x79XX 0x79 OUTD @R -

Note:
The RAM address for @RAM is pointed by RC:MAddr:LAddr.
The RAM address for @R is pointed by RC:RB:RA.
The MAddr is represented by the letter "m".

Examples:

Instruction Word Instruction Comment
0x090b OUTD 0xb Sends the operand to the OUTD port
0x1900 OUTD ACC Sends the ACC to the OUTD port.
0x2900 OUTD RA Sends the RA to the OUTD port.
0x39c3 OUTD @0xc3 Sends the content of RAM to the OUTD port. In this case, the
RAM address = RC:c:3
0x7900 OUTD @R Sends the content of RAM to the OUTD port. In this case, the
RAM address = RC:RB:RA

The Instruction Word, for example, for OUTD @R is coded as,

0x7900
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 0
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = 9
  └─────> Most significant Nibble => HiNB[b15:b12] = 7

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0111 1001 0000 0000
  ┆    ┆    ┆    └──> Operand = 0 (For this instruction, it doesn't matter)
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = 9 (OPCode)
  └─────────────────> HiNB = 7 (MICRO2_IN = 0, AMODE = 1, MOD = 3)

STW - Store in RAM Memory
Description: Stores the contents of the ACC in RAM.
Operation: RAM <─ ACC

Instruction Word ROMH Instruction Affected Flags
0x0Amn 0x0A STW @RAM,ACC -
0x4AXX 0x4A STW @R,ACC -

Examples:

Instruction Word Instruction Comment
0x0A1f STW @0x1f,ACC Stores the contents of the ACC in RAM (address RC:1:f)
0x4A00 STW @R,ACC Stores the contents of the ACC in RAM (address RC:RB:RA)

The Instruction Word, for example, for STW @0x1f,ACC is coded as,

0x0A1f
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = f
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 1
  ┆└────> Third Nibble => MICRO[b11:b8] = A
  └─────> Most significant Nibble => HiNB[b15:b12] = 0

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0000 1010 0001 1111
  ┆    ┆    ┆    └──> Operand = f
  ┆    ┆    └───────> MAddr = 1
  ┆    └────────────> MICRO = A (OPCode)
  └─────────────────> HiNB = 0 (MICRO2_IN = 0, AMODE = 0, MOD = 0)

SUB - Subtract from accumulator
Description: Subtracts from the accumulator the content of (Operand n, RA, RB or RAM) and stores the result in the accumulator.
Operation:
ACC <─ ACC - Operand
ACC <─ ACC - Register
ACC <─ ACC - RAM

Instruction Word ROMH Instruction Affected Flags
0x0BXn 0x0B SUB ACC,n CF,ZF
0x1BXX 0x1B SUB ACC,RA CF,ZF
0x2BXX 0x2B SUB ACC,RB CF,ZF
0x3Bmn 0x3B SUB ACC,@RAM CF,ZF
0x7BXX 0x7B SUB ACC,@R CF,ZF

Examples:

Instruction Word Instruction Comment
0x0B0f SUB ACC,0xf Subtract from ACC the operand n and store the result in ACC
0x1B00 SUB ACC,RA Subtract from ACC the Register RA and store the result in ACC
0x2B00 SUB ACC,RB Subtract from ACC the Register RA and store the result in ACC
0x3B9a SUB ACC,@0x9a Subtract from ACC the RAM address. In this case, the RAM
address = RC:9:a
0x7B00 SUB ACC,@R Subtract from ACC the RAM address. In this case, the RAM
address = RC:RB:RA

The Instruction Word, for example, for SUB ACC,RB is coded as,

0x2B00
  ┆┆┆└──> Least significant Nibble => Operand[b3:b0] = 0
  ┆┆└───> Second Nibble => MAddr[b7:b4] = 0
  ┆└────> Third Nibble => MICRO[b11:b8] = B
  └─────> Most significant Nibble => HiNB[b15:b12] = 2

Also, the instruction word (in binary) to be manually programmed into MikroLeo using physical switches is,

0010 1011 0000 0000
  ┆    ┆    ┆    └──> Operand = 0 (For this instruction, it doesn't matter)
  ┆    ┆    └───────> MAddr = 0 (For this instruction, it doesn't matter)
  ┆    └────────────> MICRO = B (OPCode)
  └─────────────────> HiNB = 2 (MICRO2_IN = 0, AMODE = 0, MOD = 2)

...

Basic Documentation

- MikroLeo has four Registers
ACC - Accumulator (4 bit) - Stores the result of logical and arithmetic operations. Moreover, ACC stores data that is read from or written to RAM.
RA - 4 bit General purpose Register (also used for addressing).
RB - 4 bit General purpose Register (also used for addressing).
RC - 4 bit Special purpose Register used for addressing.

- Two Flags
Flags can only be checked by conditional jump instructions (JPC and JPZ).

CF - Carry Flag - It is Set (CF=1) by ADD Instruction if it produces a carry or by SUB/CMP instruction if it results in a borrow.
ZF - Zero Flag - It is affected by operations that modify the contents of the ACC and by CMP instruction. It is Set (ZF=1) if the result of the last operation was zero.

Example of how CF and ZF are Set:

LDI ACC,1    ;Load the operand value into the ACC accumulator.
ADD ACC,0xF  ;Performs the addition between the accumulator and the operand and stores the
             ;result in the accumulator.

This code does it,

   0001
+  1111
-------  
 1 0000  
 ↓   ↓  
CF  ACC

As the value zero is written to ACC, ZF=1.

- Addressing Modes

Immediate

In immediate addressing, the operand (n) is contained in the lower nibble of the instruction (b3:b0), and it is denoted by Operand, LAddr or OPR.

Example 1:

LDI ACC,1    ;Load the operand value into the ACC accumulator.

Example 2:

LDI ACC,0xA  

Example 3:

NAND ACC,0   ;Performs the NAND operation between the accumulator and the operand value and
             ;stores the result in the accumulator.

Example 4:

OUTA 0xF     ;Sends the operand value to the OUTA output port.

Example 5:

CMP ACC,0    ;Performs the comparison between the accumulator and the operand.

Example 6:

SUB ACC,1    ;Performs the subtraction between the accumulator and the operand and stores
             ;the result in the accumulator.

Example 7:

ADD ACC,5    ;Performs the addition between the accumulator and the operand and stores the
             ;result in the accumulator.

Register Direct

In this mode, the operand must be one of the four registers (ACC, RC, RB, RA). Thus, the contents of the lower and medium nibble of the instruction (MAdrr, b7:b4 and LAddr, b3:b0) do not matter. Note that in the LDR instruction, the operand (ACC) is implied. LDR stands for load the Register Rx with ACC, being x={A,B,C}. In the LDA instruction, the operand must be one of the three registers (RC, RB, RA). LDA stands for load the accumulator with one of Rx Registers. Note that in register direct addressing mode, data can be read from or written to a register.

Example 1:

LDR RA     ;Loads the value of the ACC accumulator into the RA register.

Example 2:

LDR RB     ;Loads the value of the ACC accumulator into the RB register.

Example 3:

LDA RA     ;Loads the value from the RA Register into the ACC accumulator.

Example 4:

LDA RC     ;Loads the value from the RC Register into the accumulator ACC.

Register Indirect + Absolute

In this addressing mode, the RC Register points to the high address (b11:b8). The medium (MAddr) and low (LAddr) nibble of the instruction, point to the medium and low address, respectively.

The final address is composed by RC:MAddr:LAddr.

For example, if:

RC = 3  
MAddr = 2  
LAddr = 1  

The address to be accessed is 321h.
In the MikroLeo python assembler, absolute addresses (MAddr:LAddr) are indicated by an @.

Example 1:

LDI RC,1       ;Loads the operand value into the RC Register.
OUTA @0xF4     ;Sends the contents of the RAM address pointed to by RC:MAddr:LAddr to output
               ;port A, in this case, the RAM address is RC:MAddr:LAddr = 1F4h.

Example 2:

LDI RC,3       ;Loads the operand value into the RC Register.
ADD ACC,@0xFC  ;Sum the contents of the RAM address pointed to by RC:MAddr:LAddr with ACC
               ;and stores it in ACC. In this case, the RAM address is RC:MAddr:LAddr = 3FCh.

Example 3:

LDI RC,1       ;Loads the operand value into the RC Register.
JPI @0x23      ;Jumps to the specified label. In this case, the label address is
               ;RC:MAddr:LAddr = 123h.

Example 4:

LDI RC,2       ;Loads the operand value into the RC Register.
CMP ACC,0      ;Compares the contents of ACC with the operand. Is ACC equal to 0?
JPZ @0x34      ;Jumps to the specified label if ZF=1 (ACC = 0). In this case, the label
               ;address is PCH:MAddr:LAddr = PCH:34h. JPZ does not affect PCH.

Example 5:

LOOP:  
  LDI RC,3       ;Loads the operand value into the RC Register.
  STW @0x21,ACC  ;Stores the contents of the accumulator in the RAM address pointed by
                 ;RC:MAddr:LAddr, in this case, the RAM address is RC:MAddr:LAddr = 321h.
  LDI RC,>LOOP   ;Gets the address of the label, as this code changes the contents of the
                 ;Register RC.
  JPI LOOP       ;Jumps to the specified label.

Example 6:

LOOP:  
  LDI RC,3       ;Loads the operand value into the RC Register.
  LDW ACC,@0x21  ;Loads the contents of the RAM address pointed by RC:MAddr:LAddr in the
                 ;accumulator, in this case, the RAM address is RC:MAddr:LAddr = 321h.
  LDI RC,>LOOP   ;Gets the address of the label, as this code changes the contents of the
                 ;Register RC.
  JPI LOOP

Example 7:

LOOP:  
  LDI RC,4       ;Loads the operand value into the RC Register.
  CMP ACC,@0x32  ;Compares the contents of ACC with the contents of the RAM address
                 ;pointed by RC in this case, the RAM address is RC:MAddr:LAddr = 432h.
                 ;Is ACC equal to @432h?
  JPZ LOOP       ;Jumps to the specified label if ZF=1 (ACC = @432h).

Register Indirect

In this addressing mode, the RC Register points to the high address (b11:b8). Likewise, the RB Register points to the medium Address (MA) while the RA Register points to the low Address (LA). Note that the contents of the lower and medium nibble of the instruction (MAddr, b7:b4 and LAddr, b3:b0) do not matter.

The final address is composed by RC:RB:RA.

For example, if:

not matter.
RC = 3  
RB = 2  
RA = 1  

The address to be accessed is 321h.
In MikroLeo's python assembler, indirect register addresses (RC:RB:RA) are indicated by an @R.

Example 1:

LDI RC,1       ;Loads the operand value into the RC Register.
LDI RB,0xF
LDI RA,4
OUTA @R        ;Sends the contents of the RAM address pointed to by RC:RB:RA to output
               ;port A,
               ;in this case, the RAM address is RC:RB:RA = 1F4h.

Example 2:

LDI RC,3       ;Loads the operand value into the RC Register.
LDI RB,0xF
LDI RA,0xC
ADD ACC,@R     ;Sum the contents of the RAM address pointed to by RC:RB:RA with ACC
               ;and stores it in ACC. In this case, the RAM address is RC:RB:RA = 3FCh.

Example 3:

LDI RC,1       ;Loads the operand value into the RC Register.
LDI RB,2
LDI RA,3
JPI @R         ;Jumps to the specified label. In this case, the label address is
               ;RC:RB:RA = 123h.

Example 4:

LDI RC,2       ;Loads the operand value into the RC Register.
LDI RB,3
LDI RA,4
CMP ACC,0      ;Compares the contents of ACC with the operand. Is ACC equal to 0?
JPZ @R         ;Jumps to the specified label if ZF=1 (ACC = 0). In this case, the
               ;label address is PCH:RB:RA = PCH:34h. JPZ does not affect PCH.

Example 5:

LOOP:  
  LDI RC,3       ;Loads the operand value into the RC Register.
  LDI RB,2
  LDI RA,1
  STW @R,ACC     ;Stores the contents of the accumulator in the RAM address pointed by
                 ;RC:RB:RA, in this case, the RAM address is RC:RB:RA = 321h.
  LDI RC,>LOOP   ;Gets the address of the label, as this code changes the contents of
                 ;the Register RC.
  JPI LOOP       ;Jumps to the specified label.

Example 6:

LOOP:  
  LDI RC,3       ;Loads the operand value into the RC Register.
  LDI RB,2
  LDI RA,1
  LDW ACC,@R     ;Loads the contents of the RAM address pointed by RC:RB:RA in the
                 ;accumulator, in this case, the RAM address is RC:RB:RA = 321h.
  LDI RC,>LOOP   ;Gets the address of the label, as this code changes the contents of
                 ;the Register RC.
  JPI LOOP

Example 7:

LOOP:  
  LDI RC,4       ;Loads the operand value into the RC Register.
  LDI RB,3
  LDI RA,2
  CMP ACC,@R     ;Compares the contents of ACC with the contents of the RAM address
                 ;pointed by RC in this case, the RAM address is RC:RB:RA = 432h.
                 ;Is ACC equal to @432h?
  JPZ LOOP       ;Jumps to the specified label if ZF=1 (ACC = @432h).

Assembler Compiler

Released! See examples how to use...

How to transfer compiled program to MikroLeo

Download documentation (pdf file)

Emulator

In progress...🚧

Demo

MikroLeo in action!

A simple program to make a LED sequencer using the output ports.

Sequential_LEDs_small.mp4

A simple program to initialize an LCD.

LCD_HD44780_small.mp4

Building your own MikroLeo

...:soon:

Contribution guidelines

...:soon:

Pictures

Simulation of the MikroLeo circuit (Made with "Digital"):
Digital is free, open source and cross-platform software with a nice interface for digital logic design and circuit simulation.

Breadboard:

PCB (KiCad 3D viewer):
To carry out the project, the KiCad software was used, an excellent and powerful free and open-source tool for printed circuit board (PCB) designers.
Size: 295.9mm x 196.9mm

A simple seven-segment display interface (the PCB has a layout thought for educational purposes, that's why it got big),
Size: 88.65mm x 141.mm

PCB Prototype:


Development stages

  • - Bibliographic research
  • - Architecture definition
  • - Circuit design
  • - Circuit simulation
  • - Prototype assembly on breadboard
  • - Printed circuit board design
  • - Prototype assembly on PCB
  • - Final Tests

History and Motivation

Since the time I took an 8086 assembly language programming course and took digital electronics and microprocessors classes in college, this project has been something I've always wanted to do. I'm fascinated by electronics, computers and programming!

The project started in 2020, and the first usable version was completed on April 20, 2020.

Initially, the development of the project used the Logisim-Evolution, and later it was migrated to the Digital.

Some sources of inspiration can be seen at:

http://www.sinaptec.alomar.com.ar/2018/03/computadora-de-4-bits-capitulo-1.html
https://www.bigmessowires.com/nibbler/
https://gigatron.io/
https://eater.net/
https://apollo181.wixsite.com/apollo181/specification
https://www.megaprocessor.com/
http://www.mycpu.eu/
https://minnie.tuhs.org/Programs/CrazySmallCPU/index.html

Dedication

I dedicate this project to my beloved son, Leonardo Pimentel Acordi.

Acknowledgements

The authors would like to thank:

  • The IFPR (Instituto Federal do Paraná), CNPq (Conselho Nacional de Desenvolvimento Científico e Tecnológico) and Fundação Araucária for the partial funding and support for this project.

  • The RENESAS (https://www.renesas.com/br/en) for sending me memory samples for tests with MikroLeo.

  • All people from the Github community and externals who support this project.

Sponsor

Starting with revision 1.02A (which will be finalized soon) MikroLeo has gained a sponsor for the printed circuit board, the PCBWAY company, a serious company that produces high-quality PCBs.
https://www.pcbway.com/

Authors

Edson Junior Acordi
Matheus Fernando Tasso
Carlos Daniel de Souza Nunes

License

Hardware: Licensed under CERN-OHL-S v2 or any later version
https://ohwr.org/cern_ohl_s_v2.txt

Software: Licensed under GNU GPL v3
https://www.gnu.org/licenses/gpl-3.0.txt

Documentation: Licensed under CC BY-SA 4.0
https://creativecommons.org/licenses/by-sa/4.0/

Note:
As this project is intended for educational purposes, I have decided to use the CERN-OHL-S license for hardware to ensure that it is always free, contributing, promoting and disseminating the essential knowledge. As such, all hardware derived from it will also be open source!
Likewise, for the software, the GNU GPL license was used.

Contact

Note: If you have any questions, please consider opening a discussion first, as your question may be helpful to others. If you want to report a bug, please open an issue.
You can also contact me via email: [email protected]

Visitor count

About

MikroLeo project files (schematic, PCB, assembler, emulator/debugger, circuit simulation file, documentation, example of programs etc). MikroLeo is a 4-bit microcomputer developed mainly for educational purposes and distributed for free under open-source licenses.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published