cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
ggillett
Contributor
Contributor
581 Views
Registered: ‎08-14-2018

Simulating inferred BRAM

Jump to solution

Hi,

I am running into some difficulty with a behavioral simulation of inferred BRAM in 2020.1. The system verilog module is:

 

module asym_sdp_ram #(
  parameter   WIDTH = 16,         // number of bits in an element
  parameter   ADDR_BITS = 4,     // RAM holds 2**ADDR_BITS elements
  parameter   ELM_ADDR_BITS = 2, // 2**ELM_ADDR_BITS elements output per read.
  localparam  RD_WIDTH = 2**ELM_ADDR_BITS*WIDTH,     // output bus width
  localparam  RD_ADDR_BITS = ADDR_BITS-ELM_ADDR_BITS // read port
 ) (
   
   input wire                       wr_clk,
   input wire                       rd_clk,
   input wire                       ena,
   input wire                       enb,
   input wire                       wr_en,
   input wire   [ADDR_BITS-1:0]     wr_addr,
   input wire   [RD_ADDR_BITS-1:0]  rd_addr,
   input wire   [WIDTH-1:0]         din,
   output logic [RD_WIDTH-1:0]      dout
   
);

logic [WIDTH-1:0] RAM [0:2**ADDR_BITS-1]; // = {{WR_WIDTH{1'b0}}};
  
logic [RD_WIDTH-1:0] read_data;


// porta write
always @(posedge wr_clk) 
  if (ena)
    if (wr_en) RAM[wr_addr] <= din; 

// portb read    
integer elm_addr;
always @(posedge rd_clk) begin
  for (elm_addr = 0; elm_addr < 2**ELM_ADDR_BITS; elm_addr++)
    read_data[(elm_addr+1)*WIDTH-1 -:WIDTH] <= RAM[{rd_addr, elm_addr}];
  if (enb) 
    dout <= read_data;
end
endmodule

 

I think this complies with the template in UG901, I've tried variations but the read port does not appear to work. This testbench:

 

module asym_sdp_ram_TB;

parameter WIDTH = 16;
parameter ADDR_BITS = 4;
parameter ELM_ADDR_BITS = 2; // 4 elements on the bus at a time

reg clk;
reg  wr_en;
reg [WIDTH-1:0] din = 0;
wire [WIDTH*2**ELM_ADDR_BITS-1:0] dout;
reg [ADDR_BITS-1:0] wr_addr;
reg [ADDR_BITS-ELM_ADDR_BITS-1:0] rd_addr;
reg ena, enb;

asym_sdp_ram #(
  .WIDTH(WIDTH),
  .ADDR_BITS(ADDR_BITS),
  .ELM_ADDR_BITS(ELM_ADDR_BITS)
) asym_sdp_ram_instance (
  .wr_clk(clk),
  .rd_clk(clk),
  .ena(ena),
  .enb(enb),
  .wr_en(wr_en),
  .wr_addr(wr_addr),
  .rd_addr(rd_addr),
  .din(din),
  .dout(dout)
);

initial begin
clk=1; wr_addr=0; rd_addr=2; wr_en=0; din=0; ena=1; enb=1;
# 8.1 wr_addr=1; wr_en=1;
# 8 wr_en=0;
# 8 rd_addr=0;
# 8 rd_addr=1;
# 8 rd_addr=2;
# 8 rd_addr=3;
end

always 
  #4 clk<=~clk; 
 
always @(posedge clk)
  din <= din+1;
  
endmodule

 

 produces this behavioral trace

BRAM sim.png 

The write works as expected, but changing the read address (rd_addr) does not appear to have any effect.  

What am I doing wrong? 

0 Kudos
1 Solution

Accepted Solutions
necare81
Voyager
Voyager
550 Views
Registered: ‎03-31-2016

How wide do you think elm_addr, or  any integer, is ?
What does that mean when you try to concatenate it to rd_addr?

 

 

 

Assume that rd_addr is set to 2 and elm_addr is 1  and all the parameters are at the default values.
this code {rd_addr,elm_addr} will produce what in binary?

 

You think it willl be 1001

But because you used integer it will be on at 1000000000000000000000000000000001

 

So elm_addr should be a sized value, like bit [ELM_ADDR_BITS-1:0] not an integer

View solution in original post

2 Replies
necare81
Voyager
Voyager
551 Views
Registered: ‎03-31-2016

How wide do you think elm_addr, or  any integer, is ?
What does that mean when you try to concatenate it to rd_addr?

 

 

 

Assume that rd_addr is set to 2 and elm_addr is 1  and all the parameters are at the default values.
this code {rd_addr,elm_addr} will produce what in binary?

 

You think it willl be 1001

But because you used integer it will be on at 1000000000000000000000000000000001

 

So elm_addr should be a sized value, like bit [ELM_ADDR_BITS-1:0] not an integer

View solution in original post

ggillett
Contributor
Contributor
535 Views
Registered: ‎08-14-2018

Duh, thanks.

0 Kudos