FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6359 Discussions

Wrong address range for custom IP in SOPC

Altera_Forum
Honored Contributor II
2,150 Views

Hello guys, 

 

I would pls like a hint or a wise word on this funny issue that I have related to address ranges. 

 

In detail, I have designed my own custom IP core that is a simple slave for the avalon bus. Its like an on-chip ram, but its not a RAM it has some other logic as well.  

 

This IP core has an address port ADDRESS_PORT(8 DOWNTO 0). So that is 9 bits for addressing, in other words I want to address 512 words of RAM. The funny thing is that when I add my component on the SOPC builder along with a NIOS some RAM etc. and I do "auto assign base addresses" then the address range that is assigned for my component by SOPC is 12bits! 

 

Just to make it more clear, for example if the base address for my component is 0x1000 then the range assigned by SOPC to the component is: 

 

0x1000-0x1FFF! That is 12 bits right? I'm expecting something like that: 

0x1000-0x11FF...so 9 bits=512words. 

 

What seems to be wrong? Why the SOPC cannot understand the address range correctly since my address port is 9 bits? 

 

 

Thank you for your help!!
0 Kudos
24 Replies
Altera_Forum
Honored Contributor II
831 Views

NIOSII has 4 KByte page and frame size. I guess, your "like an on-chip ram" core just mapped into one mem-page. 

 

Digitally yours, 

Mixa
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Hello cms, 

thank you for your time replying! 

 

What you are saying makes sense, since with 12bits one can address a 4kB RAM. 

 

Supposing that this is true, how is the system going to operate correctly? I mean what happens if NIOS tries to write something at an address beyond 512? 

 

Is this the correct or natural way? Is there any way to map my core at only 9bits? 

 

Also, if i remove NIOS will the address mapping become "as expected" (of course there will be no master then...) 

 

Thanx!
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Oh.. and another question :) 

 

If, you are implying that the minimum addressing is according to the mem page of NIOS then why when I connect a couple of switches (16) the addressing is correct? (0x1000-0x100F 4bits) 

 

thx
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

The way I understand it, the address lines to a NIOS component represent a word address. So a 9 bit address bus will give you 512 words. Assuming a word size of 32 bits, 512 words is 2048 bytes. Assuming a base address of 0x1000, the range would then be 0x1000-0x17FF. 

 

When working with custom components I have also found the address range does not always come out as expected. I haven't verified this, but I suspect when you edit a component to reduce the size of the address bus, the range used in the memory map is not automatically reduced accordingly. To fix this I have either edited the .tcl file manually (this can be dangerous unless you are really sure what you are doing) or recreated the component from scratch.
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Hi kevin! Thx for your time! 

 

After reading your reply I really think that I'm missing something here...related to how NIOS addresses registers in a slave component eg RAM. 

 

Are u implying that NIOS addresses bytes(8bits that is) instead of a whole word? 

 

To make things clearer with my custom IP, you may consider it as an on-chip RAM which consists of 512words and each word has 64bits. 

 

Now, if, ccording to your reply, NIOS addresses bytes then what I get as address range maked perfectly sense since 512words of 64bits each is 512x8= total=4096 8-bit words. So... if NIOS addresses bytes of course we need 12bits for the address range! 

 

But then the whole thing is messed up in my mind! Certain questions arise: 

 

1) How are these 12bits are physically implemented since I only provide an ADDRESS_PORT of only 9 bits? 

 

2)If we assume the above "magically solved" then does it mean that NIOS needs 8cycles to read a single 64bit RAM word?! In other words does NIOS have to give 8 addresses to the address port to get a word(64bits)?? 

 

3) Is the "byte_enable" signal that exists in the avalon_slave interface related to this?? 

 

How are all these issues handled? Any documentation? 

 

 

Thank you for your help in advance!! This thing is starting to get much more interesting and difficult than i imagined!
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

The addresses shown in SOPC builder are byte addresses. In your C code, components are also accessed using byte base addresses. 

 

However, components are at a low level accessed by the word. The LSB's of the byte address are always assumed to be zero which is why you don't need enough address lines for each byte in the range. The physcial address port uses word addresses. 

 

If a master needs to read less than one word, then the byte_enable signals come into play. However, I am fairly new to this myself, so I don't know exactly how this works. I also have no experience with using 64 bit words, so I am not 100% sure how that will play into you situation.
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

I'm not even going to bother reading the other replies. How wide is your data bus? This may actually matter. Also, what version of the tools are you using? 

 

You need to make your data bus 32-bits wide regardless of whether you are using all 32-bits or not. This will make your life easier as the NIOS has a 32-bit data bus. If you've got a 9-bit address bus you should end up with 11 bits of address space in SOPC builder. The reason for this is that address is space in SOPC builder is byte addressed. So for each 32-bit word of address in your component you have 4 byte addresses. You don't need to think about this when writing your C code. Altera provides the IOWR and IORD macros. So to write or read to/from your component: 

 

