Forum Discussion

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

QUARTUS 4.2 NIOS 1.1 UPDATE PROBLEM

After update to Quartus 4.2 and Nios 1.1

I have a problem with an 8-Bit Slave (user logic)

the adress lines are connected as follows

CPU A 9 8 7 6 5 4 3 2 1 0

8-BIT SLAVE A 7 6 5 4 3 2 1 0 - -

with Quartus 4.1 NIOS 1.0

data was written and read with

IOWR(baseadd,add,data);

IORD(baseadd,add);

everything worked fine.

after update to Quartus 4.2 NIOS 1.1 I've get the following wrong values

at the address lines.

by using IORD:

BYTE hfce1_read(HFCE1 *pi,BYTE add) {

BYTE data;

data=IORD(pi->baseadd,add);

return data;

}

0x0080d0e8 <hfce1_read>: addi sp,sp,-12

0x0080d0ec <hfce1_read+4>: stw fp,8(sp)

0x0080d0f0 <hfce1_read+8>: mov fp,sp

0x0080d0f4 <hfce1_read+12>: stw r4,0(fp)

0x0080d0f8 <hfce1_read+16>: mov r2,r5

0x0080d0fc <hfce1_read+20>: stb r2,4(fp)

0x0080d100 <hfce1_read+24>: ldw r4,0(fp)

0x0080d104 <hfce1_read+28>: ldbu r2,4(fp)

0x0080d108 <hfce1_read+32>: slli r3,r2,2

0x0080d10c <hfce1_read+36>: ldw r2,4(r4)

0x0080d110 <hfce1_read+40>: add r2,r3,r2

0x0080d114 <hfce1_read+44>: ldwio r2,0(r2)

0x0080d118 <hfce1_read+48>: stb r2,5(fp)

0x0080d11c <hfce1_read+52>: ldbu r2,5(fp)

0x0080d120 <hfce1_read+56>: ldw fp,8(sp)

0x0080d124 <hfce1_read+60>: addi sp,sp,12

0x0080d128 <hfce1_read+64>: ret

(A2 of CPU is connected to A0 of slave)

CPU A 9 8 7 6 5 4 3 2 1 0

8-BIT SLAVE A 7 6 5 4 3 2 1 0 - -

add=0x04 0 0 0 0 0 0 0 1 0 0 (measured CPU Address bus)

if I read e.g. add=0x04, the address bus of the cpu is 0x??????04

and this is add=0x01 at slave, which is wrong

-------------------------------------------------------------------------------

part from ptf file

MODULE HFCE1_0

