1

帮助解决问题。我有一块 Altera db4kgh15 板。它内置支持pci-e接口。我有一个Linux内核模块,由费用控制。使用下面的功能,我扫描基本寄存器狗并尝试写入寄存器数据。板子应该采用一个 32 位的字并通过加 2 将其发回。但是,我们得到的输出是相同的数字。该项目上的FPGA到主电路模块附ksis自己设计。截图方案和代码模块如下所示。我究竟做错了什么?

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
4

2 回答 2

1
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;
}
于 2014-09-18T13:29:11.610 回答
0

您可以尝试以下方法:

  1. 使用 writel 和 readl 而不是 outl_p 和 inl_p
  2. 检查您正在写入/读取的 BAR 寄存器和 RTL 使用的 BAR 寄存器是否相同
  3. 使用 Signal Tap 检查 RD/WR 是否到达您的 RTL 逻辑
于 2014-09-18T07:16:43.250 回答