Skip to content

Instantly share code, notes, and snippets.

@lypanov
Created February 26, 2025 19:02
Show Gist options
  • Save lypanov/06f0f58c5ec6e2ca671a52f2c54a6446 to your computer and use it in GitHub Desktop.
Save lypanov/06f0f58c5ec6e2ca671a52f2c54a6446 to your computer and use it in GitHub Desktop.
stuffs

Prompt: excellent, given i've read a bit of the book, and started the basics.

i've found documentation on the ISA used in the processor, though having yet found good information about the memory map alas.

i've decided to take this path this week, i'd like to simulation first, hardware second, have a working basic ISA compatible subset CPU with instructions needed to write a LED blinker. the LED can be memory/register mapped for simplicity, whatever you feel is simpler.

so it'll need the absolute basic amount of instructions to count up till a number is reached, and when the count is reached change the state of the led, so, we'll probably need a basic ALU, PC, and branching, please write the .asm that you think we'll need to execute given the ISA spec i've included, and explain each of the instructions and what they do.

please while your at it try to find out if there is a working 'assembler' ( as in, translator from .asm to actual machine code ) that i'll be able to use to generate the instruction stream. i'll want to hardcode said instruction stream somehow into my fpga source code for now, as i do not want to get into ram / external memory for now, only the basics.

here is the definiton of the ISA: https://gist.githubusercontent.com/swetland/7f6968e26f39db8d8dd693da85f820d1/raw/451550ed442ce5f3c98a5d68abdfb538b173c703/project-oberon-risc5-architecture.txt

Key Points

  • It seems likely that today, February 26, 2025, you should focus on researching the Project Oberon RISC5 architecture and setting up your Chisel environment, as per the provided plan.
  • The evidence leans toward starting with reading the Project Oberon book and downloading its Verilog files to create a project map.
  • For your LED blinker, research suggests a simple assembly program using MOV, SUB, XOR, ADD, and branch instructions, with machine code hardcoded in Chisel for simulation first.
  • An unexpected detail is the Tang Nano 4K's 4608 LUT limit, which may require design optimization later.

Today's Tasks and Background

Research and Setup
Today, your main focus is to build a foundation for porting Project Oberon to Chisel. Start by downloading and reading the Project Oberon book from Free Computer Books, focusing on the RISC5 CPU and system overview to understand the architecture. Next, download the Verilog files from projectoberon.net to identify key modules like the control unit, ALU, register arrays, RAM/ROM, and HDMI signaling. Create a document mapping each Verilog module to its Chisel counterpart to guide your work.

Given your limited knowledge of Chisel and FPGAs, Chisel is a hardware description language embedded in Scala, allowing for high-level, reusable hardware designs compiled to Verilog for FPGA implementation. FPGAs, like the Tang Nano 4K's Gowin GW1NSR-LV4C chip, are programmable logic devices with configurable blocks for digital circuits, crucial for tasks like running a CPU and displaying on HDMI. Set up Chisel using the Chisel installation guide and explore simple modules, such as a counter, to get hands-on practice.

LED Blinker Program
For your goal of simulating a basic RISC5 CPU with instructions to blink an LED, you'll need a subset of the ISA including MOV, SUB, XOR, ADD, and branch instructions. The LED can be register-mapped for simplicity, using R0 to control its state (bit 0 determines on/off). Here's the assembly program:

MOV R1, 0    ; Initialize counter R1 to 0
MOV R2, 100  ; Set target value R2 to 100
loop:
SUB R3, R1, R2 ; Subtract R2 from R1, store in R3, sets Z flag if equal
B NE, skip_toggle ; Branch if not equal (Z not set) to skip_toggle
XOR R0, R0, 1 ; Toggle LED (R0) by XORing with 1
MOV R1, 0    ; Reset counter R1 to 0
skip_toggle:
ADD R1, R1, 1 ; Increment counter R1 by 1
B always, loop ; Always branch back to loop