{

class = "altera_avalon_user_defined_interface";

class_version = "2.5";

SYSTEM_BUILDER_INFO

{

Instantiate_In_System_Module = "0";

Is_Enabled = "1";

Date_Modified = "--unknown--";

View

{

MESSAGES

{

}

Is_Collapsed = "1";

}

Clock_Source = "clk";

}

WIZARD_SCRIPT_ARGUMENTS

{

Imported_Wait = "0";

Nios_Gen_Waits = "1";

Simulate_Imported_HDL = "0";

Port_Type = "Avalon Slave";

HDL_Import = "0";

Timing_Units = "ns";

Unit_Multiplier = "1";

Setup_Value = "40";

Hold_Value = "40";

Wait_Value = "160";

Address_Width = "32";

Module_List = "";

Show_Streaming = "1";

Show_Latency = "0";

Technology = "User Logic";

File_Count = "0";

Port_Count = "6";

Component_Desc = "HFCE1";

Module_Name = "";

}

SLAVE avalonS

{

SYSTEM_BUILDER_INFO

{

Bus_Type = "avalon_tristate";

Address_Alignment = "native";

Address_Width = "8";

Data_Width = "8";

Has_IRQ = "1";

Base_Address = "0x00903000";

Has_Base_Address = "1";

Read_Wait_States = "160.0ns";

Write_Wait_States = "160.0ns";

Setup_Time = "40.0ns";

Hold_Time = "40.0ns";

Is_Memory_Device = "0";

Uses_Tri_State_Data_Bus = "1";

Is_Enabled = "1";

MASTERED_BY ext_ram_bus/tristate_master

{

priority = "1";

}

IRQ_MASTER cpu/data_master

{

IRQ_Number = "4";

}

}

PORT_WIRING

{

PORT address

{

direction = "input";

width = "8";

type = "address";

is_shared = "1";

}

PORT write_n

{

direction = "input";

width = "1";

type = "write_n";

is_shared = "1";

}

PORT read_n

{

direction = "input";

width = "1";

type = "read_n";

is_shared = "1";

}

PORT data

{

direction = "inout";

width = "8";

type = "data";

is_shared = "1";

}

PORT chipselect_n

{

direction = "input";

width = "1";

type = "chipselect_n";

}

PORT irq_n

{

direction = "output";

width = "1";

type = "irq_n";

}

}

}

MASTER avalonM

{

SYSTEM_BUILDER_INFO

{

Bus_Type = "avalon";

Data_Width = "32";

Address_Width = "8";

Max_Address_Width = "32";

Is_Enabled = "0";

}

}

SLAVE ahbS

{

SYSTEM_BUILDER_INFO

{

Bus_Type = "AHB";

Has_IRQ = "0";

Has_Base_Address = "1";

Address_Width = "10";

Data_Width = "32";

Base_Address = "--unknown--";

Address_Alignment = "native";

Read_Wait_States = "0";

Write_Wait_States = "0";

Is_Enabled = "0";

}

}

MASTER ahbM

{

SYSTEM_BUILDER_INFO

{

Bus_Type = "AHB";

Address_Width = "32";

Max_Address_Width = "32";

Data_Width = "32";

Interrupts_Enabled = "1";

Irq_Scheme = "Individual_requests";

Is_Enabled = "0";

}

}

HDL_INFO

{

Imported_HDL_Files = "";

}

}

