Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory module bidirectional data is unknown

Tags:

verilog

I'm trying to implement this:

enter image description here

This is my code:

module memory 
# (
    parameter AWIDTH = 5,
    parameter DWIDTH = 8
  )
  (
    input wire [AWIDTH-1:0] addr,
    input wire clk, wr, rd,
    inout wire [DWIDTH-1:0] data
  );
    reg [DWIDTH-1:0] mem [AWIDTH-1:0];

    assign data = rd ? mem[addr] : {DWIDTH{1'bz}};

    always @(posedge clk) begin
        if (wr)
            mem[addr] <= data;
    end
endmodule

Here is the result:

Loading snapshot worklib.memory_test:v .................... Done
xcelium> source /tools/cdnc/xcelium/current/tools/xcelium/files/xmsimrc
xcelium> run
Writing addr=00000 data=11111111
Writing addr=11111 data=00000000
Reading addr=00000 data=11111111
At time 40 addr=00000 data=11111111
Reading addr=11111 data=00000000
TEST FAILED
At time 50 addr=11111 data=xxxxxxxx
data should be 00000000
Simulation complete via $finish(1) at time 50 NS + 0
./memory_test.v:35 $finish;
xcelium> exit
TOOL: xrun(64) 19.09-s010: Exiting on May 23, 2021 at 03:45:50 IDT (total: 00:00:01)

It doesn't save my data (x is uninitialized). What am I doing wrong?

Here is the test bench code:

module memory_test;

  localparam integer AWIDTH=5;
  localparam integer DWIDTH=8;

  reg               clk   ;
  reg               wr    ;
  reg               rd    ;
  reg  [AWIDTH-1:0] addr  ;
  wire [DWIDTH-1:0] data  ;
  reg  [DWIDTH-1:0] rdata ;

  assign data=rdata;

  memory
  #(
    .AWIDTH ( AWIDTH ),
    .DWIDTH ( DWIDTH ) 
   )
  memory_inst
   (
    .clk  ( clk  ),
    .wr   ( wr   ),
    .rd   ( rd   ),
    .addr ( addr ),
    .data ( data ) 
   );

  task expect;
    input [DWIDTH-1:0] exp_data;
    if (data !== exp_data) begin
      $display("TEST FAILED");
      $display("At time %0d addr=%b data=%b", $time, addr, data);
      $display("data should be %b", exp_data);
      $finish;
    end
   else begin 
      $display("At time %0d addr=%b data=%b", $time, addr, data);
   end 
  endtask

  initial repeat (67) begin #5 clk=1; #5 clk=0; end

  initial @(negedge clk) begin : TEST
    reg [AWIDTH-1:0] addr;
    reg [DWIDTH-1:0] data;
    addr=0; data=-1;
    $display("Writing addr=%b data=%b",addr,data);
    wr=1; rd=0; memory_test.addr=addr; rdata=data; @(negedge clk);
    addr=-1; data=0;
    $display("Writing addr=%b data=%b",addr,data);
    wr=1; rd=0; memory_test.addr=addr; rdata=data; @(negedge clk);
    addr=0; data=-1;
    $display("Reading addr=%b data=%b",addr,data);
    wr=0; rd=1; memory_test.addr=addr; rdata='bz; @(negedge clk) expect(data);
    addr=-1; data=0;
    $display("Reading addr=%b data=%b",addr,data);
    wr=0; rd=1; memory_test.addr=addr; rdata='bz; @(negedge clk) expect(data);
    $display("Writing ascending data to   descending addresses");
    addr=-1; data=0;
    while ( addr ) begin
      wr=1; rd=0; memory_test.addr=addr; rdata=data; @(negedge clk);
      addr=addr-1;
      data=data+1;
    end
    $display("Reading ascending data from descending addresses");
    addr=-1; data=0;
    while ( addr ) begin
      wr=0; rd=1; memory_test.addr=addr; rdata='bz; @(negedge clk) expect(data);
      addr=addr-1;
      data=data+1;
    end
    $display("TEST PASSED");
    $finish;
  end

endmodule
like image 692
Yuval Saraf Avatar asked Mar 21 '26 05:03

Yuval Saraf


1 Answers

You created mem using

reg [DWIDTH-1:0] mem [AWIDTH-1:0];

So you have mem with 5 rows and then you send address 'h 1f (row 32 counting from 1) which is out of your mem. To fix this problem you have to create mem with 32 rows. I suggest power operator. Example mem with 32 rows:

reg [DWIDTH-1:0] mem [2**AWIDTH-1:0];
like image 106
ToTamire Avatar answered Mar 23 '26 12:03

ToTamire



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!