LmCast :: Stay tuned in

Show HN: E80: an 8-bit CPU in structural VHDL

Recorded: Jan. 20, 2026, 10:03 a.m.

Original Summarized

GitHub - Stokpan/E80: A simple CPU in VHDL for educational purposes

Skip to content

Navigation Menu

Toggle navigation

Sign in

Appearance settings

PlatformAI CODE CREATIONGitHub CopilotWrite better code with AIGitHub SparkBuild and deploy intelligent appsGitHub ModelsManage and compare promptsMCP RegistryNewIntegrate external toolsDEVELOPER WORKFLOWSActionsAutomate any workflowCodespacesInstant dev environmentsIssuesPlan and track workCode ReviewManage code changesAPPLICATION SECURITYGitHub Advanced SecurityFind and fix vulnerabilitiesCode securitySecure your code as you buildSecret protectionStop leaks before they startEXPLOREWhy GitHubDocumentationBlogChangelogMarketplaceView all featuresSolutionsBY COMPANY SIZEEnterprisesSmall and medium teamsStartupsNonprofitsBY USE CASEApp ModernizationDevSecOpsDevOpsCI/CDView all use casesBY INDUSTRYHealthcareFinancial servicesManufacturingGovernmentView all industriesView all solutionsResourcesEXPLORE BY TOPICAISoftware DevelopmentDevOpsSecurityView all topicsEXPLORE BY TYPECustomer storiesEvents & webinarsEbooks & reportsBusiness insightsGitHub SkillsSUPPORT & SERVICESDocumentationCustomer supportCommunity forumTrust centerPartnersOpen SourceCOMMUNITYGitHub SponsorsFund open source developersPROGRAMSSecurity LabMaintainer CommunityAcceleratorArchive ProgramREPOSITORIESTopicsTrendingCollectionsEnterpriseENTERPRISE SOLUTIONSEnterprise platformAI-powered developer platformAVAILABLE ADD-ONSGitHub Advanced SecurityEnterprise-grade security featuresCopilot for BusinessEnterprise-grade AI featuresPremium SupportEnterprise-grade 24/7 supportPricing

Search or jump to...

Search code, repositories, users, issues, pull requests...

Search

Clear

Search syntax tips

Provide feedback


We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.
You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

Stokpan

/

E80

Public

Notifications
You must be signed in to change notification settings

Fork
0

Star
12

A simple CPU in VHDL for educational purposes

License

GPL-3.0 license

12
stars

0
forks

Branches

Tags

Activity

Star

Notifications
You must be signed in to change notification settings

Code

Issues
0

Pull requests
0

Discussions

Actions

Projects
0

Security

Uh oh!

There was an error while loading. Please reload this page.


Insights

Additional navigation options

Code

Issues

Pull requests

Discussions

Actions

Projects

Security

Insights

Stokpan/E80

 mainBranchesTagsGo to fileCodeOpen more actions menuFolders and filesNameNameLast commit messageLast commit dateLatest commit History8 CommitsAssemblerAssembler  GHDLGHDL  GowinGowin  InstallerInstaller  ModelSimModelSim  QElectroTechQElectroTech  QuartusQuartus  VHDLVHDL  VivadoVivado  .gitattributes.gitattributes  .gitignore.gitignore  LICENSELICENSE  README.mdREADME.md  View all filesRepository files navigationREADMEGPL-3.0 licenseE80 CPU
A simple CPU in VHDL, developed from scratch for my undergraduate thesis to provide all three characteristics of a Constructionist Microworld:

Low floor, as it depends purely on textbook-based, structural VHDL components, and offers a toolchain installer for one-click simulation.
High ceiling, as it supports all typical instructions found in Computer Architecture textbooks, including stack operations & subroutine calling.
Wide walls, as it was designed for compatibility with a variety of platforms, as seen below, and provides the complete source material (from the CFG grammar to EDA project files) for study and modification.

