uController bring-up using the TinyFPGA


#1

Hi,

I am trying to bring-up and test a RISC-V uController using the TinyFPGA. The uController relies on an SPI peripheral to retrieve the code from an external flash memory. I intend to flash my code in the TinyFPGA’s flash memory using the “TinyFPGA-Bootload”, and then connect the SPI interface to the FPGA to access the flash memory.

The issue I am having is that my uController is supposed to look for the first instruction at address 0x00, while the TinyFPGA-Bootloader stores the user data at address 0x50000. I guess there are two ways to solve this:

1- I edit the TinyFPGA-Bootloader such that it partitions the flash memory differently, so that the user data is stored starting address 0x00. However, I am not sure whether this is possible ? and how it should be done?

2- The other way, would be to implement some logic on the FPGA to shift the address requests coming from the uController to the user data addrerss defined by the bootloader (0x50000). However, I am not what would be the implications of this on the performance ? and how hard would this be to implement ?

Thanks


#2

Hi,

1-

The iCE40 Programming and Configuration Technical Note (www.latticesemi.com/view_document?document_id=46502) gives information about how the iCE40LP8K boots depending on some configurations. It might be a good read to understand what is possible and what not. It might be possible to load the initial data from a different section of the SPI see (10. Cold Boot Configuration Option) but is my memory serves correctly some of those options are already used by TinyFPGA to be able to reboot into the user code after having run on bootloader mode.

I think this is non trivial/probably not the way to go

2-
My understanding is that you actually want to execute code “in place” therefore request from the CPU to a certain area in memory needs need to map directly to requests done to a certain area of the SPI flash. In such situation you will always need to convert memory request to actual requests to the SPI chip and unless you are also implementing some level of caching it probably going to give you bad performance. Not because of the “additional” code but more the latency (and amount of cycles) it would take to fetch an instruction. Still I think this is what https://github.com/tinyfpga/TinyFPGA-BX/tree/master/examples/picosoc is doing.

A more traditional solution is to include part of the code (as ROM code) directly into your microcontroller. Define and area of ram inside your code and let the rom code load data to ram before executing it . Or… initialize the ram directly (this is not my code) https://github.com/keesj/tiny_usb_examples/blob/keesj/picorv32/src/top.v#L98

I hope … you find a nice solution.


#3

@keesj Many thanks for your answer, it was helpful to make few things clear for me.

Actually my uController is already typed-out and there is no way to make it request the first instruction at a different address. The good news is that I double checked my RTL and simulation and turns-out that the first instruction is being requested at address 0x100000.

So rather than changing the boatloader and the user image address range, I only have to move the user data address range from 0x50000-0x100000 (default my tinyprog) to 0x100000 - 0x150000 . This should be possible since the Bx has 8 mbit of flash memory.

I guess this should be much easier than what I was trying to do, but If you have any idea how this can be easily achieved, I would be grateful to read you out :slight_smile:


#4

Hi,

The CPU will try to load the first instruction at an address of 0x100000 what is this address pointing to and how does this change your problem? there is no magic to map this to performing a request to the SPI. Is this a self defined blockram area or is this still to be defined?

Normally(I think) you should expect those request to be send over some bus (how is IO mapped , how is the SPI Mapped and… how is memory mapped)?

For example In picosoc you can see the following: in hardware line 103 (iomem_addr[31:24] == 8’h03) will redirect memory access matching to to GPIO (for example)

or more in general

One more thing note that tinyprog has the -p and -u options (to flash the user partition)


#5

@keesj ny thanks again for your answer.

I am not sure whether we are on the same page, but let me try to be clearer. So I have a uController (post-silicon) that I typed out. The uController has an internal RAM, but it is supposed to get the instructions/code/program from an external memory using its SPI interface.

The SPI interface of the uController, as soon as it is powered up, it tries to get the first instruction from the external memory by sending a read request, followed by the address of the first instruction.

Now the issue is this address request (corresponding to the address of the first instruction) sent by the SPI interface of the uController is 0x100000. This is the case, because the PROG_ADD_RESET of my uControllerr is hardcoded to 0x100000.

I am not sure whether I gave you a better picture ?


#6

Thank you… I now understand better. The flash map (according to the meta-data is the following
(tinyprog -m)

[
  {
    "boardmeta": {
      "name": "TinyFPGA BX",
      "fpga": "ice40lp8k-cm81",
      "hver": "1.0.0",
      "uuid": "8617ef5d-bf65-4118-97ee-ff1487b963dc"
    },
    "bootmeta": {
      "bootloader": "TinyFPGA USB Bootloader",
      "bver": "1.0.1",
      "update": "https://tinyfpga.com/update/tinyfpga-bx",
      "addrmap": {
        "bootloader": "0x000a0-0x28000",
        "userimage": "0x28000-0x50000",
        "userdata": "0x50000-0x100000"
      }
    },
    "port": "/dev/ttyACM0"
  }
]

and your start address is excactly the end address of the usedata section. so… a little more research is needed to know if it is possible to grow of move the data section. If the user data would be in 0x100000 + range the code fetch should work correct?


#7

Exactly ! it should work. That’s what I am trying to figure out.