Instruction Explanations:

  • MOV R1, 0: Loads immediate 0 into R1, initializing the counter (F1, op=0, a=1, n=0).
  • MOV R2, 100: Loads immediate 100 into R2, setting the target value (F1, op=0, a=2, n=100).
  • SUB R3, R1, R2: Subtracts R2 from R1, stores in R3, sets Z flag if R1 equals R2 (F0, op=9, a=3, b=1, c=2).
  • B NE, skip_toggle: Branches if not equal (Z not set) to skip_toggle, using offset calculated based on addresses (F3, v=0, cond=1001, off=2).
  • XOR R0, R0, 1: Toggles R0 by XORing with 1, affecting the LED state (F1, op=7, a=0, b=0, n=1).
  • ADD R1, R1, 1: Adds 1 to R1, incrementing the counter (F1, op=8, a=1, b=1, n=1).
  • B always, loop: Always branches back to loop, using offset -6 (F3, v=0, cond=0111, off=-6).

The machine code, hardcoded for Chisel, is:

  • 0x41000000
  • 0x42000064
  • 0x03190200
  • 0xE9000002
  • 0x40070001
  • 0x41000000
  • 0x41180001
  • 0xE7FFFFFA

Assembler and Hardcoding
Research suggests using Astrobe for RISC5, a Windows IDE, might provide an assembler, but it's designed for Xilinx FPGAs, not Gowin. Given this, you may need to manually assemble or find open-source tools. For now, hardcode the above machine code in your Chisel design's instruction memory, defining a Vec of UInt(32.W) with these values, and simulate first before hardware testing.


Survey Note: Detailed Guidance for Today's Work on Project Oberon and Chisel

This note provides a comprehensive overview of the tasks for February 26, 2025, aligning with your goal to port the Project Oberon Verilog implementation to Chisel for the Tang Nano 4K FPGA, focusing on rendering a GUI via HDMI, and creating a simple LED blinker program for simulation. Given your limited knowledge of Chisel and FPGAs, this section aims to equip you with the necessary background and practical steps to begin effectively.

Understanding Project Oberon and RISC5 Architecture

Project Oberon, designed by Niklaus Wirth and Jürg Gutknecht, is a complete desktop computer system encompassing an operating system, compiler, and hardware, implemented in the Oberon language. The 2013 edition, adapted for FPGAs, is particularly relevant, with a focus on the RISC5 CPU, a custom processor distinct from more common architectures like RISC-V. To start, download the Project Oberon book PDF from Free Computer Books and focus on chapters detailing the RISC5 architecture and system overview. This will help you understand the digital system's behavior, which you'll need to replicate in Chisel.

Identifying Key Verilog Modules

The original implementation is in Verilog, and you need to identify key modules for porting. Download the Verilog files from projectoberon.net, which include files like RISC5Top.v and Registers.v, covering components such as the control unit, ALU, register arrays, RAM/ROM, and HDMI signaling. Review these files to map out the functionality of each module, noting how they interact, such as the CPU's datapath and control logic, and the HDMI module's timing for video output. This step is crucial for creating a project map, outlining each Verilog module and its Chisel counterpart, which will guide your translation process.

Setting Up Chisel Environment

Chisel, an acronym for Constructing Hardware in a Scala Embedded Language, is a hardware description language built on Scala, enabling type-safe, object-oriented, and functional programming for hardware design. It generates Verilog for synthesis on FPGAs. To set up, follow the Chisel installation guide, which recommends using Scala CLI for quick starts. Install a Java Development Kit (JDK), version 17 or newer, and download a Chisel example to verify your setup, such as a simple counter module. This hands-on approach will familiarize you with Chisel's syntax and workflow.

Practical Example: Simple Chisel Module

To get started, consider writing a basic Chisel module, such as a register, to understand its structure. Here's an example:

import chisel3._

class Register(width: Int) extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(width.W))
    val out = Output(UInt(width.W))
    val load = Input(Bool())
  })
  val reg = Reg(UInt(width.W))
  when (io.load) {
    reg := io.in
  }
  io.out := reg
}

This module defines a register that loads an input when the load signal is high and holds its value otherwise. Compile and simulate this using ChiselTest to see how it behaves, helping you grasp Chisel's hardware description capabilities.

Background on FPGAs and the Tang Nano 4K

FPGAs are field-programmable gate arrays, integrated circuits with configurable logic blocks (CLBs) connected via programmable interconnects, allowing for custom digital circuit implementation. The Tang Nano 4K, based on the Gowin GW1NSR-LV4C FPGA chip, has 4608 LUTs, an HDMI connector for GUI output, and additional features like a Cortex-M3 core. Understanding FPGA basics is essential; refer to FPGA Tutorial for concepts like combinational and sequential logic, clocking, and reset. The board's resource constraints, particularly LUT limits, will influence your design, requiring careful optimization as you integrate modules.