This makes it easy to use, capable of running pretty complex and realistic programs, and can be used in multiple lab or classroom scenarios.

Feature
Description

Dependencies
ieee.std_logic_1164 (no arithmetic libraries)

Execution
Single-cycle

Word Size
8-bit

Buses
8-bit data, 8-bit address, 16-bit instruction

Instruction size
Variable (1 or 2 words)

RAM
Multiport (2R, 1R/W), addressable at 0x00-0xFE

Register file
Multiport (1R/W, 1R, 1W), 8x8-bit

Registers
6 general purpose (R0-R5), Flags (R6), SP (R7)

Stack
Full descending (Stack Pointer init = 0xFF)

Architecture
Load/Store, register-register

Addressing
Immediate, direct, register, register-indirect

Input
8-bit Memory Mapped at 0xFF (1x8 DIP switch)

Output
Flags, Registers, PC, Clock (3x8 LEDs)

Assembly syntax
Hybrid of ARM, x86, and textbook pseudocode

Assembler
ISO C99 (standard library, stdin I/O)

Simulated on
GHDL/GTKWave & ModelSim via one-click scripts

Editor
SciTE, with syntax coloring & one-click run

Synthesized on
Quartus Lite, Gowin Education, Vivado Standard

Tested on
Tang Primer 25K, Altera Cyclone IV

ISA cheatsheet
n : 8-bit immediate value or memory address.
r,r1,r2 : 3-bit register address (R0 to R7), eg. MOV R3,R5 translates to
0b(00011000 0rrr0rrr) ≡ 0b(00011000 00110101) or 0x(18rr) ≡ 0x(1835).
[x] : Memory at address x < 255, [255] = DIP input.
PC : Program counter, initialized to 0 on reset.
SP : Register R7, initialized to 255 on reset.
--SP Decrease SP by 1, and then read it.
SP++ Read SP, and then increase it by 1.
Flags : Register R6 = [CZSVH---] (see ALU.vhd)
C = Carry out (unsigned arithmetic) or shifted-out bit.
Z = Zero, set to 1 when result is 0.
S = Sign, set to the most significant bit of the result.
V = Overflow (signed arithmetic), or sign bit flip in L/RSHIFT
H = Halt flag, (freezes PC).

