Writing into memory and reading from memory

Hi,

Below code is to call write/read task. As seen below, the memory address contains 0x1234_5678 and memory data contains 0x1. After the execution of write task 0x1 will be written at 0x1234_5678 memory location. For the execution of read task, the data of memory location 0x1234_5678 will be read and the memory data will get updated by the value of the 0x1234_5678 memory location (0x1). But from the simulation output, the read task output is shown as 0x0 not 0x1. May I know where I’m going wrong here?

class c1;
  rand byte unsigned byte_data[];
  rand longint unsigned address;
  rand bit byte_enable[];
endclass

module m1;
  bit[31:0] read_data;
  initial begin
    c1 hand1;
    hand1 = new();
    read_data = 0;
    write(32'h1234_5678, 32'h01);
    read (32'h1234_5678, read_data);
  end
endmodule

task write(longint unsigned address, byte unsigned byte_data, bit[3:0] byte_enable = 4'hF);
  c1 hand1;
  hand1 = new();
  hand1.address = address;
  hand1.byte_data = new[4];
  hand1.byte_enable = new[4];
  foreach (hand1.byte_data[i]) begin
    hand1.byte_data[i]    = byte_data[8*i +:8]; 
    hand1.byte_enable[i]   = byte_enable[i];
  end
  $display("Value of address = %h, data = %h",address,byte_data);    
endtask

task read(longint unsigned address, byte unsigned byte_data, bit[3:0] byte_enable = 4'hF);
  c1 hand1;
  hand1 = new();
  hand1.address = address;
  hand1.byte_data = new[4];
  hand1.byte_enable = new[4];
  foreach (hand1.byte_data[i]) begin
    hand1.byte_data[i]    = byte_data[8*i +:8]; 
    hand1.byte_enable[i]   = byte_enable[i];
  end
  $display("Value of address = %h",address); 
  $display("Value of data = %h",byte_data);
endtask

Simulation Output
Value of address = 0000000012345678, data = 01
Value of address = 0000000012345678
Value of data = 00

In reply to basilleaf:

You should put a little more effort into explaining why you think byte_data should be 1. How did it get that value?

In reply to dave_59:

I’m sending read/write transaction. Im writing 0x1 value to address 0x1234_5678 and when reading address(0x1234_5678), the byte_data is expected to show 0x1 output. With that expectation, I have coded as shown above. This is why the byte_data should be 1.

In reply to basilleaf:

You need to show us where you think you have assigned a value to byte_data. I do not see where you made that assignment.

In reply to dave_59:

I pass the byte_data argument value when the task write is called.

write(32'h1234_5678, 32'h01);

In reply to basilleaf:

You do not have any delay statements within the write/read task.
This schedules both read and write operation at the same simulation cycle.
Hence the read task does not see the updated value of byte_data instead the initial value.

I added a $time to your display statements and see the below result:
Note: 0ns timestamp prints in the result.


  $display("At %0tns Value of address = %0h, data = %0h",$time, address,byte_data);    
  ...
  ...
  $display("At %0tns Value of address = %0h",$time, address); 
  $display("At %0tns Value of data = %0h",$time, byte_data);

Result:
At 0ns Value of address = 0000000012345678, data = 01
At 0ns Value of address = 0000000012345678
At 0ns Value of data = 00


In reply to natasv:

I added #1us before end of the task, i still see the same output where data = 00 not 01

In reply to basilleaf:

  1. The write and read tasks look identical with the exception of the $display() calls at the end. Can you explain what the differences in the two tasks are?
  2. You create new ‘c1’ handles within each task. Are you expecting to be using the same ‘c1’ in both tasks?
  3. As Dave commented, there is nothing in the read task which modifies byte_data. You will display the value passed into the task, which in this case is ‘0’. Everything is working as coded.

In reply to cgales:

I will give example for each task

  1. Write task
    Ex: Write to address 0x123_4567 with value 0x1
    Code:
class c1;
  rand byte unsigned byte_data[];
  rand longint unsigned address;
  rand bit byte_enable[];
endclass
 
module m1;
  initial begin
    c1 hand1;
    hand1 = new();
    write(32'h123_4567, 32'h01);
  end
endmodule
 
task write(longint unsigned address, byte unsigned byte_data, bit[3:0] byte_enable = 4'hF);
  c1 hand1;
  hand1 = new();
  hand1.address = address;
  hand1.byte_data = new[4];
  hand1.byte_enable = new[4];
  foreach (hand1.byte_data[i]) begin
    hand1.byte_data[i]    = byte_data[8*i +:8]; 
    hand1.byte_enable[i]   = byte_enable[i];
  end
  $display("Write task: Value of address = %h, data = %h",address,byte_data);    
endtask

Output:
Value of address = 01234567, data = 01

Read task
Ex: Read from address 0x123_4567 (bit0) until it is 1
I try to implement the write task I have coded for this read task but I think I went wrong.

class c1;
  rand byte unsigned byte_data[];
  rand longint unsigned address;
  rand bit byte_enable[];
endclass
 
module m1;
  bit[31:0] read_data;
  initial begin
    c1 hand1;
    hand1 = new();
    read_data = 0;
    read (32'h1234_5678, read_data);
  end
endmodule

task read(longint unsigned address, byte unsigned byte_data, bit[3:0] byte_enable = 4'hF);
  c1 hand1;
  hand1 = new();
  hand1.address = address;
  hand1.byte_data = new[4];
  hand1.byte_enable = new[4];
  foreach (hand1.byte_data[i]) begin
    hand1.byte_data[i]    = byte_data[8*i +:8]; 
    hand1.byte_enable[i]   = byte_enable[i];
  end
  $display("Read task: Value of address = %h, data = %h",address, byte_data);
endtask
  1. Im expecting to use the same “c1” in both tasks with the expectation of reading the data value (byte_data) ofthe address argument value passed in the read task.

  2. I think the code I have prepared is wrong based on what you are saying. I am not sure how to code for read task as the example I mentioned above.

In reply to basilleaf:

You need to change your class definition of your memory. Perhaps use an associative array for your memory and storing values using the address as an index? You don’t need address or byte_enable in your class as those variables define a specific transaction, and not part of the memory.

You can add write() and read() functions to your class, and call those from your module code.