Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Intel Support hours are Monday-Fridays, 8am-5pm PST, except Holidays. Thanks to our community members who provide support during our down time or before we get to your questions. We appreciate you!

Need Forum Guidance? Click here
Search our FPGA Knowledge Articles here.
12410 Discussions

Lightweight HPS to FPGA Bridge register accessses not working

Honored Contributor II



I created a System in Qsys with a slave-template from Altera and offset it to base 0x10000 relative to lightweight H2F bridge. (image1) 


In Quartus I connected the SoC-System outputs of the slave-template. (image2) I got 2 r/w registers configured in the slave-template wizard in qsys. 

Since the slave-template gives me the std_logic_vectors for in and outbound data, i just inserted a loopback and made reg0 output what was input into reg0. the same for the second register. 


Now as I understood, the lightweight AXI is 32bit width. Is the addressing byte- or wordaddressing? 


In my baremetal program I do the following first: 

# define LWHPS2FPGA_BRIDGE_BASE 0xFF200000 //lightweight h2f bridge base# define test_out_base 0x10000 //offset of the qsys avalon slave component (slave-template) 



volatile unsigned int *reg0 = (volatile unsigned int *)LWHPS2FPGA_BRIDGE_BASE + test_out_base; //first register 

volatile unsigned int *reg1 = (volatile unsigned int *)LWHPS2FPGA_BRIDGE_BASE + test_out_base+2; //second register when word-addressing 

volatile unsigned int *reg2 = (volatile unsigned int *)LWHPS2FPGA_BRIDGE_BASE + test_out_base+4; //second register when byte-addressing 


I always read 32bit as I am using unsigned int*, do I have to read 8bit instead by using char*? I tried it, but it did not work, too. 

Then I'm writing/reading regs like: 


getc(); //wait for button 

*reg0 = 0x12345678; 

puts("put 0x12345678 to reg0 ... read now?\n"); 


printf("reg0: %x\n",*reg0); 


I did the same for *reg1 and *reg2. but no matter what I write into the registers, whenever I read them, they are 0. 


What am I missing/messing up here? 


Thanks for every hint!
0 Kudos
3 Replies
Honored Contributor II

okay, when I use the AXI h2f_master instead of the lightweight AXI, all is working. the only thing i changed is: hook up the slave template component in qsys to h2f_master instead of lw_h2f_master and for the addresses in the baremetal app I used 0xC0000000 instead of 0xFF200000 as the bridge base. since I'm booting from FPGA, I know that h2f full bridge is configured correct, cause it's loading the preloader from on-chip-memory. 


So the question is: do I have to take the h2f lightweight bridge out of reset or configure it somehow? I thought qsys is handing this config info to the preloader generation process when I setup the lightweight bridge in the HPS component in qsys?
Honored Contributor II

ok, forget my last post. it's still not working. the values are saved, but they are even saved when i remove my loopback for the slave template in/out std_logic_vectors. so i probably write to the on-chip-memory here which begins at 0xC0000000. but WHY? I am writing to volatile unsigned int *reg0 = H2F_BRIDGE + test_out_base; where# define H2F_BRIDGE 0xC0000000 and# define test_out_base 0x10000. this should be outside the address range of the on-chip-memory and 0x10000 is the offset of the slave template qsys component. 


I don't get any further. this should be one of the simplest tasks to implement, I really would like to start developing, but I cannot seem to get beyond this. Can anyone help me please? I know I am missing something obvious.
Honored Contributor II

okay, solved the problem, either nobody is reading my threads or nobody has experience with pointers or I'm just a noob, everybody is laughing at. 

I don't care, maybe someone can make a use of this: 


volatile unsigned int *reg0 = (volatile unsigned int *)LWHPS2FPGA_BRIDGE_BASE + test_out_base; 


this is equivalent to reg0 = (volatile unsigned int *)( LWHPS2FPGA_BRIDGE_BASE + (test_out_base * 4) ); 


because increasing an int pointer adds + 4 (since int are (often) 4byte type) to the stored address. 


all I had to do was add brackets to make the addition happen before casting one summand: 


volatile unsigned int *reg0 = (volatile unsigned int *)(LWHPS2FPGA_BRIDGE_BASE + test_out_base); 


thank you larso for helping me out! 

you're welcome larso! 

happy xmas, hanuka, kwanzaa, whateveryoulike to everyone.