# Using BRAM as buffer

I'm trying to implement a buffer for an image processing pipeline and need to load data into BRAM.

I've been following an online tutorial (https://www.youtube.com/watch?v=n35zS__YEFQ) for implementing different parts of the system, but after synthesis and implementation, I can see that my code is using LUTRAM instead of BRAM. I have tried looking into the language templates provided by vivado for inferring single port BRAM and to me the code looks very similar, but I'm new to FPGAs and don't know much, so I'm not entirely sure how I can force BRAM to be inferred instead of LUTRAM.

here is my verilog code:

module buffer #(parameter NUM_ELEMENTS=10, ADDRESS_BITS=4, WIDTH=8) (
input clk,
input rst,
input [WIDTH-1:0] dataIn,
input validInput,
output wire [WIDTH-1:0] dataOut
);

reg [WIDTH-1:0] mem [NUM_ELEMENTS-1:0];

always @ (posedge clk) begin
if (rst) begin
wrPtr <= 0;
end else if (validInput) begin
mem[wrPtr] <= dataIn;
wrPtr <= wrPtr + 1;
end
end

assign dataOut = mem[rdPtr];

always @ (negedge clk) begin
if (rst) begin
rdPtr <= 0;
rdPtr <= rdPtr + 1;
end
end

endmodule


simulating the module shows that it is working correctly as expected (I need to take care of some edge cases where the read pointer goes past the end of the buffer, more on that later).

my test bench code is:

timescale 1ns / 1ps

module buffer_tb();
reg clk;
reg rst;
reg [buffer.WIDTH-1:0] dataIn;
reg validInput;
wire [buffer.WIDTH-1:0] dataOut;

integer i;

initial clk = 1;
always #5 clk = ~clk;

initial begin
rst = 1;
dataIn = 0;
validInput = 0;
#10;
rst = 0;
validInput = 1;
for (i=0; i<10; i = i+1) begin
dataIn = 2*i;
#10;
end
validInput = 0;
#40;
#100;
\$stop;
end

endmodule
`

and the output of the simulation is:

but opening project summary or the elaborated design shows the incorrect use of LUTRAM:

I emphasize again that I'm a total beginner and just started using FPGAs; After searching a bit on xilinx's guides, I still can't find any way of specifying the type of RAM, only that it can be inferred when using a very specific syntax, which seems odd and I haven't managed to make it work.

My main questions are:

1. how can you infer BRAM instead of LUT? do I have to copy the suggested example code line by line or are there changes permitted?
2. if I have to copy the template codes directly, would it better to use the IP core generator to instantiate BRAM in the block design and write a controller for it (the buffer module acting as a wrapper), or whether to use the actual code template? to be honest I don't even know what the differences are. as I understand it, the block design gets converted to verilog anyways.
3. I only need to write to buffers till they are full, then read from them until they are empty. Should I be using a FIFO instead of trying to implement my own buffer code? The way I understood the online tutorial for image processing, I can create more buffers than required and fill them while processing other portions of the data, then multiplex the buffers, but I'm not sure what the advantages and downsides of a FIFO block are, compared to a hand written buffer.
• Before that did u calculate how much bram is needed for a frame buffer and how much is available. A typical 7 series low end xilinx FPGA doesn't have enough bram to incorporate say 640x480 VGA frame. – Mitu Raj May 30 at 15:40
• Yes, I will be periodically filling the buffer with data from QSPI modules which give me enough capacity for all the data input. the actual image will be loaded via DMA from a ZYNQ processor but that's way in the future. I can't even get the buffer itself to work how I want it :( – OM222O May 30 at 15:49
• DMA+DDR+Processor is how usually video engines are implemented on an FPGA. BRAMs can be used to implement line buffers or FIFOs on video/image processing pipeline. But they are not big enough in most FPGAs for frame buffers especially if at least double buffering is needed. And yes, you have to follow coding guidelines and attributes to properly infer the BRAM using RTL. – Mitu Raj May 30 at 16:03