Injener
Injener

Reputation: 11

Access to internal Xilinx FPGA block RAM

I'm writing a device driver for Xilinx Virtex-6 X8 PCI Express Gen 2 Evaluation/Development Kit SX315T FPGA. My OS is openSUSE 11.3 64 bit. In the documentation for this device (Virtex-6 FPGA Integrated Block form PCI Express User Guide UG517 (v5.0) April 19, 2010, page 219) says:

The PIO design is a simple target-only application that interfaces with the Endpoint for PCIe core’s Transaction (TRN) interface and is provided as a starting point for customers to build their own designs. The following features are included:

• Four transaction-specific 2 KB target regions using the internal Xilinx FPGA block RAMs, providing a total target space of 8192 bytes

• Supports single DWORD payload Read and Write PCI Express transactions to 32-/64-bit address memory spaces and I/O space with support for completion TLPs

• Utilizes the core’s trn_rbar_hit_n[6:0] signals to differentiate between TLP destination Base Address Registers

• Provides separate implementations optimized for 32-bit, 64-bit, and 128-bit TRN interfaces

In the device is available BAR0 and BAR2 length 128 bytes. I'm trying to access internal Xilinx FPGA block RAM, for that I am mapping BAR0 in virtual space kernel.

struct pcie_dev {
    struct          pci_dev* dev; 
    struct          cdev chr_dev;
    atomic_t        dev_available;
    u32             IOBaseAddress;
    u32             IOLastAddress;
    void* __iomem   bar;
    void            *virt_addr;
    u32             length;
    unsigned long   sirqNum;
    void           *private_data; };

struct pcie_dev cur_pcie_dev;

    cur_pcie_dev.IOBaseAddress = pci_resource_start(dev, 0);
    cur_pcie_dev.IOLastAddress = pci_resource_end(dev, 0);
    cur_pcie_dev.length=pci_resource_len(dev,0); 
    cur_pcie_dev.bar=pci_iomap(dev, 0,cur_pcie_dev.length); 

IOBaseAddress is 0xfbbfe000 IOLastAddress is 0xfbbfe07f length=128;

Using IOCTL I try, write/read data.

case IOCTL_INFO_DEVICE:
{
u32 *rcslave_mem = (u32 *)pCur_dev->bar;
u32 result = 0;

     u32 value = 0;
     int i;
     for (i = 0; i <2048 ; i++) {
             printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
                     (u32)value, (void *)rcslave_mem + i);
             iowrite32(value, rcslave_mem + i);
             value++;
     }
     /* read-back loop */
     value = 0;
     for (i = 0; i < 2048; i++) {
             result = ioread32(rcslave_mem + i);
                     printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
                             (u32)value, (void *)rcslave_mem + i, (u32)result);

             value++;
     } 

But it turns out to write and read only 32 values​​. As I understand it, the recording takes place in BAR0 (4 byte * 32 values ​​= 128 bytes), but not in internal Xilinx memory.I tried to go the other way.

    cur_pcie_dev.IOBaseAddress = pci_resource_start(dev, 0);
    cur_pcie_dev.IOLastAddress = pci_resource_end(dev, 0);
    cur_pcie_dev.length=pci_resource_len(dev,0);
    flags = pci_resource_flags(dev,0);

if (flags & IORESOURCE_MEM) {
  if (request_mem_region(cur_pcie_dev.IOBaseAddress,cur_pcie_dev.length, DEVICE_NAME)== NULL) {
                 return -EBUSY;}

   cur_pcie_dev.virt_addr=ioremap_nocache(cur_pcie_dev.IOBaseAddress,cur_pcie_dev.length);
     if (cur_pcie_dev.virt_addr == NULL) {
                printk(KERN_ERR "ERROR: BAR%u remapping FAILED\n",0);
                return -ENOMEM;
            }
            printk(KERN_INFO " Allocated I/O memory range %#lx-%#lx\n",      cur_pcie_dev.IOBaseAddress,(cur_pcie_dev.IOBaseAddress+cur_pcie_dev.length-1));
        } else {
            printk(KERN_ERR "ERROR: Invalid PCI region flags\n");
            return -EIO;
        }

Then

     address = ((unsigned int)pCur_dev->virt_addr+pd.Address);
     iowrite32(pd.Value,(unsigned int*) address); 

     address = ((unsigned int)pCur_dev->virt_addr+pd.Address);
     pd.Value = ioread32((unsigned int *)address); 

I use a summing virtual address and the address, which specifies the user. But the result is read / write operations is also not true. Tell me what I'm doing wrong.

P.S.Sorry for my bad English

Upvotes: 1

Views: 3600

Answers (1)

saeedn
saeedn

Reputation: 3378

What is the reason you are trying to access internal block RAM of your board? I think a normal behavior of a device driver (which your device here is a PCI Express interface), would suffice if you are using Programmed I/O (PIO) on your FPGA. When you write to your device driver, the data would be transferred to block RAM by downloaded IP core on FPGA side (and also in reverse).

Take a look at Linux Driver in xapp1022 (Memory Endpoint Test) package from Xilinx.

P.S.: I know it's an old question and you may found your answer way sooner :)

Upvotes: 1

Related Questions