Vladimir Bochkov
Vladimir Bochkov

Reputation: 11

PCI-E Altera transmit-change-receive trouble

help to solve the problem. I have a board Altera db4kgh15. It has built-in support pci-e interface. I have a Linux kernel module, which is controlled by the fee. with the function below I scan the base registers dogs and try to write in the register data. The board should adopt a 32-bit word and send it back by adding to it 2. However, the output we get the same number. The project on the FPGA to the main circuit module attached ksis own design. Screenshot scheme and code module is presented below. What am I doing wrong?

static int scan_bars(struct pci_dev *dev) {
    int i;
    int end = 0x3f;
    ulong j;
    for (i = 0; i < ALTPCIE_BAR_NUM; i++) {
    unsigned long bar_start = pci_resource_start(dev, i);
    if (bar_start) {
        unsigned long bar_end = pci_resource_end(dev, i);
        unsigned long bar_flags = pci_resource_flags(dev, i);
        printk(KERN_INFO "##pci_m.ko# BAR%d 0x%08lx-0x%08lx flags 0x%08lx\n",
          i, bar_start, bar_end, bar_flags);
        virt_bar0 = (ulong) bus_to_virt(bar_start);
        bar0 = bar_start;
        printk(KERN_INFO "##pci_m.ko# Virt bar0 ADDR = 0x%08lx\n", virt_bar0);

        if(bar0 == virt_bar0) {
        printk(KERN_INFO "##pci_m.ko# bars equals!");
        }

        outl_p(number, bar0);
        printk(KERN_INFO "##pci_m.ko# (bus) outl_p 0x%08lx\n", number);

        /*for(j = bar0; j <= bar0 + end + 5; j++) {
        printk(KERN_INFO "##pci_m.ko# (bus) inb_p[0x%08lx + %d] 0x%08lx\n", bar0, j - bar0, inb_p(j));
        }*/

        for(j = bar0; j <= bar0 + end + 5; j += 4) {
        printk(KERN_INFO "##pci_m.ko# (bus) inl_p[0x%08lx + %d] 0x%08lx\n", bar0, j - bar0, inl_p(j));
        }

        outl_p(number, virt_bar0);
        printk(KERN_INFO "##pci_m.ko# (virtual) outl_p 0x%08lx\n", number);

        /*for(j = virt_bar0; j <= virt_bar0 + end + 5; j++) {
        printk(KERN_INFO "##pci_m.ko# (virtual) inb_p[0x%08lx + %d] 0x%08lx\n", virt_bar0, j - virt_bar0, inb_p(j));
        }*/

        for(j = virt_bar0; j <= virt_bar0 + end + 5; j += 4) {
        printk(KERN_INFO "##pci_m.ko# (virtual) inb_p[0x%08lx + %d] 0x%08lx\n", virt_bar0, j - virt_bar0, inl_p(j));
        }

    } else {
        printk(KERN_INFO "##pci_m.ko# Could not correct read BAR #%d\n", i);
        break;
    }
    }

    return 0;

}

// bvs_pci_server1bar.v

`timescale 1 ps / 1 ps
module bvs_pci_server1bar #(
        parameter AUTO_CLOCK_SINK_CLOCK_RATE = "-1"
    ) (
        input  wire [31:0] serv_bar1_0_addr,          //     avalon_slave.address
        input  wire        serv_bar1_0_read,          //                 .read
        output wire        serv_bar1_0_waitreq,       //                 .waitrequest
        input  wire        serv_bar1_0_write,         //                 .write
        output wire [63:0] serv_bar1_0_readd,         //                 .readdata
        input  wire [63:0] serv_bar1_0_writed,        //                 .writedata
        input  wire [6:0]  serv_bar1_0_burstcnt,      //                 .burstcount
        input  wire [8:0]  serv_bar1_0_byteen,        //                 .byteenable
        output wire        serv_bar1_0_readdatavalid, //                 .readdatavalid
        output wire [19:0] serv_txs_addr,             //    avalon_master.address
        output wire [7:0]  serv_txs_byteen,           //                 .byteenable
        input  wire [63:0] serv_txs_readd,            //                 .readdata
        output wire        serv_txs_read,             //                 .read
        output wire        serv_txs_write,            //                 .write
        input  wire        serv_txs_readdatavalid,    //                 .readdatavalid
        input  wire        serv_txs_waitreq,          //                 .waitrequest
        output wire        serv_txs_chipsel,          //                 .chipselect
        output wire [6:0]  serv_txs_burstcnt,         //                 .burstcount
        output wire [63:0] serv_txs_writed,           //                 .writedata
        input  wire        serv_rst,                  //       reset_sink.reset
        input  wire        serv_clk,                  //       clock_sink.clk
        output wire        serv_irq                   // interrupt_sender.irq
    );

    // TODO: Auto-generated HDL template

    assign serv_bar1_0_waitreq = 1'b0;

    assign serv_bar1_0_readd = 64'b0000000000000000000000000000000000000000000000000000000000000000;

    assign serv_bar1_0_readdatavalid = 1'b0;

    assign serv_txs_burstcnt = 7'b0000000;

    //assign serv_txs_writed = 64'b0000000000000000000000000000000000000000000000000000000000000000;

    assign serv_txs_addr = 20'b00000000000000000000;

    assign serv_txs_chipsel = 1'b0;

    assign serv_txs_write = 1'b0;

    assign serv_txs_read = 1'b0;

    assign serv_txs_byteen = 8'b00000000;

    //assign serv_irq = 1'b0;

    reg[63:0] _value = 64'b0000000000000000000000000000000000000000000000000000000000000000;
    reg _irq = 1'b0;
    reg _txs_writed = 64'b0000000000000000000000000000000000000000000000000000000000000000;

    always @(posedge serv_clk)
    begin
        if(serv_bar1_0_readd != _value)
            begin
                _value <= serv_bar1_0_readd;
                _txs_writed <= serv_bar1_0_readd | 64'b0100000000000000000000000000000000000000000000000000000000000010;
                _irq <= 1'b1;
            end
        else
            _irq <= 1'b0;
    end

    assign serv_value = _value;
    assign serv_irq = _irq;
    assign serv_txs_writed = _txs_writed;

endmodule

Upvotes: 1

Views: 410

Answers (2)

TSP
TSP

Reputation: 76

plx_pci_io_base = pci_resource_start(dev, 0);
iolength = pci_resource_len(dev, 0);

if (!request_mem_region(plx_pci_io_base, iolength, "PGDR IO Base")) {
    DEBUG(KERN_ERR "request region #1\n");
    return -EBUSY;
}

iobase = ioremap_nocache(plx_pci_io_base, iolength);
if (!iobase) {
    DEBUG(KERN_ERR "ioremap #1\n");
    ret_status = -ENOMEM;
    goto cleanup1;
}

Upvotes: 1

TSP
TSP

Reputation: 76

You can try the following:

  1. Use writel and readl instead of outl_p and inl_p
  2. Check if the BAR register into which you are writing/reading and the BAR register used by RTL are same
  3. Use Signal Tap to check if the RD/WR reach you RTL logic

Upvotes: 0

Related Questions