Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12606 Discussions

How the avalon mm slave "address alignment" works?

Altera_Forum
Honored Contributor II
3,257 Views

Hi everyone 

I use avalon mm slave port with conduit to interface a 16bits peripheral, 

but everytime when i READ the peripgheral, the data readback can not in  

correct address when inspected in NIOS-IDE. 

for condition is :  

the peripheral address start from 0x0000(in byte), and have 4 date(16bits) to be read, the data and address offset in the peripheral is: 

addr.offset-> data 

0x0000 0x0011 

0x0002 0x0000 

0x0004 0x0808 

0x0006 0x080f 

 

but when i inspected in the IDE, the read back data with the address is: 

(the port baseaddress is start at 0x6000 and i use 3 address line here) 

addr-> data 

0x6000 ???? 

0x6002 0x1100 

0x6004 ???? 

0x6006 0x0000 

0x6008 ???? 

0x600a 0x0808 

0x600c ???? 

0x600e 0x080f 

(???? is un-correct data and not stable) 

 

in the avalon port definition, i made: 

1-read_n 

16-readdata 

1-CSn 

3-address 

and correspondly signal with a conduit interface to the peripharl. 

the address to the peripheral is: 

ADR0--not connected and set to 0 at the peripheral side! 

ADR1--peripheral adr1 

ADR2--peripheral adr2 

 

the peripheral has a BHn signal for High 8bit enable, and when BHn=0 with the  

addressline0=0 at same time, it can give 16bit out put at byte address N and 

N+1 at its 16bits datalines.  

 

is there anyone can tell me what is the problem?? or tell me what is the data appear in the avalon mm slave address lines when read.
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
1,267 Views

Given that the nios2 cpu always does 32bit memory accesses, and that these get converted into two 16bit cycles to access a 16bit target, it might be worth making your peripheral have a 32bit interface and just ignore the high bits? 

 

The 32bit MM bus doesn't have address lines for the bottom 2 address bits, writes use 4 byte enable lines, and (IIRC) reads are always 32bit. 

 

It might be that the ADR0 line corresponds to value 4.
0 Kudos
Altera_Forum
Honored Contributor II
1,267 Views

Sounds like you are finding out why native addressing is depreciated since the address offsets are fairly confusing when the master and slave widths do not match. My advice to all component developers is to make your slave port dynamic by including byte enables. Without byte enables your slave port is considered to be native and you will need to use this formula to access each word of the component: 

 

<master address> = <slave base address> + (<slave word offset> * <master data width in bytes>) 

 

Page 9 of: http://www.altera.com/literature/hb/qts/qts_qii54003.pdf
0 Kudos
Altera_Forum
Honored Contributor II
1,268 Views

Yes&#65292; I am try to change the port into a 32bits one, and there seems other problem on the read timing when i use the signaltapII to snap the singal, i will test

0 Kudos
Altera_Forum
Honored Contributor II
1,268 Views

did u already solved that problem ??? 

 

i m just trying to read from my own HDL but i dunno exactly how to use the adress 

 

i got more than 1 parameter where i would like to read/write from/to 

 

 

i m using the IORD_32DIRECT and IOWR_32DIRECT 

 

but the controll over the address don t work dunno why -.- 

sometimes it makes one thing sometimes not. 

at the moment i can read from RGB_ADDR but nothing else 

and i can write to GRAY and THREST but not to SCREENSHOT -.-  

 

before i had played a bit on the addresses i could set SCREENSHOT but couldn t read or write anything else ... 

 

HELP MEEEEE plz 

 

heres an example: 

NIOS II CODE:  

 

#define RGB_ADDR (0x01)# define SCREENSHOT (0x02)# define GRAY (0x03)# define THRESH (0x04)# define READOBJEKTX (0x08)# define READOBJEKTY (0x05)# define STARTFOUND (0x06)# define START (0x07) IOWR_32DIRECT(PICREADANDFIND_0_BASE,SCREENSHOT,0x00000001); IOWR_32DIRECT(PICREADANDFIND_0_BASE,GRAY,0x00000001); IOWR_32DIRECT(PICREADANDFIND_0_BASE,THRESH,0x00000001); start_found=IORD_32DIRECT(PICREADANDFIND_0_BASE,STARTFOUND); I_XYBILD = IORD_32DIRECT(PICREADANDFIND_0_BASE,RGB_ADDR); 

 

and the Code in Verilog: 

module( MYADDR, MYWRITEDATA, MYREADDATA, MYWRITE, MYREAD ); input MYADDR; input MYWRITEDATA; input MYWRITE; input MYREAD; output reg MYREADDATA; parameter RGB_ADDR = 8'h01; parameter SCREENSHOT = 8'h02; parameter GRAY = 8'h03; parameter THRESH = 8'h04; parameter READOBJEKTY = 8'h05; parameter STARTFOUND = 8'h06; parameter START = 8'h07; parameter READOBJEKTX = 8'h08; always@ (posedge CLK50) begin : AVALON_INTERFACE begin if(MYWRITE == 1'b1) begin case(MYADDR) SCREENSHOT : screenshotreg <= MYWRITEDATA; STARTFOUND: getStart <= MYWRITEDATA; GRAY: Grayreg <= MYWRITEDATA; THRESH: Threshreg <= MYWRITEDATA; default:; endcase end else if((MYREAD == 1'b1) ) begin case(MYADDR) RGB_ADDR: begin MYREADDATA <= {xstart}; end READOBJEKTX: begin MYREADDATA <= {xstart}; end READOBJEKTY: begin MYREADDATA <= {32'hFFF11FFF}; screenshotreg <= ~screenshotreg; end STARTFOUND: begin MYREADDATA <={31'h00,set_start}; end default: MYREADDATA <= 32'hFFFAAFFF; endcase end endmodule
0 Kudos
Altera_Forum
Honored Contributor II
1,268 Views