+----------+----------+-------+---------------+-----------------------+-------+
| Instr1 | Instr2 | Hex | Mnemonic | Description | Flags |
+----+----------+----------+-------+---------------+-----------------------+-------+
| 1 | 00000000 | | 00 | HLT | PC ← PC | H |
| 2 | 00000001 | | 01 | NOP | | |
| 3 | 00000010 | nnnnnnnn | 02 nn | JMP n | PC ← n | |
| 4 | 00000011 | 00000rrr | 03 0r | JMP r | PC ← r | |
| 5 | 00000100 | nnnnnnnn | 04 nn | JC n | if C=1, PC ← n | |
| 6 | 00000101 | nnnnnnnn | 05 nn | JNC n | if C=0, PC ← n | |
| 7 | 00000110 | nnnnnnnn | 06 nn | JZ n | if Z=1, PC ← n | |
| 8 | 00000111 | nnnnnnnn | 07 nn | JNZ n | if Z=0, PC ← n | |
| 9 | 00001010 | nnnnnnnn | 0A nn | JS n | if S=1, PC ← n | |
| 10 | 00001011 | nnnnnnnn | 0B nn | JNS n | if S=0, PC ← n | |
| 11 | 00001100 | nnnnnnnn | 0C nn | JV n | if V=1, PC ← n | |
| 12 | 00001101 | nnnnnnnn | 0D nn | JNV n | if V=0, PC ← n | |
| 13 | 00001110 | nnnnnnnn | 0E nn | CALL n | PC+2 → [--SP]; PC ← n | |
| 14 | 00001111 | | 0F | RETURN | PC ← [SP++] | |
| 15 | 00010rrr | nnnnnnnn | 1r nn | MOV r,n | r ← n | ZS |
| 16 | 00011000 | 0rrr0rrr | 18 rr | MOV r1,r2 | r1 ← r2 | ZS |
| 17 | 00100rrr | nnnnnnnn | 2r nn | ADD r,n | r ← r+n | CZSV |
| 18 | 00101000 | 0rrr0rrr | 28 rr | ADD r1,r2 | r1 ← r1+r2 | CZSV |
| 19 | 00110rrr | nnnnnnnn | 3r nn | SUB r,n | r ← r+(~n)+1 | CZSV |
| 20 | 00111000 | 0rrr0rrr | 38 rr | SUB r1,r2 | r1 ← r1+(~r2)+1 | CZSV |
| 21 | 01000rrr | nnnnnnnn | 4r nn | AND r,n | r ← r&n | ZS |
| 22 | 01001000 | 0rrr0rrr | 48 rr | AND r1,r2 | r1 ← r1&r2 | ZS |
| 23 | 01010rrr | nnnnnnnn | 5r nn | OR r,n | r ← r|n | ZS |
| 24 | 01011000 | 0rrr0rrr | 58 rr | OR r1,r2 | r1 ← r1|r2 | ZS |
| 25 | 01100rrr | nnnnnnnn | 6r nn | XOR r,n | r ← r^n | ZS |
| 26 | 01101000 | 0rrr0rrr | 68 rr | XOR r1,r2 | r1 ← r1^r2 | ZS |
| 27 | 01110rrr | nnnnnnnn | 7r nn | ROR r,n | r>>n (r<<8-n) | ZS |
| 28 | 01111000 | 0rrr0rrr | 78 rr | ROR r1,r2 | r1>>r2 (r1<<8-r2) | ZS |
| 29 | 10000rrr | nnnnnnnn | 8r nn | STORE r,[n] | r → [n] | |
| 30 | 10001000 | 0rrr0rrr | 88 rr | STORE r1,[r2] | r1 → [r2] | |
| 31 | 10010rrr | nnnnnnnn | 9r nn | LOAD r,[n] | r ← [n] | ZS |
| 32 | 10011000 | 0rrr0rrr | 98 rr | LOAD r1,[r2] | r1 ← [r2] | ZS |
| 33 | 10100rrr | | Ar | LSHIFT r | (C,r)<<1; V ← S flip | CZSV |
| 34 | 10110rrr | nnnnnnnn | Br nn | CMP r,n | SUB, discard result | CZSV |
| 35 | 10111000 | 0rrr0rrr | B8 rr | CMP r1,r2 | SUB, discard result | CZSV |
| 36 | 11000rrr | nnnnnnnn | Cr nn | BIT r,n | AND, discard result | ZS |
| 37 | 11010rrr | | Dr | RSHIFT r | (r,C)>>1; V ← S flip | CZSV |
| 38 | 11100rrr | | Er | PUSH r | r → [--SP] | |
| 39 | 11110rrr | | Fr | POP r | r ← [SP++] | |
+----+----------+----------+-------+---------------+-----------------------+-------+

Notes

ROR R1,R2 rotates R1 to the right by R2 bits. This is equivalent to left rotation by 8-R2 bits.
Carry and oVerflow flags are updated by arithmetic and shift instructions, except ROR.
Shift instructions are logical; Carry flag = shifted bit and the Overflow flag is set if the sign bit is changed.
The Sign and Zero flags are updated by CMP, BIT, and any instruction that modifies a register, except for stack-related instructions.
Explicit modifications of the FLAGS register take precedence over normal flag changes, eg. OR FLAGS, 0b01000000 sets Z=1 although the result is non-zero.
The HLT instruction sets the H flag and freezes the PC, thereby stopping execution in the current cycle. Setting the Halt flag by modifying the Flags (R6) register will stop execution on the next cycle.
Comparison of unsigned numbers via the Carry flag can be confusing because SUB R1,R2 is done via standard adder logic (R1 + ~R2 + 1). See the flags cheatsheet below.

