3
votes

I am using cyclone V to perform read/write on dual port RAM (HPS_master->FPGA_slave). For 32bit data, it able to perform by using ioread32 and iowrite32 but it not meet our targeted speed for data transfer(it takes longer cycle in signal tab after tuning only up to 400MHz).Cyclone V is using ARM Cortex-A9 MPCore Processor(32bit) but as stated in the datasheet, the AXI bus is able to configure up to 64bit. asm/io.h only supported up to ioread32/iowrite32. We try to configure 64bit in the HPS-FPGA using altera software and i try read/write using code below, but i am getting wrong data. Any proper solution and method to verify this?

static void iowrite64(u64 val,  u64 addr)
{
iowrite32((u32)val,  (u32) addr);
iowrite32(val >> 32, (u32)addr + 1);
}
static u64 ioread64 (u64 addr)
{
return ioread32(addr) | ((u64)ioread32((u32)addr + 1) << 32);
}

UPDATE/SOLUTION: We are able to read 64bit data from logram. Below are the changes we made. -driver/amba/bus.c, we change u32 to u64. -we add another inline function in io.h

    static inline u64 __raw_readq(const volatile void __iomem *addr)
    {
      u64 val;
      asm volatile("ldrd r2, %0" : "+Qo" (*(volatile u64 __force *)addr));
      register u32 v1 asm ("r2");
      val = v1;
      register u32 v2 asm ("r3");
     val=(val<<32) | v2; 
     return val;
   }

-printk is able to print up to 32bit but we print 2 times.

1
These are not 64-bit accesses. Why don't you use DMA? - CL.

1 Answers

1
votes

The ARM versions of these are in arch/arm/include/asm/io.h. The iowrite32 macros will ultimately call these. You can look at an implementation for 32bits.

static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
    asm volatile("str %1, %0"
             : "+Qo" (*(volatile u32 __force *)addr)
             : "r" (val));
}

There is an ARMv5+ instruction called strd which takes two registers and writes them. It is possible if you BUS structure is configured properly that it will run this as a single cycle. However, you need to have many other things setup properly. The MMU permissions for the I/O page as well as physical/FPGA connection of the ARM AXI to your FPGA device.

There are no public gcc constraints for a 64bit ARM assembler values. As the calling convention puts them in r0 and r1 we can make the function never inline.

static noinline void __raw_write64(u64 val, volatile void __iomem *addr)
{
    register u32 v1 asm ("r0") = val >> 32;
    register u32 v2 asm ("r1") = val & 0xfffffffUL;
    asm volatile("strd r0, %0"
             : "+Qo" (*(volatile u64 __force *)addr)
                 : "r" (v1), "r" (v2));
}

This is at least generating good code with objdump, but you might need to polish it for production quality.

That is at least the code needed. I think that the device memory should be non-cacheable and non-bufferable by default. You may need barrier type instructions as well.