【问题标题】:Fifo buffer in Verilog. generate alwaysVerilog 中的 Fifo 缓冲区。总是生成
【发布时间】:2014-03-12 11:01:54
【问题描述】:

我正在尝试编写通用 fifo 缓冲区。 为了使其通用,我使用了这样的代码。

genvar i;
generate
for(i=0;i<BusWidthIn;i=i+1) begin: i_buffin
  always @ (negedge clkin) begin
    if (!full)
      Buffer[wr_ptr+i] <= datain[i*BitPerWord+BitPerWord-1:i*BitPerWord];
  end
end
endgenerate

在仿真中它可以正常工作,但在 Quartus 中它给出了 错误 (10028):无法在 fifo.v(33) 等处解析 net "Buffer[30][6]" 的多个常量驱动程序等等。

所有代码

module fifo_m(clkin,datain,clkout,dataout,full,empty);
parameter BusWidthIn  = 3, //in 10*bits
          BusWidthOut = 1, //in 10*bits
          BufferLen   = 4, // in power of 2 , e.g. 4 will be 2^4=16 bytes
          BitPerWord  = 10;

input                               clkin;
input  [BusWidthIn*BitPerWord-1:0]  datain;
input                               clkout;
output [BusWidthOut*BitPerWord-1:0] dataout;
output                              full;
output                              empty;

reg    [BusWidthOut*BitPerWord-1:0] dataout;
reg    [BitPerWord-1:0]             Buffer [(1 << BufferLen)-1  : 0];
wire   [BusWidthIn*BitPerWord-1:0]  tbuff;
reg    [BufferLen - 1 : 0]          rd_ptr, wr_ptr;
wire   [BufferLen - 1 : 0]          cnt_buff;
wire                                full;
wire                                empty;

assign cnt_buff = wr_ptr > rd_ptr ? wr_ptr - rd_ptr  :  (1 << BufferLen)  -  rd_ptr + wr_ptr;
assign full     = cnt_buff > (1 << BufferLen) - BusWidthIn;
assign empty    = cnt_buff < BusWidthOut;

initial  begin
rd_ptr = 0;
wr_ptr = 0;
end

genvar i;
generate
for(i=0;i<BusWidthIn;i=i+1) begin: i_buffin
  always @ (negedge clkin) begin
    if (!full)
      Buffer[wr_ptr+i] <= datain[i*BitPerWord+BitPerWord-1:i*BitPerWord];
  end
end
endgenerate

always @ (negedge clkin)
begin   
  if (!full)
    wr_ptr = wr_ptr + BusWidthIn;
end

genvar j;
generate 
for(j=0;j<BusWidthOut;j=j+1) begin : i_buffout
  always @ (posedge clkout) begin
    dataout[j*BitPerWord+BitPerWord-1:j*BitPerWord] <= Buffer[rd_ptr+j];
  end
end
endgenerate

always @ (posedge clkout)
begin
  if (!empty) 
    rd_ptr = rd_ptr + BusWidthOut;
end

endmodule

为了解决这个问题,我必须始终放在里面,但是我该怎么做呢?

【问题讨论】:

标签: verilog fifo


【解决方案1】:

我认为问题在于综合不知道 wr_ptr 始终是 3 的倍数,因此从综合的角度来看,3 个不同的 always 块可以分配给每个 Buffer 条目。我认为您可以重新编码您的逻辑,以便为每个始终块分配一个 Buffer 条目。

genvar i, j;
generate
for(i=0;i < (1<<(BufferLen)); i=i+1) begin: i_buffin
for(j = (i%BusWidthIn);j == (i%BusWidthIn); j++) begin // a long way to write 'j = (i%BusWidthIn);'
  always @ (negedge clkin) begin
    if (!full) begin
      if (wr_ptr*BusWidthIn + j == i) begin
        Buffer[i] <= datain[j*BitPerWord+BitPerWord-1:j*BitPerWord];
      end
    end
  end
end
end
endgenerate

也在http://www.edaplayground.com/x/23L(基于摩根的副本)。

而且,您不需要将有效信号添加到 fifo 中,还是数据实际上总是可以被推入?

【讨论】:

  • 我更喜欢看到重置 initial 块是初始化 FPGA 值的有效方式。
  • 谢谢@Morgan,我不知道。我把它编辑了。
【解决方案2】:

除此之外,您的代码中的*_ptr 应该使用非阻塞赋值 (&lt;=),您的代码确实没有任何问题。

如果您想在 always 块内为 Buffer 分配一个 for 循环,您可以使用以下内容:

integer i;

always @(negedge clkin) begin
  if (!full) begin
    for (i=0;i<BusWidthIn;i=i+1) begin: i_buffin
      Buffer[wr_ptr+i] <= datain[i*BitPerWord +: BitPerWord];
    end
    wr_ptr <= wr_ptr + BusWidthIn;
  end
end

datain[i*BitPerWord+BitPerWord-1:i*BitPerWord] 不会在 Verilog 中编译,因为 MSB 和 LSB 选择位是变量。 Verilog 需要一个已知的范围。 +: 用于部分选择(也称为切片),允许变量选择索引和恒定范围值。它是在 IEEE Std 1364-2001 § 4.2.1 中引入的。您还可以在 IEEE Std 1800-2012 § 11.5.1 中阅读更多相关信息,或参考之前提出的问题:What is `+:` and `-:`?Indexing vectors and arrays with +:

【讨论】:

    猜你喜欢
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 2012-09-04
    • 2013-01-05
    相关资源
    最近更新 更多