Flags cheatsheet
+------+-----------------------------+----------------------+
| Flag | Signed | Unsigned |
+---------+------+-----------------------------+----------------------+
| ADD a,b | C=1 | | a+b > 255 (overflow) |
| | C=0 | | a+b ≤ 255 |
| | V=1 | a+b ∉ [-128,127] (overflow) | |
| | V=0 | a+b ∈ [-128,127] | |
| | S=1 | a+b < 0 | a+b ≥ 128 (if C=0) |
| | S=0 | a+b ≥ 0 | a+b < 128 (if C=0) |
+---------+------+-----------------------------+----------------------+
| SUB a,b | C=1 | | a ≥ b |
| or | C=0 | | a < b (overflow) |
| CMP a,b | V=1 | a-b ∉ [-128,127] (overflow) | |
| | V=0 | a-b ∈ [-128,127] | |
| | S=1 | a < b | a-b ≥ 128 (if C=1) |
| | S=0 | a ≥ b | a-b < 128 (if C=1) |
+---------+------+-----------------------------+----------------------+

Assembly cheatsheet
string : ASCII with escaped quotes, eg. "a\"b\"c" is quoted a"b"c.
label : Starts from a letter, may contain letters, numbers, underscores.
number : -128 to 255 no leading zeroes, bin (eg. 0b0011), hex (eg. 0x0A).
val : Number or label.
csv : Comma-separated numbers and strings.
reg : Register R0-R7 or FLAGS (alias of R6) or SP (alias of R7).
op1/op2 : Reg or val (flexible operand).
[op2] : Memory at address op2 (or DIP input if op2=0xFF).

+----------------------+----------------------------------------------------+
| Directive | Description |
+----------------------+----------------------------------------------------+
| .TITLE "string" | Sets VHDL output title to string |
| .LABEL label number | Assigns a number to a label |
| .SIMDIP value | Sets the DIP input to value (for simulation only) |
| .DATA label csv | Appends csv at label address after program space |
| .FREQUENCY deciHertz | Set frequency to deciHertz (1-1000) |
+----------------------+----------------------------------------------------+

+----------------------+----------------------------------------------------+
| Instruction | Description |
+----------------------+----------------------------------------------------+
| label: | Marks the address of the next instruction |
| HLT | Sets the H flag and halts execution |
| NOP | No operation |
| JMP op1 | Jump to op1 address |
| JC n | Jump if Carry (C=1) |
| JNC n | Jump if Not Carry (C=0) |
| JZ n | Jump if Zero (Z=1) |
| JNZ n | Jump if Not Zero (Z=0) |
| JS n | Jump if Sign (S=1) |
| JNS n | Jump if Not Sign (S=0) |
| JV n | Jump if Overflow (V=1) |
| JNV n | Jump if Not Overflow (V=0) |
| CALL n | Call subroutine at n |
| RETURN | Return from subroutine |
| MOV reg, op2 | Move op2 to reg |
| ADD reg, op2 | Add op2 to reg |
| SUB reg, op2 | In unsigned subtraction, C = reg ≥ op2 |
| ROR reg, op2 | Rotate right by op2 bits (left by 8-op2 bits) |
| AND reg, op2 | Bitwise AND |
| OR reg, op2 | Bitwise OR |
| XOR reg, op2 | Bitwise XOR |
| STORE reg, [op2] | Store reg to op2 address, reg → [op2] |
| LOAD reg, [op2] | Load word at op2 address to reg, reg ← [op2] |
| RSHIFT reg | Right shift, C = shifted bit, V = sign change |
| CMP reg, op2 | Compare with SUB, set flags and discard result |
| LSHIFT reg | Left shift, C = shifted bit, V = sign change |
| BIT reg, n | Bit test with AND, set flags and discard result |
| PUSH reg | Push reg to stack |
| POP reg | Pop reg from stack |
+----------------------+----------------------------------------------------+

