Trouble getting YOSYS to infer block ram array (rather than using logic cells) verilog ice40

1.3k Views Asked by At

I've been having trouble the last little while with a project that uses look up table arrays quite a bit and getting yosys to infer them as block ram. Yosys keeps thinking one or the other of my arrays should be implemented using logic cells.

example:

reg signed [11:0] dynamicBuffer [0:2047];

gets inferred as IceStorm LC and thus quickly overflows my logic cell budget.

Info: Device utilisation:
Info:            ICESTORM_LC: 83524/ 7680  1087%
Info:           ICESTORM_RAM:    18/   32    56%
Info:                  SB_IO:    36/  256    14%
Info:                  SB_GB:     8/    8   100%
Info:           ICESTORM_PLL:     2/    2   100%
Info:            SB_WARMBOOT:     0/    1     0%

I've read that an array needs to have a registered output or Yosys does not see it as ram (is this true?) I've tried to rework things such that my arrays are ultimately routed to a register at each clock count. But I still cannot get it working. What is the right way of working with multiple arrays, copying them one to the other, and getting yosys to infer them as block ram? What do I need to avoid?

3

There are 3 best solutions below

5
gatecat On

Assuming you are using a for loop like in your last example, for loops in hardware do not run sequentially like in software but do the entire copy in one clock. You need to use a counter and a state machine for the copy, not a Verilog for loop.

1
ke10g On

The solution in this case was to implement an asynchronous fifo.

I was crossing clock domains when I connected the two modules so needed to synchronize reading and writing from the array. The lack of coordination between reads and writes to the array was causing yosys to infer that the array was not to be implemented as block ram.

0
TinLethax On

I've read that an array needs to have a registered output or Yosys does not see it as ram (is this true?)

Yes, its true. Only way I can make Yosys infer to BRAM is to make it an asynchronous BRAM with Input and Output. I took this from my VFD display controller project

module GRAM(
input R_CLK,
input W_CLK,

input [7:0]GRAM_IN,
output reg [7:0]GRAM_OUT,

input [11:0] GRAM_ADDR_R,
input [11:0] GRAM_ADDR_W,

input G_CE_W,
input G_CE_R);

reg [7:0] mem [3002:0];// change this to what you want.

initial mem[0] <= 255;// fill the first byte to let Yosys infer to BRAM.

always@(posedge R_CLK) begin// reading from RAM sync with reading clock.
    if(G_CE_R)
        GRAM_OUT <= mem[GRAM_ADDR_R];   
end 

always@(posedge W_CLK) begin// writing to RAM sync with writing clock.
    if(G_CE_W)
        mem[GRAM_ADDR_W] <= GRAM_IN;
end

endmodule// GRAM