Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
16 years ago

How the avalon mm slave "address alignment" works?

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.

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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 :(
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- 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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.