im-tomu / fomu-workshop

Support files for participating in a Fomu workshop
https://workshop.fomu.im
Apache License 2.0
162 stars 64 forks source link

wishbone-tool and CSRStorage access #154

Closed lromor closed 4 years ago

lromor commented 4 years ago

Hi,

I'm using the fomu hacker. I'm trying to achieve a read/write of some storage of arbitrary size.

For instance: https://github.com/lromor/fomu-workshop/tree/simple-regs-example/litex/examples/two_registers

I have two questions: 1) Those CSRStorage Signals, where are they stored? My guess is that they are simple registers attached to the wishbone bus and mapped to some address.

2) The wishbone-tool allows to read some the mapped memory as described in cat build/csr.csv What is the "granularity" of the wishbone bus? Say that I instanced, similarly to the example linked above, a CSRStorage(32) which is mapped at 0x60003000. After writing some values (wishbone-tool 0x60003000 0xffffffff) I would expect to read the same value with wishbone-tool 0x60003000. What I'm instead reading is:

Value at 60003000: 000000ff

Thanks,

-l

Could you help me understanding what's going on?

xobs commented 4 years ago
  1. CSRStorage signals each have a register equal to their storage size. In Verilog terms they have a "reg". In migen, they have a "Signal()". This sits on the CSR bus, which is mapped to Wishbone.

  2. In Foboot 1.x and 2.x, the csr bus is 8 bits wide. This is the default in litex. If you define a csr that's larger than 8 bits, the single logical register is split into multiple actual registers.

For example, if you create a CSRStorage that's 9 bits wide, you will get two actual registers: one that's eight bits, and one that's 1 bit. For a real world example of this, see the CTRL registers, which contain 32 bit logical values that are spread among 8 bit physical registers: http://rm.fomu.im/ctrl.html#ctrl-scratch3

As for their actual address, each csr top level Module gets its own range.

You may want to look into documenting your project to get a better idea of how it's laid out.

lromor commented 4 years ago

Thank you for the detailed answer. One last question I forgot to ask which I still cannot connect with your answer:

As for their actual address, each csr top level Module gets its own range.

So in my case I should have 4 8-bit registers mapped. Those registers are not listed in the .csv file, I was expecting them to be one next to each other but instead the addresses 0x60003000, 0x60003001, 0x60003002, 0x60003003 are all returning the same value which is quite unexpected.

xobs commented 4 years ago

For 32-bit Wishbone, the address line is actually 30 bits. Then there is a four bit mask called "SEL" that indicates which of the last two bits are valid. For example, if you do an eight bit write to 0x60003002, then SEL[2] would be 1 and all other bits would be 0. If you do a sixteen bit write to that address, then SEL[2] and SEL[3] would be 1.

That's how Wishbone works. But the bridge only supports 32-bit writes, so it takes the 30 bits of address and sets all four SEL bits.

I'm unsure of how it's wired up in the csr bridge, but I suspect it also ignores the SEL lines.

lromor commented 4 years ago

I see, so the way to fix this is to use "fields". In this way I can map with the proper granularity my CSRStorage with greater size. Like this: https://github.com/im-tomu/foboot/blob/57f7a8bb95eec058efe2a748f46d3fd44983b3d0/hw/rtl/picorvspi.py#L13-L17