How to read and write an on-chip fifo from HPS / ARM?

I’ve seen a lot of examples for the doing LEDs and basic memory writes.

But is it possible to write and read from a FIFO in the fpga? I have the GSRD 16.1 of the arria 10 soc board and have added a fifo to the lightweight bridge alongside the sys_id module. But I can’t seem to write to it.

I’ve confirmed that I can read the sys_id using the alt_read_word(LW_BRIDGE_ADDR + SYSID_QSYS_0_BASE), so clearly my memory reads appears to be working.

Thanks for any help,
-Joe

Joe,

It is definitely possible to do. Verify the Qsys connections are made to the In & Out ports and note their addresses. The easiest interface to start with is the Avalon-MM input and Avalon-MM output. Writing a value to the input side should result in the fill_level increasing by 1. The fill_level can be read from offset 0x0 from the base address for the CSR registers port (out_csr, or in_csr depending on configuration).

The FIFO datasheet is: https://www.altera.com/en_US/pdfs/literature/hb/nios2/qts_qii55002.pdf

-S

It doesn’t seem to work. I can read the qsys_id, I can blink leds.

But I can’t write to a fifo and read from it, despite trying the same code.

I received a “Transparent bridge in fifo_0 of type altera_avalon_fifo is not yet supported” when creating the device tree using:
https://rocketboards.org/foswiki/view/Documentation/A10GSRDGeneratingTheLinuxDeviceTree

void * GLOBAL_LW_BRIDGE_ADDRESS;

