In reply to GiuseppeT:
In reply to ben@SystemVerilog.us:
My supervisor told me to not use Assertions so for the moment, don’t want to lie but I don’t even know what they are. He told me to just focus on those 5 situations that I need to verify and to do that, I was trying to realize 2 agents which, if I understood correctly, means to realize one sequencer (or generator), one driver and one monitor for each agent.
[Ben] You can specify the kind of situation to test thru the use of a variable of enum type
and then based on the value of the variable fire concurrent tasks using the fork-join construct. for example, (conceptual code
// Updated from the link of my VMM model
package fifo_pkg;
timeunit 1ns; timeprecision 100ps;
`define TOP fifo_tb
// My update for the situation
// read only, write only, read/write at the same time,
// write when the FIFO is full, and read when the FIFO is empty.
typedef enum {RD, WR, RD_WR, WR_FULL, RD_MT} situation_e;
typedef enum {PUSH, POP, PUSH_POP, IDLE, RESET} fifo_scen_e;
typedef enum {PUSH_MODE, POP_MODE} mode_e;
typedef enum {PASSED, FAILED} fifo_status_e;
typedef enum {DONE_GEN, DONE_BFM} notification_e;
parameter BIT_DEPTH = 4;
parameter FULL = 16;
parameter WIDTH = 32;
typedef logic [WIDTH-1 : 0] word_t;
typedef logic[31:0] wword_t;
typedef logic [WIDTH-1 : 0] wire_word_t;
typedef word_t [0 : (2**BIT_DEPTH-1)] buffer_t;
parameter ALM_EMPTY_REG = 2'b00;
parameter ALM_FULL_REG = 2'b01;
endpackage : fifo_pkg
The two agents then should share a common Scoreboard to check the results and apply the operations; that at least is the idea that I am currently following.
Again, I would use one agent because it is much simpler. For example,
// package alsready imported
task Fifo_cmd_xactor::main();
Fifo_xactn fifo_xactn_0; // transaction to get
Fifo_response fifo_response; // response to generator
// typedef enum {RD, WR, RD_WR, WR_FULL, RD_MT} situation_e;
situation_e situation;
fifo_xactn_0 =new();
// DIrected tests with some randomness depending upon the situation
// Do 5 reads
situation=RD;
bit[0:2] delay;
// READ
randomize(delay);
repeat(5) @(posedge rd_clk)
fork rd_task(delay);
join // joins at end of task processing
randomize(delay);
// WRITE
repeat(4) @(posedge wr_clk)
fork wr_task(delay);
join // joins at end of task processing
...
// If you want to mix those five situations:
// RD, WR, RD_WR, WR_FULL, RD_MT
if (!randomize(situation) with {
situation dist {RD:=1, WR:=2, RD_WR:=1, WR_FULL:=0, RD_MT:=0};
}) $error(" randomization failed");
case (situation)
RD: this.rd_task(dealy);
WR : ...
endcase
endtask : main
// THose task calls above are calls to the driver and to the monitor.
Point is, I kinda feel insecure about the SystemVerilog code that I am writing since I have no one to check on it and literally I have finished a SV course without absorbing concepts yet.
About using the Queue, I thought about using this in the Reference Model, the one which gets the inputs from the Stimulus Monitor, to recreate the behaviour of the design somehow; I should basically recreate those 5 situations mentioned early in the Sequencer/Driver, like creating some tasks I guess? Sorry, I know what to do but maybe I cannot translate it in SV syntax
10 years ago I wrote a UVM model for a counter. I didn’t touch it since.
I am giving you this model in the hope that it might guide you in modeling what you need.
You can commentt out all those UVM includes and simplify the model.
http://systemverilog.us/vf/uvm_counter.zip
Best of luck,
Ben