3

我有一个 Verilog 模块,它从 32 位总线读取数据,一次一个字,并将这些字组合成一个更宽的 reg,作为其他几个模块的输入。输入总线是内存总线,所以每个字都带有一个地址,用于标识我必须将它存储在哪里。

我使用部分选择将单词存储到reg中。因为总线上最低地址的字对应于寄存器中最重要的字,所以我通过翻转地址的位然后附加三个 0 位以将其从字节偏移量转换为有点偏移。

这实际上工作得很好。但是因为我在几个地方使用了“翻转位然后添加三个零”逻辑,所以我决定将它分配给一条线,然后使用该线作为部件选择中的偏移量。但是,当我这样做时,突然它根本不起作用。第一次写入字 0 有效。但是在第二个周期,写入字 1 会覆盖字 0!然后对字 2 的以下写入保存在字 1 中。就好像电线是一个 reg,并且直到下一个周期才看到计算偏移量的结果。这看起来很奇怪,因为我认为电线只是地址总线的线路穿过一些非门;每当地址改变时,偏移量就会改变。

我将问题提炼为以下两个示例。我使用 3 位地址总线和 8 位值只是为了更容易看到发生了什么。谁能解释为什么他们表现出不同的行为?我认为这是由于 Verilog 调度块的方式有些特殊,但我无法解释。显然,我可以只使用工作版本,或者使用数组而不是广泛的 reg,但我认为理解其原因将在未来帮助我。

谢谢!

作品:

module busif(
        input clock,
        input [2:0] address,
        input read,
        input write,
        input [7:0] data_in,
        output reg [7:0] data_out
    );

    // 8 bytes of memory (3-bit address).
    reg [63:0] memory;

    always @(posedge clock) begin
        if (write) begin
            memory[{~address, 3'b000} +: 8] <= data_in;
        end
        // (read case omitted)
    end       

endmodule

不起作用(偏移似乎需要 1 个周期才能通过“电线”传播):

module busif(
        input clock,
        input [2:0] address,
        input read,
        input write,
        input [7:0] data_in,
        output reg [7:0] data_out
    );

    // 8 bytes of memory (3-bit address).
    reg [63:0] memory;

    wire [5:0] offset;
    assign offset = {~address, 3'b000};

    always @(posedge clock) begin
        if (write) begin
            memory[offset +: 8] <= data_in;
        end
        // (read case omitted)
    end       

endmodule
4

1 回答 1

2

您的代码没有任何问题 - 请注意,isim 在历史上一直存在很多错误,并且可能仍然存在。几年前我放弃了它。

附加了简单的测试台 - 这两个模块都通过了 Modelsim 和 Icarus。

/**
 * Maia testbench: download and install maia from maia-eda.net. To run the
 * testbench, save this code as tb.tv, and:
 *
 * rtv tb.tv busif.v
 *
 * On success, you should get the following output:
 *
 * # finished: 'memory' is 102040810204080
 * # (Log) (80 ns) 8 vectors executed (8 passes, 0 fails)
 *
 */
#pragma _StrictChecking 0  // turn off some type checking for simplicity

DUT {
   module busif
      (input           clock,
      input [2:0]      address,
      input            read,
      input            write,
      input [7:0]      data_in,
      output reg [7:0] data_out);

   signal(output reg[63:0] memory);                // internal signals to test

   [clock, write, address, data_in] -> [memory];   // vector definition
   create_clock clock;                             // define a clock
}

main() {
   int   i;
   var64 expected = 64`hxxxxxxxx_xxxxxxxx;
   var64 mask     = 64`hff000000_00000000;
   var64 data;

   for(i=0; i<8; i++) {
      data = 64`h1 << ((7-i)*8) + i;
      expected &= ~mask;                           // clear out the new byte
      expected |= data;                            // get the expected result
      mask >>= 8;

      [.C, 1, i, 1<<i] -> [expected];              // clock and test
   }
   report("finished: 'memory' is %x\n", memory);   // read this backwards!
}
于 2013-07-25T08:47:33.143 回答