11-16-2020 10:36 AM - edited 11-16-2020 10:47 AM
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
The write works as expected, but changing the read address (rd_addr) does not appear to have any effect.
What am I doing wrong?
11-16-2020 02:59 PM
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
11-16-2020 02:59 PM
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
11-16-2020 04:02 PM
Duh, thanks.