Skip to content

Creating Modifications

Diogo Valadares Reis dos Santos edited this page Aug 26, 2025 · 5 revisions

[Português]

[← Previous Page | Next Page →]

Creating Modifications

Once you've explored the simulation and run your own programs, you might feel ready to tweak or expand the system. This guide walks you through how to do that, while offering practical advice for debugging along the way.

Before diving in, it's helpful to have some basic familiarity with either Logisim Evolution or SystemVerilog. Logisim is more approachable for quick experimentation, thanks to its built-in tutorials and visual interface. SystemVerilog, on the other hand, offers a more robust environment with better debugging tools, especially for larger or more complex systems.

Adding External Devices

Introducing external devices that interact with the processor is a great starting point for modification. Your component should be able to send or receive data, respond to read/write signals, and synchronize with the system clock. Including a reset signal is also a good idea, and depending on your design, you might want to provide address or data size inputs as well.

It's best to begin by designing and testing your device in isolation. Once you're confident it behaves correctly, you can connect it to the IO interface. Looking at how existing components are wired up, like the Real-Time Device, can be a helpful reference.

Real-Time Device Connection

After connecting your device, you'll need to load a program that interacts with it. If things don’t work as expected, double-check your connections and ensure your program uses the correct addresses. If that still doesn’t solve the issue, it’s time to dig deeper with some debugging techniques.

Debugging Techniques

When debugging, sometimes the simplest approach is the most effective. If your program is small or you can visually spot when something goes wrong but struggle to pause the simulation in time, slowing things down can help. In Logisim, you can reduce the simulation frequency via Simulate > Auto Tick Frequency > 1Hz.

In SystemVerilog, adjusting the CLOCK_UPDATE_TIME parameter has a similar effect, though SV’s detailed logs often make this unnecessary.

If your component worked in isolation but fails when integrated, try testing it with a minimal program: just a single store or load instruction followed by an infinite loop. This helps isolate the issue without the noise of a full application.

For deeper inspection, waveform analysis is your best friend. Logisim includes a timing diagram tool, though it can be glitchy and may slow down or crash the simulation. If you use it, reset the simulation before adding or removing signals, and stick to only the ones relevant to your issue. It’s also helpful to include signals for the current instruction, address, clock, and IO bus. You can change how values are displayed—hex or decimal—for easier reading.

Logisim Timing Diagram

SystemVerilog offers a more stable and detailed waveform inspection through its VCD output. You can open the VCD file in VS Code and use the VaporView extension to visualize signal changes over time. Signals can be added manually via the netlist panel, or you can load a pre-configured view by right clicking the graph, selecting load VaporView settings and selecting the dump.json file. This setup highlights the most important buses and registers, and you can customize how values are displayed for clarity.

VaporView Interface

Adding Internal Components

Adding Internal Components

Adding internal components is a bit more involved than working with external ones, since it requires creating new control signals and custom interfaces to ensure your component integrates properly with the processor. If you're implementing a feature already defined in the RISC-V specification, the process becomes more straightforward—you won’t need to worry as much about compatibility with the rest of the system. Still, there will be design challenges to overcome.

Just like with external devices, it's a good idea to begin by developing your component in isolation. Once it behaves as expected, you can start planning how it will connect to the processor. Consider which internal buses it will interact with—such as A, B, C, Immediate, and PC—and whether it needs to communicate with other components. If you're aiming for deeper integration, like the CSR Controller, you'll also need to define how control signals are generated and which instructions will trigger them.

Once your component is ready, the next step is to modify the Operation Controller. If your component responds to an instruction that hasn’t been implemented yet, you’ll need to add decoding logic to the OPCode decoder PLA and expand its output accordingly. You can also use instruction fields like funct3 or funct7 to fine-tune the behavior of your component.

And if you're introducing a new control signal, don’t forget to register it before propagating it to other parts of the system. This ensures proper synchronization and avoids unexpected behavior during execution.

Clone this wiki locally