I’m working with Cyclone V SoC and I’m trying to share part of HPS DDR between FPGA fabric and HPS. I have limited the linux DDR usage to 800MB through u-boot script to avoid any writing by FPGA on DDR portion that linux was using. I have placed a DMA in Qsys that reads samples from an on-chip memory and writes them to DDR through f2h_sdram interface. However the DMA never ends the transaction and the length register never goes down.
How do you access from linux to a part of memory that is outside its memory??? I dont think thats the way to do it.
You can allocate a buffer in linux (so linux has access because it is his memory) and pass the pointer to the DMA to complete the transaction. To do so you have to use a driver because the regullar malloc you use in applications is virtually contiguous but the system does not ensure it is physically contiguous (and you need a contiguous buffer for the DMA).
So inside a driver you can use kmalloc() if you want the buffer to be cached. In this case you should use the ACP port to access it from FPGA because it is the only to do cached accesses. ACP is usually useful for small data sizes below kB or for few kB. If you want the buffer not to be cached (in this case any time the CPU access to it the cache is bypassed and data is directly written into the SDRAM ensuring coherency with the FPGA accesses) you should use the function dma_alloc_coherent().
I have 2 examples in my repo that does the same you want to do but using the DMA in the HPS.
This one (https://github.com/robertofem/CycloneVSoC-examples/tree/master/Linux-modules/DMA_PL330_LKM_basic) is a basic driver that makes a transfer in between processor and FPGA. You can use it to see how the buffers are allocated. Then you just have to change the part that interacts with DMA. I did this to understand drivers and buffers.
This one (https://github.com/robertofem/CycloneVSoC-examples/tree/master/Linux-modules/DMA_PL330_LKM) is a generic driver that permits applications to move data between the application and FPGA as easy as opening a file and writing to it.
In your case you want to access through the FPGA-to-SDRAM bridges so you need to use non cached buffers allocated with dma_alloc_coherent(). You also need to enable the FPGA-to-SDRAM ports in the SDRAM controller because they are disabled by default. This is the code to do it:
//SDRAMC beginning address
#define SDRAMC_REGS 0xFFC20000
//Offset of FPGA-to-SDRAMC ports reset register from the beginning of SDRAMC
#define FPGAPORTRST 0x5080
//Remove FPGA-to-SDRAMC ports from reset so FPGA can access SDRAM through them
*((unsigned int *)(SDRAMC_REGS + FPGAPORTRST)) = 0xFFFF;
Hope it helps
thank you for reply and advices. I wrote and read the sdram through the f2h bridge, just for test, but I think the best way is to use the f2h_sdram to have un-cached accesses. I will try to use it soon.
I’m back working on transfering data between FPGA and HPS. I don’t know a lot about linux kernels and modules, because I worked mainly with FPGA (not SoC until now) firmware. I have probably a trivial question, but I ask you anyway. In your projects you use a module to manage the HPS DMA in order to move data from FPGA to SDRAM and back. Is it possible to move data only with FPGA DMA? I try to explain better what I mean. My idea was to move data from FPGA on-chip RAM to SDRAM through FPGA DMA that use the fpga2hps_sdram interface to write directly in the SDRAM. This because the SDRAM controller of the Cyclone V SoC have a multiport front-end that interface directly with FPGA (precisely the fpga2hps_sdram interface). In your examples, a L3 Interconnect was used to move data together with hps2fpga and fpga2hps bridges, but I would like to use the fpga2hps_sdram interface to have (I hope so) the best throughput and avoid using the HPS cache.
Thanks a lot.
Yeah, of course you can. I ve done it in that repo in baremetal but i didnt merged it to the master.
You can see this example in the branch soft_dma_baremetal of the repo. The exact link is this:
This example runs over this hardware:
In this example I access the HPS through FPGA-to-HPS bridge because I was interested on studying the ACP too. But you can change the DMA port and connect it to FPGA-to-SDRAM port. In this case the Avalon to AXI conversion is not needed because you can configure FPGA-to-SDRAM as Avalon. You can write a driver, similar to the one i did to allocate a buffer in SDRAM memory that the DMAC can use. Another important issue is that FPGA-to-SDRAM ports are switched off by default. You need to access to the fpgaportrst and remove them from reset:
*((unsigned int *)(SDRAMC_REGS + FPGAPORTRST)) = 0xFFFF;
where SDRAMC_REGS is the SDRAM Controller base address and FPGAPORTRST the offset for that register.
I will do the Operating system version soon, next week or so as I need that transfer data rates for my thesis.
hi ,could you help me?fpga to hps SDRAM interface do not support 2 port,and the second port not work,the waitrequest signal keep high.
I hope to help you! What device do you use? I used a Cyclone V SoC FPGA and I had the Avalon-MM Bidirectional type for the SDRAM interface. What version of Quartus are you using?
Thanks for the explanation and github links. I have a small question and hope you can help me answer.
I am trying to use DMA Controller in HPS ( bare metal ) but I cannot activate it. I go to Qsys to modify my HPS. In peripheral pin tab, all I can see are I2C controller, UART controller, SPI controller, etc. but I cannot find DMA Controller. I find it weird because in Intel document states that HPS support DMA Controller.
Do I misunderstand something here ?
Thanks in advance !
i dont think you need to do anything in qsys.
i have a working 3xample on what you ar3 trying to do in:
Thanks for quick respond,
I had read your example before and that made me a bit confused ( I’m quite new to this field ).
For example if I want to work with I2C peripheral, I need to go Qsys and modify it. Then I can make my bare metal application to control it.
But when reading your examples and explanation, I find that DMA controller in HPS is ‘always’ there. It does not need to initialize in Qsys like other peripheral. All I need to do is programming it in bare metal application or on Linux.
Please give me a confirmation or correct me if I am wrong.
And once again, thank you for replying me !
did you read vol3 of the cyclone v soc handbook, specially chapters 1 (intro to hps), 20 (i2c component details) and 27 (hps instantiation in qsys)? there you should find the answer you are looking for. maybe the ic2 needs to be activated because it interfaces external pins while dma is an internal component. or maybe because i2c shares pins with other compomemts so you have to choose one or the other. things like that.
i dont have the computer on hand to open qsys or handbook and later i may forget. check it and write me if you still do not clarfy this subject.
Thanks roberbot ! I will check it out.
Thanks for you help. I really appreciate it. Hope this does not bring you any inconvenience.
Kind regards !