Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
1,836 Views

Creating Memory device for Nios II processor

Hello, 

 

I want to transfer data from my custom component to the processor. Ideally it would be possible to access the data using pointer. Normally I would have to use IORD and IOWR macros to circumvent the caching of the processor. 

 

I plan to implement the interface as an Avalon MM slave interface. If I add a new memory device in the "Linker Script" section will it it possible to access the region using pointers then? 

 

Can I declare the interface as an memory device in the TCL script of my component? 

 

Are there any prerequisites to use the interface as a memory device, e.g.: 

-must the interface expose both a read write port (I only want to read data from the interface) 

-does the interface have to support pipelined transfers, bursting? 

 

 

Best regards 

Martin
0 Kudos
11 Replies
Altera_Forum
Honored Contributor I
64 Views

Use DMA for that. If You're using Avalon-ST, then use SGDMA, if not, there's simple DMA.

Altera_Forum
Honored Contributor I
64 Views

Is there a specific reason for using the DMA controller instead of declaring the interface as a RAM module? The data I want to access is stored in on-chip memory. In SOPC builder / Qsys there is a on-chip memory available so this should be pretty similar. The most obvious difference for me would be that I would use one port of the dual port to interface with my custom logic and the other port would be used to interface with the Nios II processor.

Altera_Forum
Honored Contributor I
64 Views

Well You can give it a try, but I doubt it will be 100% ok. That's why DMA is used.

Altera_Forum
Honored Contributor I
64 Views

That doesn't sound too promising....

Altera_Forum
Honored Contributor I
64 Views

I'd use Avalon-ST and SGDMA. Proven to work :)

Altera_Forum
Honored Contributor I
64 Views

Hi Martin, 

I think Socrates is somehow misleading you. The point is not DMA. 

DMA is simply a method used to transfer data from one slave memory device to another. 

Any slave device (MM or streaming) can be used both with DMA and normal memory access; the difference is that DMA exploits an external master engine (independent from cpu) to transfer data from one location to another, while in usual memory transfers the bus master is the cpu itself which performs the same operations. 

Then, IORD/IOWR can be also performed by equivalent pointer operations. 

If you need to bypass cache you simply need to raise address bit 32. 

Example: 

IOWR(MM_BASE,offset,data); 

is equivalent to: 

int * addr = MM_BASE+offset 

*addr = data; 

 

data = IORD(MM_BASE, offset); 

is equivalent to : 

data = *addr; 

data = *(addr | 0x80000000); // the same as above, with cache bypass 

 

Regarding the other questions: 

- yes, you can have a read only interface.  

- support for burst tranfers is not mandatory; I'm not sure but I believe you specify the burst support feature in the tcl script of the sopc/qsys component. Pipeline is usually managed by a specific adapter component inserted between the Avalon bus and the MM slave. 

 

Regards
Altera_Forum
Honored Contributor I
64 Views

Well I did that for purpose. Getting into the wrong area using a pointer is quite easy. Plus a DMA will give interrupt when data is ready, so You won't get the same result by reading the same value over and over again.

Altera_Forum
Honored Contributor I
64 Views

If the data is already inside an onchip memory in the custom designed component it's a lot easier to access it directly through an Avalon MM slave interface than by using a DMA. 

StMartin81, you don't need to edit the linker script. This would only be necessary if you wanted to place static variables in that area, which isn't what you want to do. 

The address for your slave interface will be defined in system.h as a componentname_BASE constant, and you can use it either with a pointer or the IORD/IOWR macros, as explained by Cris72. 

If you plan to use pointers, be careful with the data cache. Either invalidate the cache before reading the data, or change the pointer into a uncached pointer (by setting bit 32 as explained by Cris72 or by using the alt_remap_uncached() function). The IORD/IOWR automatically bypass the cache.
Altera_Forum
Honored Contributor I
64 Views

IIRC the nios cpu itself doesn't do burst transfers (except optionally for cache line transfers) so you don't need to support them. 

 

If you are worried about the performance of the generated code. You'll get the best code by defining a 'global register variable' to point to a 64k block of address space than contains all the IO (and maybe memory) registers. 

Using %gp will generate slight worse code - even with the compiler patches I wrote to enable structure accesses relative to %gp (%gp relative arrays are always worse than global register relative arrays). 

In the latter case you do need to use the linker script to assign 'static' addresses to your IO locations.
Altera_Forum
Honored Contributor I
64 Views

 

--- Quote Start ---  

IIRC the nios cpu itself doesn't do burst transfers (except optionally for cache line transfers) so you don't need to support them. 

 

--- Quote End ---  

 

 

Afaik it does if You enable them. It also creates a bunch of burst adapters then.
Altera_Forum
Honored Contributor I
64 Views

Short update if anyone stumbles upon this thread. I've attached my module as a memory device to the Nios II processor. The magic is that you have to define the device as a memory device in the _hw.tcl script. 

 

Before reading from the device you have to flush the processor read cache for that memory region: 

alt_dcache_flush_no_writeback((void *) <address of burst IF>, <length of burst IF memory region in bytes>); Regards 

Martin
Reply