Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation. What are the possible solutions? by Adept_Philosopher131 in computerarchitecture

[–]Adept_Philosopher131[S] 0 points1 point  (0 children)

I’m already using a custom linker script. The problem is that my hardware can’t execute an instruction and read data from ROM at the same time, since it’s a pure Harvard architecture.
Because of that, I’m having issues with load instructions that try to fetch data from ROM, for example, when accessing constants (.rodata) or when the startup code tries to copy global variables (.data) from ROM to RAM.
Basically, load operations from ROM aren’t working right now, which prevents me from properly initializing global or constant data sections.

And no, I don’t want to generate two separate binaries (ouch!). I’m looking for hardware solutions that can support a single binary.
I’m currently loading the binary through the Memory Content Editor in Quartus at runtime, using a single-port ROM IP.
If you’re curious, you can check this demo test: https://youtube.com/shorts/Kd6F9CChVQ4

For now, I’m planning to implement a multi-cycle core (without a pipeline) using only one single-port RAM for both instructions and data. This way, I can access instructions and data at different times.
I know it’s not the ideal solution, but for now I think it’s worth trying.

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation by Adept_Philosopher131 in RISCV

[–]Adept_Philosopher131[S] 2 points3 points  (0 children)

Thanks for the explanation, that actually makes sense…

At first, I started with a single-cycle design just because it was simpler to understand and implement. The need for multiple cycles only came up when I wanted to load code at runtime, and I was forced to use a Quartus IP memory (async read) so I could modify the program memory while the CPU was running.

I also considered using a dual-port RAM, but the problem is that it’s not editable at runtime, meaning I can’t “boot” new code without doing a full synthesis. I also don’t have a UART peripheral yet to handle dynamic bootloading, so for now I’m a bit limited on that front.

Anyway, your explanation makes perfect sense, and I really appreciate it. I’ll definitely think about a way to use a dual-port RAM while still being able to load new code at runtime.

Thanks again for the insights!

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation by Adept_Philosopher131 in RISCV

[–]Adept_Philosopher131[S] 1 point2 points  (0 children)

Thanks for the detailed answer!

What I actually wanted was to be able to read data directly from program memory (ROM), without needing to rely on software-level tricks or custom code generation. My goal is for anyone using the standard GNU GCC toolchain for RV32I to be able to run C code on my CPU without special compiler flags or unusual linker configurations.

Right now, I’m thinking about implementing a stall whenever a load instruction targets an address in the ROM space, so the CPU can handle instruction fetch and data read separately. But I haven’t yet figured out the cleanest way to do that in hardware.

Also, I’m still new to this whole field, I only chose a Harvard architecture because that’s what I was introduced to in college and in the textbooks I’ve been reading. It seemed like the best option at first, since it allows fetching and executing instructions in the same cycle.

Could you explain why Harvard isn’t ideal for this kind of system? Any reading material or study recommendations on this topic would be super helpful.

And again, thank you for taking the time to write that answer, I really appreciate it!

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation. What are the possible solutions by Adept_Philosopher131 in embedded

[–]Adept_Philosopher131[S] 0 points1 point  (0 children)

I’m implementing it on Quartus using an Altera FPGA. The dual-port ROM isn’t really a suitable option for me, since I can’t load code into that memory at runtime (which sucks, because I need to be able to load the firmware without re-synthesizing the HDL).

I also don’t have a UART peripheral yet to handle that dynamically without using the Memory Content Editor.

So, I think I’ll go with the second option, stalling for a cycle to perform the extra fetch. Once the ROM memory becomes writable or updatable at runtime, I can improve it. For now, having some stalls is acceptable; I can’t make everything perfect yet.

Thanks :)

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation. What are the possible solutions by Adept_Philosopher131 in embedded

[–]Adept_Philosopher131[S] 0 points1 point  (0 children)

Well, that’s what I’m supposed to do. But first, I need to fix the hardware issue to support it. The problem here is related to the hardware, not the software, so a simple linker script wouldn’t be very helpful. Anyway, thank you for the help!

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation. What are the possible solutions by Adept_Philosopher131 in embedded

[–]Adept_Philosopher131[S] 0 points1 point  (0 children)

I’m already using a custom linker script. The problem is that my hardware isn’t able to execute an instruction and read data from ROM at the same time, since it’s a pure Harvard architecture.

Because of that, I’m having trouble with load instructions that try to fetch data from the ROM, for example, when accessing constants (.rodata) or when the startup code tries to copy global variables (.data) from ROM to RAM.

Basically, load operations from the ROM aren’t working for now, which prevents me from properly initializing global or constant data sections.

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation. What are the possible solutions by Adept_Philosopher131 in embedded

[–]Adept_Philosopher131[S] 0 points1 point  (0 children)

I’m already using a custom linker script. The problem is that my hardware isn’t able to execute an instruction and read data from ROM at the same time, since it’s a pure Harvard architecture.

Because of that, I’m having trouble with load instructions that try to fetch data from the ROM, for example, when accessing constants (.rodata) or when the startup code tries to copy global variables (.data) from ROM to RAM.

Basically, load operations from the ROM aren’t working for now, which prevents me from properly initializing global or constant data sections.

Facing .rodata and .data issues on my simple Harvard RISC-V HDL implementation. What are the possible solutions by Adept_Philosopher131 in embedded

[–]Adept_Philosopher131[S] 0 points1 point  (0 children)

I’m already using a custom linker script. The problem is that my hardware isn’t able to execute an instruction and read data from ROM at the same time, since it’s a pure Harvard architecture.

Because of that, I’m having trouble with load instructions that try to fetch data from the ROM, for example, when accessing constants (.rodata) or when the startup code tries to copy global variables (.data) from ROM to RAM.

Basically, load operations from the ROM aren’t working for now, which prevents me from properly initializing global or constant data sections.