The design spec says, “Read Operation: address and rd_en should be driven on the same clock cycle, Design will respond with the data in the next clock cycle.”
But in the UVM monitor and driver codes under the rd_en conditions, we, respectively, are sampling and driving the memory’s read data after waiting on two of posedge clocks. Why is that?
Both the driver and monitor are poorly written and using extra clocks to mask functional issues.
When you are using clocking blocks, everything should be sampled in relation to the clocking block. In this testbench, the driver and monitor are mixing the top interface clock and the clocking block data values.
Here is a better monitor:
virtual task run_phase(uvm_phase phase);
forever begin
@(vif.monitor_cb);
if(vif.monitor_cb.wr_en) begin
trans_collected = new();
trans_collected.addr = vif.monitor_cb.addr;
trans_collected.wr_en = vif.monitor_cb.wr_en;
trans_collected.wdata = vif.monitor_cb.wdata;
trans_collected.rd_en = 0;
item_collected_port.write(trans_collected);
end
if(vif.monitor_cb.rd_en) begin
trans_collected = new();
trans_collected.addr = vif.monitor_cb.addr;
trans_collected.rd_en = vif.monitor_cb.rd_en;
trans_collected.wr_en = 0;
@(vif.monitor_cb);
trans_collected.rdata = vif.monitor_cb.rdata;
item_collected_port.write(trans_collected);
end
end
endtask : run_phase