Since you are using the direct macros increment your address by 4 bytes since your slave port is 32-bits wide. So your addresses are: 0x0, 0x4, 0x8, 0xC, etc... 

 

My other recommendation is to include byteenables for your slave port. I normally ignore byte enables on reads if there are no side effects and just use them to register the individual byte lanes coming in. This will make your component more portable to other masters that may use a different data width. 

 

Last but not least make sure you declare your slave port to have 1 cycle of read latency since your read data is registered. Also from a coding perspective I recommend separating the register reads and writes. So have a process for registering the write data, and have another process to register the readdata. Normally I stick to one process per write register since it makes things much easier for making small changes and optimizations. If you want to see an example go ahead and send me a message with your email address and I can forward a component a threw together yesterday that should show this in the HDL.
0 Kudos
Altera_Forum
Honored Contributor II
1,268 Views

Hi 

thanks for ur help would be great if u can send me an example 

 

i don t understand why i have to use 0x0, 0x4, 0x8, 0xC, etc... 

 

but at all that i tried already and didn t worked aswell :/ 

 

i m using the offset adress only for intern adressfinding i don t access an RAM or something like that 

 

i only want to write or read different things from my own HDL to the NIOS 

 

i set the readlatency to 5 i ll try to set it to 1 maybe that helps 

 

and the main question 

 

i m using a 8 Bit Adress so i have HEX from 00 to FF 

if i m using now 8'h00, 8'h04, 8'h08, 8'h0C ... in the HDL do i give the adress the same in the NIOS ? or do i need there 0x00 0x01 and so on? or 0x00 0x04 0x08 ??? 

 

dunno sometimes i get an adress access but sometimes i don t dunno why :(
0 Kudos
Altera_Forum
Honored Contributor II
1,268 Views

 

--- Quote Start ---  

Hi 

thanks for ur help would be great if u can send me an example 

 

i don t understand why i have to use 0x0, 0x4, 0x8, 0xC, etc... 

 

but at all that i tried already and didn t worked aswell :/ 

 

i m using the offset adress only for intern adressfinding i don t access an RAM or something like that 

 

i only want to write or read different things from my own HDL to the NIOS 

 

i set the readlatency to 5 i ll try to set it to 1 maybe that helps 

 

and the main question 

 

i m using a 8 Bit Adress so i have HEX from 00 to FF 

if i m using now 8'h00, 8'h04, 8'h08, 8'h0C ... in the HDL do i give the adress the same in the NIOS ? or do i need there 0x00 0x01 and so on? or 0x00 0x04 0x08 ??? 

 

dunno sometimes i get an adress access but sometimes i don t dunno why :( 

--- Quote End ---  

 

 

Hi, what you what to do is a little different from what we are doing, if you want use the IORW and IORD, i think you can use the "address" whatevery you prefer to use, but when you want the addressing space of the peripheral become a part of the CPU`s data or instruction addressing space, then you can not use the macro anymore, you can just use the memory-mapped bus. 

To my problem, i am partly resovled, but not so satisfactory, i'd make a HDL to give more function to alignment the 16bits peripheral to a 32bits avalon master.
0 Kudos
Altera_Forum
Honored Contributor II
1,267 Views

The reason why I suggested 1 cycle of read latency is so that when the read event occurs you'll get the data exactly when it's been registered in your component. If these read events are infrequent then 5 would probably work but if that's not the case you might accidentally read old data when posting multiple accesses that are 5 cycles or closer together. 

 

So there are two formats for these cache bypassing macros: 

 

Native (IORD, IOWR) <-- Which I don't recommend for any new custom components since native addressing is deprecated. 

 

Dynamic (IOWR_8DIRECT, IOWR_16DIRECT, IOWR_32DIRECT, IORD_8DIRECT, IORD_16DIRECT, and IORD_32DIRECT) <-- Dynamic means that the component is byte addressable (has byte enables). 

 

The native macros use offsets based on word addressing of the slave port. So in this case IORD(base, 0), IORD(base, 1), IORD(base, 2) access words at addresses 0, 4, and 8 in your component. One key thing is that these offsets are based on the word size of the slave port and not the master so the bytes they access depend on the slave. This is why native addressing is deprecated since having the byte mapping change based on the slave width is a bit cumbersome. 

 

The dynamic macros use offsets based on byte addressing. So because your component is 32 bits wide each word is located on a 4 byte boundary. This means to access each 32 bit register in your component you need to access byte addresses 0, 4, and 8. Using the dynamic macros should be accompanied by slave ports that have a byte enable signal for data widths greater than 8 bits. 

 

So you are attempting to use dynamic addressing macros to access a native addressing component. Switching to 4 byte aligned offsets should correct any addressing issue so perhaps changing the read latency to 1 will solve whatever other issue you are facing.
0 Kudos
Reply