10 Replies

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

    Yes this was discussed in another thread. To solve this problem add an extra bit to the address width (called Address_Width) in the class.ptf file for that component. In Quartus 4.1 an extra bit was added to the address (one more then there should have been) and with Quartus 4.2 this is fixed (so if it was connected to that extra bit then it will not be connected after the upgrade). So when you make this change you are compensating by adding an extra bit (to get back to where you started with Quartus 4.1)

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

    Thanks for your reply,

    I&#39;m a little bit confused, what is wrong.

    First the part of the ptf file for this component is equal to that of Quartus

    4.1 (only one additional line " Clock_Source = "clk"; "

    looking at io.h

    ..

    /* 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))

    ..

    by using IORD(..)

    __IO_CALC_ADDRESS_NATIVE already makes a multiplication of register * 4

    the base adress of my component is 0x903000

    IORD(baseadd,0x01) results in __builtin_ldwio(0x903004)

    which should read Register 1 of my slave

    the first time I get A0=1 of my slave (A2 of CPU) is by reading

    IORD(baseadd,0x10) results in __builtin_ldwio(0x903040)

    but the addtress bus of the cpu is 0x????04

    Multiplication of all offsets by 4, before calling IORD is a workaround,

    but no slolution.

    is the above ptf file correct for this component ?

    is this a bug in SOPC Buider 4.2 ?

    Quartus 4.2 ?

    NIOS 1.1 ?

    is it only a project conversion problem from 4.1 to 4.2 ?

    (I regenerated the system in SOPC Builder 4.2 and recompiled with Quartus 4.2)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I&#39;m not happy with the update to Quartus 4.2 and NIOS 1.1

    I received the following answer from Altera for my problem with user logic,

    but I do not understand this answer.

    ------------------------------------------------------------------------------

    Problem:

    "Why does my embedded system fail to compile after upgrading to Quartus II

    version 4.2 due to an address width mismatch?"

    Solution:

    "In previous versions of Quartus II, SOPC Builder created an extra most

    significant address bit for registered slave peripherals (also called

    native peripherals) connected to an Avalon Tri-State Bridge. If this bridge

    has only native slave devices connected to it then some designers may have

    connected this extra address bit in their design to a peripheral. This extra

    address bit no longer exists if the embedded system is regenerated using

    Quartus II version 4.2. If a design is using the extra address bit and

    the Quartus II software is upgraded to version 4.2 then a compilation error

    will occur due to the most significant address bit not being connected.

    This issue can be corrected without the need to modify software or

    hardware interconnects. If the peripheral affected by this issue is connected

    to an interface to user logic, then increasing the address width by one

    (in the interface to user logic) will correct the issue.

    If the peripheral affected by this issue is a custom component,

    edit the "class.ptf" file for that component by increasing the value

    called "Address_Width" by one."

    ------------------------------------------------------------------------------

    1. the design could be regenerated and compiled with Quartus 4.2 without error

    2. the bridge has additional ram and flash connected.

    3. I entered 8 address bits in SOPC builder and I connected exactly 8 address

    bits from the address bus to my user logic. (which extra address bit ???, how

    can I see this in a shared address bus? )

    again:

    I have an 8 bit avalon register slave.

    address bus is shared with SRAM AND FLASH

    Address A[9..2] are connected to A[7..0] of 8 bit slave

    Interface to user logic:

    PORTNAME WIDTH DIRECTION SHARED TYPE

    address 8 input yes address

    write_n 1 input yes write_n

    read_n 1 input yes read_n

    data 8 inout yes data

    chipselect_n 1 input --- chipselect_n

    irq_n 1 output --- irq_n

    IORD and IOWR do not output the cortrect address on the bus.

    is this a bug in SOPC Buider 4.2 ?

    Quartus 4.2 ?

    NIOS 1.1 ?

    is it only a project conversion problem from 4.1 to 4.2 ?

    (I regenerated the system in SOPC Builder 4.2 and recompiled with Quartus 4.2)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This was an issue with the SOPC Builder that came with Quartus II version 4.1 The desciption that you were sent only applies if a user connected the extra address bit to the peripheral. When you upgrade to Quartus II version 4.2 that address bit is no longer present so you have two options. 1) The fix that was outlined in your correspondence from Altera, or 2) regenerate, connect the address bits correctly, and align your address space to the peripheral correctly in software(so I recommend you do the first one).

    Also as MiR stated, to talk to your peripheral you have to be word aligned, even though you are talking to an 8 bit peripheral, the data on the Nios II side is 32 bit. An example of this is if you have an 8-bit peripheral, and you talk to external native registers called "A", "B", and "C" with the base address of the peripheral specified at "base". Then you access the peripheral reading and writing at the following addresses:

    A <---> base

    B <---> base + 4 (next word)

    C <---> base + 8 (next word)

    So you may have run into either issue. If it looks like the address bits are properly aligned then the answer that you were sent from Altera was a different issue.

    I recommend looking at the link that MiR provided since there is a lot of discussion in their about this.

    Let us know if you are still running into problems.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Is the setting, which I made in SOPC Builder, wrong ?

    I only can say that I connected A9..A2 of the address bus(A22..A0) to A7..A0 of

    the 8 bit slave.

    The size of the address bus did not change with respect to Quartus 4.1

    (same problem as niosIIuser)

    A <---> base

    B <---> base + 4 (next word)

    C <---> base + 8 (next word)

    this should be done by (A=0,B=1,C=2)

    IORD(base,A) <--> base

    IORD(base,http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/cool.gif <--> base+4

    IORD(base,C) <--> base+8
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Ok, then this is correct you probably have run into the second issue I describbed. When I used +4 and +8 those are the word alignments on the Nios side, but the peripheral itself will be knocking off the two lsbs of the address. I have lost track in this long post what the peripheral is but I seem to recall it&#39;s some 8 bit native peripheral. Because it is an 8 bit device it byte offsets of 1, 2, and 3 all map to the same address on the peripheral side (you are just lining up the 8 lsbs of the data from the avalon bus to the 8 data bits of your peripheral so trying to write to bits 31..8 doesn&#39;t really make much sense). Here is an example that I hope clarifies this (well at least I attach a link to a document that explains this if my example doesn&#39;t do the job):

    I have some piece of logic that I want to connect to the interface to user logic. My data width is 8 bits, and I have 6 registers to write to externally.

    The IUL will connect address bits 5..3 from the avalon bus to bits 2..0 on the external interface (where you connect your hardware). So I would access these registers in my software from offsets of 0, 4, 8, 12, 16, 20. But on my external interface I&#39;ll see addresses of 0, 1, 2, 3, 4, 5 (because the avalon addresses 5..3 were mapped to external addresses 2..0). So address bits going from the avalon bus to the external bus are simply being shifted to the right by two bits (the two lsbs are not used because they are not necessary with a 32 bit master writing to an 8 bit slave).

    This may seem odd but it serves a very important purpose when it comes to masters of different widths trying to use a peripheral like this. Using that example lets say another master of only 16 bits is used. In this case to properly align the address bits only the first lsb will be knocked off (so an address shift by 1 bit to the right). The IUL knowns to do the proper shifting depending on the data width of the master (so with the 32 bit master it&#39;ll access offsets of 4, 8, 12, etc... and the 16 bit master will access the peripheral at offsets of 2, 4, 6, etc...) But looking at the external addresses going to the peripheral, the offsets will be always 1, 2, 3, 4, etc..... (so your hardware pepripheral is transparent to the width of the master).

    I recommend taking a look at this document "Avalon Bus Specification", http://www.altera.com/literature/manual/mn..._avalon_bus.pdf (http://www.altera.com/literature/manual/mnl_avalon_bus.pdf) <page 100>. It has a table showing what I explained, only it probably makes more sense since describing hardware in plain text is tricky.

    Let me know if this is making sense or I have just steered you down the wrong path further.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    the problem still exists, can someone from ALTERA please check what the problem

    is,

    setup of user logic wrong ?

    physical connection to 8 Bit slave wrong ?

    IORD, IOWR problem ?

    conversion problem ?

    the proposed workaround:

    multiply the register * 4 before calling IORD and IOWR, results in a multiplication

    by 16 for __builtin_ldwio ??? (see macro IORD in io.h)

    what will be a workaround, and what I have to change

    with next software version ?

    should I go back to Quartus 4.1 and NIOS 1.0 ???
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    IORD and IOWR does the multiplication by 4 for you (it&#39;s a macro). So if you use those then you don&#39;t need to multiply it (MiR was probably talking directly to the peripheral and had to do the multiplication factor of 4 manually).

    Can you probe the address pins and figure out what is coming out? If you write to the base address of the peripheral you should see an address of 0 come out of the system, if you write to base + 4 then you should see address 1 come out of the system, .... and so on.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    the adress lines are connected as follows

    CPU A[9..2] to

    8-BIT SLAVE A[7..0]

    BASE 0x903000

    correct behavior should be (is with Quartus 4.1 Nios 1.0) :

    function systemadd(CPU) add at slave

    IORD(BASE,0x00) 0x????00 0x00

    IORD(BASE,0x01) 0x????04 0x01

    IORD(BASE,0x02) 0x????08 0x02

    IORD(BASE,0x03) 0x????0C 0x03

    ..

    IORD(BASE,0x10) 0x????40 0x10

    wrong behavior is (measured):

    function ldwio r2,0(r2) systemadd(CPU) add at slave

    IORD(BASE,0x00) r2=0x903000 0x????00 0x00

    IORD(BASE,0x01) r2=0x903004 0x????01 0x00

    IORD(BASE,0x02) r2=0x903008 0x????02 0x00

    IORD(BASE,0x03) r2=0x90300C 0x????03 0x00

    IORD(BASE,0x04) r2=0x903010 0x????04 0x01

    (by debugging assembly code, i can see that r2 has the correct value before

    ldwio)