开发者

Access to internal Xilinx FPGA block RAM

开发者 https://www.devze.com 2023-03-07 23:38 出处:网络
I\'m writing a devi开发者_Go百科ce driver for Xilinx Virtex-6 X8 PCI Express Gen 2 Evaluation/Development Kit SX315T FPGA. My OS is openSUSE 11.3 64 bit.

I'm writing a devi开发者_Go百科ce 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


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 :)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号