0

I'm tring to write universal fifo buffer. To make it universal i used code like this.

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

In simulation it works properly, but in Quartus it gives Error (10028): Can't resolve multiple constant drivers for net "Buffer[30][6]" at fifo.v(33) and so on.

All Code

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

To solve this problem I must put for inside always, but how I can do it?

tshepang
  • 12,111
  • 21
  • 91
  • 136
zavdimka
  • 1
  • 1
  • 2

2 Answers2

3

I think the issue is that synthesis doesn't know that wr_ptr is always a multiple of 3, hence from the synthesis point of view 3 different always blocks can assign to each Buffer entry. I think you can recode your logic to assign just a single Buffer entry per always block.

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

Also at http://www.edaplayground.com/x/23L (based off of Morgan's copy).

And, don't you need to add a valid signal into the fifo, or is the data actually always available to be pushed in ?

sgauria
  • 458
  • 2
  • 7
  • 2
    As much I prefer to see resets `initial` blocks are a valid way of initializing values for an FPGA. – Morgan Mar 12 '14 at 15:09
1

Other then the *_ptr in your code should be assigned with non-blocking assignment (<=), there really isn't anything wrong with your code.

If you want to assign Buffer with a for-loop inside of an always block, you can use the following:

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] will not compile in Verilog because the MSB and LSB select bits are variables. Verilog requires a known range. +: is for part-select (also known as a slice) allows a variable select index and a constant range value. It was introduced in IEEE Std 1364-2001 § 4.2.1. You can also read more about it in IEEE Std 1800-2012 § 11.5.1, or refer to previously asked questions: What is `+:` and `-:`? and Indexing vectors and arrays with +:.

Greg
  • 18,111
  • 5
  • 46
  • 68