IOWR(MY_IP_BASE, <some register address>, <new_data>); 

and 

IORD(MY_IP_BASE, <some register address>) 

 

The IOWR and IORD macros will convert your desired register address to a byte address and perform the transaction. 

 

I have written hundreds of SOPC custom components so I have a fairly firm grasp on how things work.  

 

Now as to why you have 12-bits of address space instead of 11. I've only seen this in one case. There used to be a setting for custom user components that specified the addressing scheme (DYNAMIC or NATIVE). I won't go into what that means. Anyway, that setting was deprecated in 7.1 of the tools. With the newer tools (like 8.0 and newer), if the component was somehow set to use the deprecated NATIVE addressing scheme, it would give two extra bits of address space to the component. I'm not sure if this is what is happening to you but if it is then I would guess your data bus is 16-bits wide and you somehow have the deprecated NATIVE parameter assigned to your avalon slave interface. 

 

Jake
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Thank you all for your replies! 

 

I have fully understood why i need 12bits of addressing in the SOPC to address my custom IP. 

 

As said, my IP has 512words of 64bits each. So physically it needs 9 bits for addressing. These bits ARE provided by the SOPC. 

 

NIOS uses dynamic addressing for avaon bus components, since NIOS is 32bits and the components connected to the bus might be 16,or 64 like my case or whatever. In order to make programmers lives easier, NIOS addresses bytes! 

 

So 9bits out of the SOPC address line go to the physical address_port of my custom IP and the rest 3bits are picking up the bytes out of the 64bit word coming out on the avalon bus by my IP. 2^3=8 64bits=8x8bytes. 

 

As I understand it NIOS presents the 9bit address on the custom IP address_port, then the 64bit word comes out and then using the extra 3 bits NIOS fetches the word in 8 cycles, 1byte each cycle.
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

You seem to understand why there is 12 bits of address lines to your component, but I think there is still some confusion on how the component is actually accessed. 

 

To read 64 bits from you component, I think NIOS will perform this in two 32 bit cycles. 

 

Try synthesizing the simplest test case you can and then look at the RTL viewer. This can often clear up what is going on at a low level. I just tried this for a simple system with a NIOS processor and a 64 bit wide component. If you trace the 64 bit bus from the component, what you will find is that it is split into two 32 bit halves and fed input a 2:1 mux. The mux is controlled by bit 2 of the address bus.
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Hey everyone.. i am fairly new to Nios II. I have built a custom SOPC component.. now i know i can use IORD and IOWR for accessing data to and from the component...  

my problem is well i am unable to write more than one value to my component. for my design i need to write two values and read two values each of 32 bits. Tested the read for one value and it works but unable to read the next value. 

Please do help me out..  

 

Thanks you all..
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Could you post some of your source code? (address decoding for the VHDL/Verilog part, IORD/WR calls for the software part) It would help us finding out what's wrong.

0 Kudos
Altera_Forum
Honored Contributor II
831 Views

 

--- Quote Start ---  

Could you post some of your source code? (address decoding for the VHDL/Verilog part, IORD/WR calls for the software part) It would help us finding out what's wrong. 

--- Quote End ---  

 

 

hey Daixiwien, 

 

i am attaching a test code to show what i have been trying to do  

 

input read;  

output [31:0] read_data; 

output [31:0]qx,qy 

 

always @ (posedge CLOCK_50) // each 20nsec  

 

 

begin  

 

qx= 0XAAAA; --------------------> output1 32 bits  

qy= 0XBBBB; ------------------> output 32 bits  

 

 

read_data = qx; 

read_data = qy; 

 

 

end  

 

endmodule  

 

 

S/w part: 

 

 

//SCALAR_POINT_INST - user component name // 

 

 

 

# define user_comp_read IORD(scalar_point_inst_base,0)  

 

unsigned short int yy; 

 

 

//---------------------------------------------------------------- 

// MAIN PROGRAM  

//---------------------------------------------------------------- 

int main(void) 

 

 

yy = user_comp_read;  

printf("\n data is %#x \n",yy); 

 

 

 

 

 

so this basically reads one value.. i know there must be a simple way to get this working its just that i am new to this and having difficulties. 

 

I have only included the read part right now ..  

 

if you could guide me through it would be great.. also some tips on write also would b great..
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

hey guys figured out where i was going wrong it was the data type i had assigned for it was wrong 'short' was creating all the problems for me ..  

 

 

thanks u all
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

