stnolting / neorv32

:desktop_computer: A small, customizable and extensible MCU-class 32-bit RISC-V soft-core CPU and microcontroller-like SoC written in platform-independent VHDL.

Home Page:https://neorv32.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Utilizing on-board SRAM

mahdi259 opened this issue Β· comments

Is your feature request related to a problem? Please describe.

I have a benchmark that uses large matrices (in order of 200KB data). My FPGA is Spartan 6 that has limited resources but it is connected to a 512 KB SRAM. I need to use this SRAM when I load my instructions and data with UART.

Describe the solution you'd like

Is it possible to have imem and dmem as caches on FPGA and SRAM as the next level memory?

I think indirect boot scenario b should be used according to your description. I try to find out more details about it.

Hey there,

Is it possible to have imem and dmem as caches on FPGA and SRAM as the next level memory?

sure, that is possible. You "just" need an external memory controller attached to the processor's external memory interface. Accessing external static RAM is quite simple and you should have no problems finding a suitable (open-source) controller for that. I think Xilinx ISE (or AMD Vivado?) also provide an SRAM configuration for their MIG IP.

Another option could be to use SPI SRAM attached via the SPI controller. It is slower and you cannot execute code from it (maybe you can, when you multiplex XIP) but it might be simpler to integrate as your do not need to touch the actual hardware. But this highly depends on your performance requirements.

Thanks for your reply. This week, God willing, I will try to use SRAM controller.

Hi there. I thinks one side of the SRAM controller should be wishbone compatible and the other side should connect to SRAM and control read/write operations. Am I right?

Sounds good. With a Wishbone port you can connect the controller right to the processor's external bus interface and map the SRAM directly into the core's address space.

Sorry, how should we determine that bootloader writes instruction/data to external (attached to wishbone interface) SRAM and processor reads instruction/data from it?

I'm not sure if I understand your question correctly.

For the memory controller it does not matter who (bootloader, debugger, application program, ...) reads/writes what (data or instructions). The controller just translates Wishbone accesses into SRAM accesses.

As you described in NeoRV datasheet, there are two indirect boot variants.
I want to use the second one in which the bootloader receives data through UART port and writes it to external memory.

The question is how to inform bootloader to write data to external memory and how to inform CPU to read instructions and data from external memory.
neorv32_boot_configurations

In address space section of datasheet, picture comment says that only void regions are redirected to external memory interface. So for IMEM and DMEM, the external memory interface won't receive any request.
address_space

Ah now I understand.
Seems like the data sheet is not quite precise there πŸ™ˆ I need to fix that.

If you disable the processor-internal IMEM (MEM_INT_IMEM_EN => false,) then the default address region of the IMEM (starting at 0x00000000) will also become part of the "void". Hence, all accesses that were targeting the internal IMEM will get redirected to the external bus interface - effectively accessing your external SRAM.

The default bootloader will always write any new application data starting at address 0x00000000 - so it does care if this is actually written to the internal IMEM or to an external memory.

Thanks for your reply. Do we need to specify data and address size in this case?
Does data space begin from 0x80000000 like the picture of address space?

Thanks for your reply. Do we need to specify data and address size in this case?

The bus provides 32-bit for the address and 32-bit for the data. If your SRAM only provides a 8-bit or 16-bit port then you'll need to implement some kind of state machine to transform 32-bit accesses into consecutive 16/8-bit accesses. Note that the bus interface also supports smaller access granularities, i.e. 8-bit and 16-bit accesses.

Does data space begin from 0x80000000 like the picture of address space?

"Data space" is just a software concept. On the hardware level there is just memory. You can put your data wherever you want - including your SRAM if that is what you want.

I think this can be closed, right?

Hi. Yes thank you.
I couldn't find an open source SRAM controller module. If I find one I will send the link here.

