- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi I have a question regarding to interfacing with narrower or wider width of slave. As we know, our Nios II is 32-bit width. To perform a read/write to a slave, says a 16-bit memory, how should this be done in software using IO macros? FYI, my 16-bit memory controller can be either the ssram controller or sdram controller available in SOPC Builder or Qsys. Thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The SOPC builder will include a 'bus width adapter' between the nios cpu and any 16bit slave. This automatically generates two 16bit slave cycles for each master cycle. The code is the same.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks dsl for your quick answer. Do you mean I'm going to use IOWR_32DIRECT(_BASE, 0, 0x12345678);?
In fact, I have another project which needs to use my own custom memory controller. Unfortunately, it does not have byte-enable signal. Do you have any advice for me? Thanks again.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IOWR_32DIRECT() probably maps down to the correct instruction :-)
If it is 'normal' memory, you'll have to support byte enables - otherwise single byte writes won't work, even for a 16bit write you'll see two writes one will have neither byte enable asserted! For memory mapped io buffers it is usually best to create a 32bit slave that hard-wires d16-31 to zero for reads.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In your Nios bsp project, check out
HAL/inc/io.h
/* Dynamic bus access functions */
#define
__IO_CALC_ADDRESS_DYNAMIC(BASE, OFFSET) \
((void *)(((alt_u8*)BASE) + (OFFSET)))
#define
IORD_32DIRECT(BASE, OFFSET) \
__builtin_ldwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
#define
IORD_16DIRECT(BASE, OFFSET) \
__builtin_ldhuio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
#define
IORD_8DIRECT(BASE, OFFSET) \
__builtin_ldbuio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
#define
IOWR_32DIRECT(BASE, OFFSET, DATA) \
__builtin_stwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
#define
IOWR_16DIRECT(BASE, OFFSET, DATA) \
__builtin_sthio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
#define
IOWR_8DIRECT(BASE, OFFSET, DATA) \
__builtin_stbio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
/* Native bus access functions */
#define
__IO_CALC_ADDRESS_NATIVE(BASE, REGNUM) \
((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8))))
#define
IORD(BASE, REGNUM) \
__builtin_ldwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM)))
#define
IOWR(BASE, REGNUM, DATA) \
__builtin_stwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM)), (DATA))
I think the "16" macros variants eliminate double reads and writes to a 16 bit slave. Like dsl said, you will still need to use byteeanble signals to control byte-wide writes (if you want to use IOWR_8DIRECT). I also think that IOWR_32DIRECT will actually give you two writes to a 16 bit slave, with the two byteenables ALWAYS asserted. That just makes more sense to me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The double read behavior depends on the tools and IP being accessed.
In SOPC Builder if you perform a 32-bit access in your code to a 16-bit slave two things could happen: Slaves that uses native addressing (no byte enables) --> a single access occurs and the upper 16-bits drop off during writes or get zero padded on reads. Slaves that use dynamic addressing (byte enables) --> two accesses occur at the two 16-bit locations being accessed. In Qsys there is only dynamic addressing so any native slave gets treated as a 32-bit slave port and the accesses behave as if there were byte enables present in the slave. So in that case if your slave port was native and 16-bit and Nios II performs a 32-bit access you'll end up with two accesses regardless if the slave used native addressing or not. At the end of the day my advice is to avoid native addressing at all costs since the behavior changes in Qsys and native addressing also becomes limiting in cases where the master and slave do not match in width (like a 64 bit master accessing a 32 bit slave).- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page