Verilog Knowledge for Translation

Since Chisel generates Verilog, understanding Verilog is beneficial. Start with Verilog Tutorial by ChipVerify to learn syntax and concepts like modules, ports, and behavioral modeling. This will help you translate Verilog modules, starting with simpler ones like registers, into Chisel, ensuring functionality aligns with the original design.

Incremental Approach and Simulation

The plan emphasizes simulating each module in isolation before integration, using tools like ChiselTest. This approach, detailed in the weekly themes, reduces risks by catching issues early. For today, focus on setting up simulation for your simple Chisel modules, ensuring you can inspect waveforms and verify behavior, preparing for more complex translations like the RISC5 CPU.

Resource Considerations and Risk Management

The Tang Nano 4K's 4608 LUT limit is a critical factor; compare your design's resource estimates against this to avoid bottlenecks. The plan suggests cushioning for unforeseen challenges, such as HDMI timing issues, and revisiting earlier tasks if integration bugs arise. This proactive approach ensures you meet the March 20, 2025, feature-complete target, with a buffer before the April 1 deadline.

LED Blinker Program and Assembly

For your goal of simulating a basic RISC5 CPU with instructions to blink an LED, you'll need a subset of the ISA including MOV, SUB, XOR, ADD, and branch instructions. The LED can be register-mapped for simplicity, using R0 to control its state (bit 0 determines on/off). Here's the assembly program with detailed explanations:

Instruction Assembly Explanation
Initialize MOV R1, 0 Loads immediate 0 into R1, initializing the counter (F1, op=0, a=1, n=0).
Set Target MOV R2, 100 Loads immediate 100 into R2, setting the target value (F1, op=0, a=2, n=100).
Loop Start SUB R3, R1, R2 Subtracts R2 from R1, stores in R3, sets Z flag if R1 equals R2 (F0, op=9).
Branch Condition B NE, skip_toggle Branches if not equal (Z not set) to skip_toggle, using offset (F3, cond=1001).
Toggle LED XOR R0, R0, 1 Toggles R0 by XORing with 1, affecting the LED state (F1, op=7, a=0, n=1).
Reset Counter MOV R1, 0 Resets counter R1 to 0 after toggle (F1, op=0, a=1, n=0).
Skip Toggle Label skip_toggle: Label for branching, continues execution here if not equal.
Increment Counter ADD R1, R1, 1 Adds 1 to R1, incrementing the counter (F1, op=8, a=1, b=1, n=1).
Loop Back B always, loop Always branches back to loop, using offset -6 (F3, cond=0111, off=-6).

The machine code, assembled manually, is:

  • 0x41000000 (MOV R1, 0)
  • 0x42000064 (MOV R2, 100)
  • 0x03190200 (SUB R3, R1, R2)
  • 0xE9000002 (B NE, skip_toggle, off=2)
  • 0x40070001 (XOR R0, R0, 1)
  • 0x41000000 (MOV R1, 0)
  • 0x41180001 (ADD R1, R1, 1)
  • 0xE7FFFFFA (B always, loop, off=-6)

To hardcode this in Chisel, define a Vec of UInt(32.W) with these values, and simulate the CPU starting at PC=0, connecting R0(0) to the LED output.

Assembler and Hardcoding

Research suggests using Astrobe for RISC5, a Windows IDE, might provide an assembler, but it's designed for Xilinx FPGAs, not Gowin. Given this, you may need to manually assemble or find open-source tools. For now, hardcode the above machine code in your Chisel design's instruction memory, defining a Vec of UInt(32.W) with these values, and simulate first before hardware testing.

Conclusion

By focusing on reading, mapping, and setting up Chisel today, you lay a strong foundation for the project. Leverage online resources for Chisel and FPGA basics, and begin with simple modules to build confidence. For the LED blinker, implement and simulate the CPU with the provided machine code, ensuring R0 toggles as expected. This approach, combined with the detailed plan, positions you well to achieve the goal of rendering the GUI on HDMI by March 20, 2025.

Key Citations

Comments are disabled for this gist.