Verilog中的Fifo缓冲区。永远生成

问题描述 投票:0回答:2

我正在尝试编写通用的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中它给出了Error(10028):无法在fifo.v(33)处解析网络“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
2个回答
3
投票

我认为问题是综合不知道wr_ptr总是3的倍数,因此从合成的角度来看3不同的始终块可以分配给每个Buffer条目。我认为你可以重新编码你的逻辑,为每个always块分配一个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(基于Morgan的副本)。

并且,您不需要在fifo中添加有效信号,或者实际上数据是否总是可以推入?


1
投票

除了你的代码中的*_ptr之外应该分配非阻塞赋值(<=),你的代码确实没有任何问题。

如果要在Buffer块内为for循环分配always,可以使用以下命令:

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 Std1364-2001§4.2.1中引入的。您还可以在IEEE Std 1800-2012§11.5.1中阅读更多相关信息,或参考之前提出的问题:What is `+:` and `-:`?Indexing vectors and arrays with +:

© www.soinside.com 2019 - 2024. All rights reserved.