Notes

Directives must precede all instructions.
Labels are case sensitive, but directives and instructions are not.
.DATA sets a label after the last instruction and writes the csv data to it; consecutive .DATA directives append after each other.
Comments start with a semicolon.
The grammar is available in BNF notation at Piber's Testing suite. To test your input, first select BNF from the settings cogwheel on the top right. This syntax is a structural blueprint, not a full specification, and lacks features such as comments.
The .FREQUENCY directive doesn't affect simulation; it's used in the FPGA unit only.
Likewise, the .SIMDIP directive doesn't affect execution on FPGAs; it's used in simulation only.

Example 1 - One-click simulation with GHDL/GTKWave or ModelSim
The following program writes the null-terminated string `az{"0 to memory after the last instruction (notice the label under HLT) and converts the lowercase characters to uppercase, stopping when it hits the terminator:
.TITLE "Converts the lowercase characters of a given string to uppercase"
.LABEL char_a 97
.LABEL char_after_z 123 ; character after "z" is "{"
.LABEL case_difference 32
.DATA string "`az{\"0",0 ; null-terminated string under the last instruction
MOV R0, string ; R0 = address of the first character ("`")
loop:
LOAD R1, [R0] ; Updates SZ flags (like 6800 & 6502)
JZ finish ; loop while [R0] != null
CMP R1, char_a
JNC next ; if [R0] < "a" goto next
CMP R1, char_after_z
JC next ; else if [R0] ≥ "{" goto next
SUB R1, case_difference ; [R0] ∈ ["a", "z"], so change to uppercase
STORE R1, [R0] ; write character back to RAM
next:
ADD R0, 1 ; [R0]++
JMP loop ; end loop
finish:
HLT ; stop execution & simulation

To simulate it, first install the E80 Toolchain package from the Releases, then open the E80 Editor and paste the code into it:

Notice that syntax highlighting for the E80 assembly language has been enabled by default for all code (except for VHDL files).
Press F5. The editor will automatically assemble the code, save the VHDL output, compile the entire design with GHDL, and launch a GTKWave instance. Subsequent simulations will be closing the previous GTKWave window to open a new one.
You should see the following waveform, in which the RAM has been expanded to show how the lowercase letters of the string have changed to uppercase:

Notice that the HLT instruction has stopped the simulation in GHDL, allowing for the waveforms to be drawn for the runtime only. This useful feature is supported in ModelSim as well.
You can also press F7 to view the generated Firmware.vhd file, without simulation:

Notice how the assembler formats the output into columns according to instruction size, and annotates each line to its respective disassembled instruction, ASCII character or number.
If you have installed ModelSim, you can press F8 to automatically open ModelSim and simulate into it. Subsequent simulations on ModelSim will update its existing window:

The Memory Data tab next to the Wave tab contains the RAM in the end of simulation. The contents can also be displayed by hovering on the RAM in the Wave tab, but there's a catch: if the radix is set to ASCII and the data include a curly bracket, ModelSim will throw an error when trying to show the tooltip.
Example 2 - Testing on the Tang Primer 25K
First, install Gowin EDA Student Edition (Windows, Linux, MacOS).
Study the pin assignments in the Gowin\E80.cst file and apply them to your board. Use a five-direction navigation button/joystick with Left, Right, Up, Down, Set (for Pause), and Reset. All input pins must be active high with a 10kΩ pull-down resistor and the joystick's COM port must be connected to a 3.3V output. Below is a reference photo of the board setup:

The top module (FPGA.vhd) uses three 8-LED rows for display, and the joystick buttons for control:
LEDs

Row A (Status):

[7:4] (Flags): Carry, Zero, Sign, Overflow.
[3:1] (Register Selection): Binary index of the register currently displayed on Row B.
[0] (Clock): Pulses dimly during normal execution, pulses brightly during reset, and turns solid bright on HLT.

Row B (Data): Displays the value of the selected register. When Reset is held, it mirrors the DIP switch input instead.
Row C (PC): Displays the current Program Counter.

Buttons

Joystick Left/Right: Adjust clock speed; supports auto-repeat when held down.
Joystick Center: Reset clock speed.
Joystick Up/Down: Select which register is displayed on Row B; supports auto-repeat when held down.
Set: Pause execution.
Reset: CPU initialization and firmware reset; press until the Clock LED starts flashing brightly.

To run the test, paste the following program into the editor and press F7. This will automatically update Firmware.vhd with your new code.
.TITLE "256-ROR to test joystick control"
.SIMDIP 0b00000010 ; for simulation only, FPGA ignores this
LOAD R0, [0xFF] ; loads the DIP input word to R0
MOV R1, 0
loop:
ROR R0, 1
ADD R1, 1
JNC loop ; stop after 256 RORs (32 full rotations)
HLT

You can also simulate (F5 or F8) the program prior to running in the FPGA; in this case it's suggested to match the .SIMDIP value with the DIP switches on the board.
Open the Gowin\Gowin.gprj file in the Gowin IDE. Compile the project using Run All, wait for completion, connect your Tang Primer 25K board on your PC, and then use the Programmer function to upload the configuration.
When the upload is finished, press the Reset button to initialize the RAM with your firmware, and release it when the Clock LED stops pulsing. The Clock LED will be pulsing as the program runs. LED Row B defaults to R0, so you will see it rotating. Then the HLT instruction will be executed and the Clock LED will stop pulsing.

About

A simple CPU in VHDL for educational purposes

Topics

cpu

assembly

vhdl

gcc

assembler

isa

microworld

modelsim

ghdl

digital-design

cyclone-iv

quartus

gowin

tang-primer-25k

Resources

Readme

License

GPL-3.0 license

Uh oh!

There was an error while loading. Please reload this page.


Activity
Stars

12
stars
Watchers

1
watching
Forks

0
forks

Report repository

Releases
1

E80 Toolchain Setup 1.6

Latest

Jan 10, 2026

Packages
0

No packages published

Languages

C
39.1%

VHDL
38.3%

NSIS
11.4%

Stata
4.4%

Lua
3.8%

Batchfile
1.5%

Tcl
1.5%

Footer

© 2026 GitHub, Inc.

Footer navigation

Terms

Privacy

Security

Status

Community

Docs

Contact

Manage cookies

Do not share my personal information

You can’t perform that action at this time.

The E80 CPU, developed by Stokpan as part of an undergraduate thesis, is a simplified central processing unit implemented in VHDL, designed explicitly for educational purposes. It embodies the principles of a Constructionist Microworld by offering three key characteristics: a low floor for accessibility, a high ceiling for complexity, and wide walls for compatibility across platforms. The CPU’s design prioritizes textbook-based structural VHDL components, ensuring that it remains grounded in foundational digital logic principles while providing a toolchain installer for one-click simulation. This makes it an accessible resource for students learning about computer architecture, as it balances simplicity with functionality. The E80 supports a comprehensive set of instructions typical of Computer Architecture textbooks, including stack operations and subroutine calls, while its compatibility with various platforms—such as GHDL/GTKWave, ModelSim, Quartus Lite, Gowin Education, Vivado Standard, and the Tang Primer 25K FPGA board—enhances its utility in diverse lab or classroom environments. The repository includes all necessary source materials, from the CFG grammar defining its assembly syntax to EDA project files, enabling users to study, modify, and extend the design. The CPU’s architecture is load/store based, with a register-register model, allowing for efficient data manipulation. Its 8-bit word size and 16-bit instruction format accommodate variable-length instructions (either one or two words), while its buses—8-bit data, 8-bit address, and 16-bit instruction—reflect a balanced approach to memory addressing and data transfer. The CPU features a multiport register file (1R/W, 1R, 1W) with six general-purpose registers (R0–R5), a flags register (R6), and a stack pointer (SP, alias R7). The stack is implemented as full descending, initialized to 0xFF on reset, allowing for standard subroutine calls and stack-based operations. Input is handled via an 8-bit memory-mapped DIP switch at address 0xFF, while output includes flags, register values, the program counter (PC), and a clock signal displayed through three 8-bit LEDs. The assembly syntax combines elements of ARM, x86, and textbook pseudocode, offering a hybrid approach that bridges high-level programming concepts with low-level hardware control. For instance, instructions like `MOV R3,R5` translate to binary representations such as 0b(00011000 00110101), which corresponds to the hexadecimal value 0x1835. This syntax is further supported by an ISO C99 assembler, which processes user-written programs into machine code executable within the simulated or synthesized environment. The ISA includes a range of operations, from basic arithmetic and logic (ADD, SUB, AND, OR, XOR) to more complex instructions like ROR (rotate right), LSHIFT (left shift), and RSHIFT (right shift). Conditional jumps (e.g., JC, JZ, JS) allow for branching based on the state of flags, while stack operations (PUSH, POP) and subroutine calls (CALL, RETURN) enable modular programming. The CPU’s flag system—comprising Carry (C), Zero (Z), Sign (S), Overflow (V), and Halt (H)—is updated by arithmetic, logic, and shift instructions, with specific rules for determining their values. For example, the Carry flag is set during addition if the result exceeds 8 bits, while the Overflow flag indicates signed arithmetic overflows. The HLT instruction halts execution by setting the H flag, freezing the program counter (PC) and stopping further processing. The repository also provides detailed documentation on the CPU’s behavior, including a flags cheatsheet that clarifies how signed and unsigned operations affect flag states. For instance, during addition (ADD), the Carry flag reflects whether the result exceeds 255 (unsigned overflow), while the Overflow flag indicates if the sum falls outside the range of -128 to 127 (signed overflow). Similarly, subtraction (SUB) and comparison (CMP) instructions update flags based on the relationship between operands. The E80’s assembly language includes directives like `.TITLE`, `.LABEL`, `.SIMDIP`, and `.DATA` to manage program structure, memory allocation, and simulation parameters. These directives allow users to define labels for addresses, set DIP switch inputs for simulations, and embed data directly into memory. The assembler also supports comments (using semicolons) and flexible operand formats, such as immediate values, register addresses, and memory references (e.g., `[R2]` for the value at address stored in register R2). The repository’s examples demonstrate practical applications of the CPU, such as a program that converts lowercase characters in a null-terminated string to uppercase. This example leverages instructions like `LOAD`, `CMP`, `SUB`, and `STORE` to process each character, using conditional jumps (JNC, JC) to determine whether a transformation is needed. Another example tests joystick control on the Tang Primer 25K FPGA, using `ROR` instructions to rotate a value across 256 iterations. The E80’s toolchain simplifies simulation and synthesis, with one-click scripts for GHDL/GTKWave and ModelSim, as well as project files for Quartus Lite, Gowin Education, and Vivado Standard. The repository also includes a SciTE-based editor with syntax highlighting and one-click run functionality, streamlining the development process. For hardware testing, the Tang Primer 25K setup requires pin assignments defined in the `Gowin\E80.cst` file, with specific connections for input (DIP switches) and output (LEDs). The FPGA’s top module (`FPGA.vhd`) uses three rows of LEDs to display flags, register values, and the PC, while a joystick controls clock speed, reset, and register selection. The CPU’s compatibility with multiple platforms ensures that students can experiment with different EDA tools and hardware, reinforcing their understanding of digital design principles. Overall, the E80 CPU serves as a comprehensive educational tool, bridging theoretical concepts with hands-on implementation. Its structured design, detailed documentation, and support for both simulation and physical hardware make it an invaluable resource for learning about computer architecture, VHDL programming, and FPGA development. By combining simplicity with robust features, the E80 empowers learners to explore the inner workings of a CPU while engaging with real-world design challenges.