Vivado won't synthesize BRAM, making LUT instead

217 Views Asked by At

After adding the line number_of_lines <= ram[0], Vivado won't synthesize a BRAM component. Instead I got a LUT scheme.

module bram3 (clka,clkb,ena,enb,wea,web,addra,dia,dib,doa,dob,rst);
       
       input clka,clkb,ena,enb,wea,web,rst;
       input [11:0] addra;
       input [63:0] dia,dib;
       output [63:0] dob, doa;
       reg [32:0] ram [254:0];
       reg [32:0] dob, doa;
       
       reg [11:0] new_addr=0;
       reg [11:0] number_of_lines=0;
       
       always @(posedge clka)
       begin
           if (ena)
           begin
               if (wea) ram[addra] <= dia;
               doa <= ram[addra];
           end
       end
       
       
       always @(posedge clkb or negedge rst)
       begin
           if (!rst)
           begin
                new_addr<=0;
           end
           else  if (enb)
           begin
               if (new_addr==0)
                   number_of_lines <= ram[0];
             
               new_addr<=new_addr+1;
               dob <= ram[new_addr];
               if (new_addr==number_of_lines)
                   new_addr<=0;
           end   
       end
   endmodule

I understand that I can't do more than 2 reads (in my code I got 3 reads), but I need logic to work as I implemented in my code.

How can I rewrite the logic to make a synthesizable BRAM like?

1

There are 1 best solutions below

0
EEliaz On

Like Soheil wrote above in the comments, you can just store number of lines on the side, outside of the BRAM, and by that reduce one read port.

It should look something like the next:

 module bram3 (clka,clkb,ena,enb,wea,web,addra,dia,dib,doa,dob,rst);
   
   input clka,clkb,ena,enb,wea,web,rst;
   input [11:0] addra;
   input [63:0] dia,dib;
   output [63:0] dob, doa;
   reg [32:0] ram [254:0];
   reg [32:0] dob, doa;
   
   reg [11:0] new_addr=0;
   reg [11:0] addr0_shadow=0;
   reg [11:0] number_of_lines=0;
   
   always @(posedge clka)
   begin
       if (ena)
       begin
           if (wea) ram[addra] <= dia;
           doa <= ram[addra];
       end
   end
   
   
   always @(posedge clkb) begin
       if (enb)
       begin
           dob <= ram[new_addr];
       end   
   end

   always @(posedge clka)
   begin
       if (ena)
       begin
           if (wea & (addra==0)) addr0_shadow<= dia;
       end
   end


   always @(posedge clkb or negedge rst)
   begin
       if (!rst)
       begin
            new_addr<=0;
       end
       else  if (enb)
       begin
           if (new_addr==0)
               number_of_lines <= addr0_shadow;
         
           new_addr<=new_addr+1;
           if (new_addr==number_of_lines)
               new_addr<=0;
       end   
   end
endmodule

Notes:

  1. I've separated the BRAM logic (the first two always blocks) from the new_addr and everything extra you've added.

  2. I've added a addr0_shadow register which acts as ram address #0. Every time you write to address #0 this register samples the data as well. I didn't write directly to number_of_lines since I wanted to make this a close as possible to your current RTL behavior. Maybe you can write it directly.

  3. I didn't check for compilation or behavioral functionality. I leave this to you.