int main(void) {
uint32_t * custom_led_map = 0;
volatile uint32_t * fifo_0_in = 0;
volatile uint32_t * fifo_0_out = 0;
volatile uint32_t * fifo_0_lvl = 0;
// The start address and length of the Lightweight bridge
#define HPS_TO_FPGA_LW_BASE 0xFF200000
#define HPS_TO_FPGA_LW_SPAN 0x1FFFFF
#define HPS_TO_FPGA_ON_CHIP_BASE 0xC0000000

extern void * GLOBAL_LW_BRIDGE_ADDRESS;
int devmem_fd = 0;

// Open up the /dev/mem device (aka, RAM)
devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if(devmem_fd < 0) {
    perror("devmem open");
    exit(EXIT_FAILURE);
}

// mmap() the entire address space of the Lightweight bridge so we can access our custom module
GLOBAL_LW_BRIDGE_ADDRESS = (uint32_t*)mmap(NULL, HPS_TO_FPGA_LW_SPAN, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, HPS_TO_FPGA_LW_BASE);
if(GLOBAL_LW_BRIDGE_ADDRESS == MAP_FAILED) {
    perror("devmem mmap");
    close(devmem_fd);
    exit(EXIT_FAILURE);
}

custom_led_map = (uint32_t*)(GLOBAL_LW_BRIDGE_ADDRESS + LED_PIO_BASE);
fifo_0_in = ( uint32_t*)(GLOBAL_LW_BRIDGE_ADDRESS + FIFO_0_IN_BASE);
fifo_0_out = ( uint32_t*)(GLOBAL_LW_BRIDGE_ADDRESS + FIFO_0_OUT_BASE);
fifo_0_lvl = ( uint32_t*)(GLOBAL_LW_BRIDGE_ADDRESS + FIFO_0_IN_CSR_BASE);

    // Turn all LEDs on
    *custom_led_map = 0xFF;
    *fifo_0_in = 0xFFFF;
    *fifo_0_in = 0xFFF1;
    *fifo_0_out = 0xEEEE;
    // Wait half a second
    usleep(500000);
    printf("custom leds: %x \n", *custom_led_map);
    printf("read lvl: %x \n", *fifo_0_lvl);
    printf("read out: %x \n", *fifo_0_out);

I didn’t recompile my Linux kernel, just used the GSRD one with the new device tree blob. Does that matter?

Not recompiling the Kernel shouldnt matter. I suspect it is something wrong with the way the bridges are setup and connected to the new FIFO. Hard to say without seeing it, can you post a screenshot of those connections and addresses?

Also, what are the address for the FIFO_0_xxx #defines, they didnt show up in the code above?

-S

I’m using arria10_hps_0.h:

#define FIFO_0_IN_CSR_BASE 0x40
#define FIFO_0_IN_BASE 0xc
#define FIFO_0_OUT_BASE 0x8

Found the issue.

I think the device tree compilation process didn’t quite get every step or an old load with compiled in and the dip switch was set to factory load.

A full re-compile + dip switch change appears to have fixed the issue.

josephmcg,
I too am trying to write unsigned 32 bit data to a register using c code while monitoring a buffer level. At the same time, I am trying to read those integer values from the buffer with the FPGA. I read the qii55002-9.1.0 and it is straight forward. Setting up parameters, writing values in a loop that is controlled by the buffer level in c code should be straight forward. When it gets to the Qsys part, I am lost as there are many memory entities in the ladder. I see that you have something similar that works. If your work has no IP, would you please post a copy ?
Thank you.

@josephmcg ,
An email to use is ian1196@hotmail.com.
Thank you

Look at arria10_hps_0.h, it will show the qsys addresses from the viewpoint of the hard processor.

// This is predefined:
#define HPS_TO_FPGA_LW_BASE 0xFF200000
// This is from Qsys (highest memory address of perf on the lightweight bus)
#define HPS_TO_FPGA_LW_SPAN 0x1FFFFF

void * GLOBAL_LW_BRIDGE_ADDRESS;
int devmem_fd = 0;
// Open up the /dev/mem device (aka, RAM)
devmem_fd = open(“/dev/mem”, O_RDWR | O_SYNC);
if(devmem_fd < 0) {
perror(“devmem open”);
exit(EXIT_FAILURE);
}

// mmap() the entire address space of the Lightweight bridge so we can access our custom module
GLOBAL_LW_BRIDGE_ADDRESS = (uint32_t*)mmap(NULL, HPS_TO_FPGA_LW_SPAN, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, HPS_TO_FPGA_LW_BASE);
if(GLOBAL_LW_BRIDGE_ADDRESS == MAP_FAILED) {
perror(“devmem mmap”);
close(devmem_fd);
exit(EXIT_FAILURE);
}

// Read register
custom_led_map = *( volatile uint32_t * )(GLOBAL_LW_BRIDGE_ADDRESS + LED_PIO_BASE);
// Write register
*custom_led_map = 1;

I am downloading the CD as I write. I see I failed to mention that I am using the DEO NANO SoC. Hoping there are enough similarities in the two for me to get an understanding of Qsys.
Thank you.

I hate to bother you with trivial things but can you tell me where you found the arria10_hps_0.h file? I’ve been working with the a10 SoC board for a few weeks and don’t find it anywhere, so I must be overlooking an important resource site.

Thanks - J

@josephmcg,
I have made my way past some of my earlier startup problems and was using FIFOs as you show successfully when I was working with the Cyclone V, but the A10 SoC has me stuck. Is your project using a flat design (as opposed to the partial reconfiguration included a the reference design)? I have been unable to get a flat design containing an HPS component to be loadable via the SDCard and am looking for any example of how that can be accomplished. I would be happy to send a link to my example design and the steps I take to make its device tree and uboot code. What I keep ending up with is a boot cycle that continually reboots after it has successfully loaded the RBF file (and I can see that the FPGA design has started to run because the LEDs I set start to operate before the board begins rebooting). If you have any insight into flat design use I would appreciate a tip to get me started.
Thanks,
Jambie

Hi all,

 I am working on cyclone V for first time. Is there any working application for fifo read and write through FPS to FPGA lightweight bridge.

@Jambie Would it be possible to share your Cyclone V Fifo implementation. It will be great helpful for me.

Best Regards,
Ranjith Hebbar

Hello ranjithhebbar! I have done the fifo exchange on Cyclone V in the past and would be happy to share the project with you. I will need to collect my files together so I will post it later (they are on my home computer rather than where I work so I’ll try to get them on-line tonight). It is reasonably close to the Arria 10 version posted in the projects section on this (Rocketboards) website. That project is named HPS_2_FPGA. My Cyclone V board is a DE-1 so if you are using the same board it will operate right away with no adaptation. If you do not have a DE-1 (from Terasic) the changes would be small to run it on another board as long as the Cyclone V you are using has HPS processors in the FPGA.
I’ll post directions to it here.
Enjoy computing!
Jambie

You can also see my reply on this forum to the post titled ‘HPS and FPGA communication Arria 10 SoC’. That question was for Arria 10, but as far as examples go it helps more to have one that is more directly applicable to the hardware you are running with (Cyclone V).

Hello ranjithhebbar! Sorry for the delay, I had to be out of town for a few days. I uploaded the Cyclone V HPS-FIFO example project to the project section on this (Rocketboards) site, look for the title “CycloneV HPS FIFO”. The readme.txt file describes where to download the files and how to set it up to run and edit the files. All source code is included.
Enjoy Computing!
Jambie

I am somewhat unsure when we are required to compile a new .dtb file. I understand the device tree describes the hardware available to the Kernel, but I find the idea crazy that we would have to compile a new device tree binary everytime we makes changes in Qsys with new IP. This boils down to one question: do we need a new .dtb file for every custom Quartus project/modification in Qsys or can we use the given GHRD tree binary for most projects?

I have used the same GHRD device tree file for all my projects. It is pretty complete so unless you are adding some device that it does not contain you should not require a new device tree. I did make a new device tree while trying to debug a problem with Altera-Sysid device once and the new device tree loads and runs OK, though the problem I was trying to solve did not improve (so I do not think the issue was device interface related - more likely a Linux issue). If your device tree contains support for devices you do not use it still works. If that causes resource use waste I am not aware of it.

1 Like

Using the device tree makes changes in hardware transparent to software and eases portability, and makes OS load correct drivers for you. But if you are not getting the addresses of your FPGA components from the device tree and you dont need the OS to load any driver for you on start up then you can use the ghrd device tree to make OS be able to control the HPS and you control your custom hardware in the FPGA with custom software.
I use this last approach since it is easier and faster (and i do not understand how the OS works with device tree) but I suposse it is worse method when you have big projects because small changes in hardware or changing to a new device will make you change the software again and again.