To be able to read two different 32-bit registers, you need to do some address decoding in your verilog code. For example you could assign read_data to qx if the address is 0 and to qy if the address is 1. Then from your software you can access them with IORD(SCALAR_POINT_INST_BASE,0) and IORD(SCALAR_POINT_INST_BASE,1).

0 Kudos
Altera_Forum
Honored Contributor II
831 Views

 

--- Quote Start ---  

To be able to read two different 32-bit registers, you need to do some address decoding in your verilog code. For example you could assign read_data to qx if the address is 0 and to qy if the address is 1. Then from your software you can access them with IORD(SCALAR_POINT_INST_BASE,0) and IORD(SCALAR_POINT_INST_BASE,1). 

--- Quote End ---  

 

 

hey Daixiwen, thanks for the reply... 

 

i used case statement for my address decoding, thanks alot for your reply it does clarify things.. 

 

.. i guess the same would work for write also ... right ??  

i could use if statements and assign write_data to 3 different registers ... right ?? 

 

 

thanks again
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

Yes, exactly.

0 Kudos
Altera_Forum
Honored Contributor II
831 Views

hey Daixiwen sorry to trouble you again i seem to be having problems with reading / writing... more than one value i have no clue why i have tried everything possible the code works well as long as its only one value being written or read as soon as i change that to more than one i start getting garbage values. i implemented the address logic like u said.. i have pasted the test code here again please let me know if what i am doing is right or wrong ...  

 

////////////////////////////////// here is the C code in Nios 2 /////////////// 

 

 

int main(void) 

 

 

printf("enter the values to be passed\n"); 

for(i=0;i<1;i++) 

scanf("%d",&k); 

iowr(scalar_write_inst_base,i,k); 

yy= iord_32direct(scalar_write_inst_base,i) ; 

printf("\n output data is %#x \n",yy); 

 

//////////////////////////// verilog test code/////////////////////////////// 

 

input [1:0] addr_off; ---- for address decoding logic 

reg [31:0] qx,qy; 

reg[31:0] temp; 

input[31:0] write_data; 

output[31:0] read_data;  

always @ (posedge CLOCK_50) 

begin 

if(addr_off==0) 

begin  

qx = write_data; 

read_data = qx; 

end 

else if (addr_off==1) 

begin  

qy= write_data; 

read_data=qy; 

end  

end // always 

 

/////////////////////////////// end ////////////////////////////////////////// 

 

the same code works if i just have one value to read or write but fails if more than 1 which makes me think there is some problem in the address decoding or in the S/w access side..  

 

Please do let me know what am i doing wrong.. 

 

Or is there something else i should be taking into account and i havent ??  

 

Thanks again..
0 Kudos
Altera_Forum
Honored Contributor II
831 Views

You must also have some 'read' and 'write' inputs. You should especially only perform the transfer from writedata if the "write" signal is 1. If you don't you can write garbage.

0 Kudos
Altera_Forum
Honored Contributor II
831 Views

 

--- Quote Start ---  

You must also have some 'read' and 'write' inputs. You should especially only perform the transfer from writedata if the "write" signal is 1. If you don't you can write garbage. 

--- Quote End ---  

 

 

hey Daixiwen.. i do have read and write day guess i forgot to include that in the code but i had not implemented the condition.. 

 

so you mean to say if write bit is set to 1 then a write transfer should take place write ?? 

 

btw.. i did try a few things yesterday and found out it was my width of address signal that was causing all the problems made it 8 now and the read write for more than 1 is working now .. 

 

but yes will include the new condition of when write and read signal is one only the transfer should take place.. 

 

Thanks again...
0 Kudos
Altera_Forum
Honored Contributor II
782 Views

 

--- Quote Start ---  

To be able to read two different 32-bit registers, you need to do some address decoding in your verilog code. For example you could assign read_data to qx if the address is 0 and to qy if the address is 1. Then from your software you can access them with IORD(SCALAR_POINT_INST_BASE,0) and IORD(SCALAR_POINT_INST_BASE,1). 

--- Quote End ---  

 

 

 

hey i guess i am back with another doubt .. i am able to now write to the component but i am just using the same offset i.e. 0 and i have used flags in verilog to identify the data and store appropriately.  

 

my problem is when it comes to read i tried using a count variable to provide delay so that the nios could read and print the values.. well it does that but the output is random what i mean is that at times its right and at times its wrong . I dont know why could any one tell me why ?? 

 

2nnd doubt: when i tried using different offsets for data as mentioned in the quote it works fine for offset 0 only and not any other. i defined address decoding using offsets in verilog but it didnt work. 

my basic doubt is do i have to write my own 'regs.h' file for my SOPC component if not could please some one help me out .. 

 

i guess the whole offset idea is not cear so could some one clarify this please..  

 

thanks alot  

 

if any
0 Kudos
Reply