I have this one on my stack (but haven't tested it yet): https://github.com/chkrr00k/sram-controller/blob/master/sram.vhd

It is quite simple and written in VHDL (❀️). πŸ˜…

You are awesome!
Thanks

Hi @stnolting
Should I instantiate external memory controller module inside neorv32_wishbone.vhd?

I would suggest to keep the code base as clean as possible so you don't run into merge conflicts when there are upstream changes in the Wishbone gateway πŸ˜‰

So I would just add the memory controller as individual module and connect it via Wishbone to the processor:

+-----------------+                   FPGA-internal | FPGA-external
| neorv32_top.vhd |                                 |
|      +----------+    +----------------------+     |     +------+
|      | WISHBONE |--->| Your SRAM controller |---->o---->| SRAM |
+------+----------+    +----------------------+     |     +------+

You're right. Thanks

Hi @stnolting
I have prepared SRAM controller module and want to interface it to processor external bus (wishbone). Is there any documentation on XBUS signaling?

πŸ‘ πŸ‘ πŸ‘

Keep us updated (if you like) with your SRAM progress! πŸ˜‰

yes pls I will probably in the future also need something very similar to this application case. It was really useful to have this information as a starting point. Ty!

Ok. surely.

This is my SRAM controller. It starts when both xbus_stb and xbus_cyc are '1'. My top module assigns true to INT_BOOTLOADER_EN and false to MEM_INT_IMEM_EN, MEM_INT_DMEM_EN. The source codes are attached at the bottom. SRAM signals (chip enable /SRAM_ce/, output enable /SRAM_oe/ and write enable /SRAM_we/) are active low. The sram capacity is 512k byte (equivalently 128k words /32 bits/).

Drawing1

This is the waveform of SRAM controller. As can be seen, DATApin port is 8 bits wide and therefore it needs four iterations to complete. The xbus_ack signal gets '1' when we go from BYTE_END to WAITs state (after writing all 4 bytes).

image

SRAM_controller.zip

I couldn't get it work with NeoRV32 up to now and bootloader texts to choose uploading binary or execute are not shown. The simulation needs uploading data from UART and I should find a way to do that.

@stnolting, do you have any idea for connecting a virtual UART terminal to my simulated design?

Hi!

Try with this file uart_rx.simple.vhd.

And add it in your test bench as follows:

architecture tb of tb is

-- your signals/constants

constant baud0_rate_c            : natural := 19200;
constant CLOCK_FREQUENCY         : natural := 100000000;
constant uart0_baud_val_c : real := real(CLOCK_FREQUENCY) / real(baud0_rate_c);

begin

  your_top_under_test_inst: entity work.your_top_under_test
  generic map(
    --Your generics
             )
  port map (
    --Your ports
    uart0_txd_o => uart0_txd,
    uart0_rxd_i => uart0_txd
                  );
-- UART Simulation Receiver ---------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  uart0_checker: entity work.uart_rx_simple
  generic map (
    name => "uart0",
    uart_baud_val_c => uart0_baud_val_c
  )
  port map (
    clk => clk,
    uart_txd => uart0_txd
  );

-- Your test

end architecture;

If everything is okey you will see through asserts the uart output in the terminal where you are running the simulation. For example if you use VUnit your going to see the output in the terminal using -v argument. If you use vivado your going to see the output in the tcl console.

As shown in the following image:

comment_rsp

I hope you find it helpful!

Thanks a lot.

@mahdi259

Thanks for sharing your sources and all the details! You should really put them into a repository! I think that many people would find them useful. πŸ‘

@Unike267

Try with this file uart_rx.simple.vhd.

Good idea!

One more suggestion from my side: if you enable the internal IMEM and DMEM + the bootloader you can use the bus_explorer program to execute XBUS transactions by hand. Together with an oscilloscope / logic analyzer this can help to debug the FPGA-SRAm interface.

Thanks for your positive attitude @stnolting.

Here is my SRAM controller. It's a work in progress.
https://github.com/mahdi259/SRAM_controller.git

Looks great! πŸ‘