Even after my fifo has become empty and sequence has stopped, the scoreboard still is running. Did I do something wrong in monitor, I don’t understand.Please help me.
There is nothing wrong with your scoreboard still running, as this is expected behavior. Your run_phase() will end when all of your objections are dropped and all active threads will be killed.
In reply to mikasa:
There is nothing wrong with your scoreboard still running, as this is expected behavior. Your run_phase() will end when all of your objections are dropped and all active threads will be killed.
What problems are you encountering?
Depth of my fifo is 8, I’m running my tb starting from fifo being empty then I have written into it until fifo is full, then I have read from it until fifo is empty again, while reading I have compared whether the data which I’m reading is same as what I have written, I expect my scoreboard to compare the output only eight times as that is the depth of fifo, but in scoreboard it is running 18 times due to which I’m getting failure in match. And I want to correct that.
Your behavior is caused by the #100 in the run_phase of your test.
task run_phase(uvm_phase phase);
fifo_write_sequence fifo_seq;
fifo_seq = fifo_write_sequence::type_id::create("fifo_seq",this);
phase.raise_objection( this, "Starting spi_base_seqin main phase" );
$display("%t Starting sequence fifo_seq run_phase",$time);
fifo_seq.start(env.agt.seq);
#100ns; // Your problem is caused by this delay.
phase.drop_objection( this , "Finished fifo_seq in main phase" );
endtask
If you are commenting out this additional delay it works perfectly and stops after the last transactions.
In reply to mikasa:
Your behavior is caused by the #100 in the run_phase of your test.
task run_phase(uvm_phase phase);
fifo_write_sequence fifo_seq;
fifo_seq = fifo_write_sequence::type_id::create("fifo_seq",this);
phase.raise_objection( this, "Starting spi_base_seqin main phase" );
$display("%t Starting sequence fifo_seq run_phase",$time);
fifo_seq.start(env.agt.seq);
#100ns; // Your problem is caused by this delay.
phase.drop_objection( this , "Finished fifo_seq in main phase" );
endtask
If you are commenting out this additional delay it works perfectly and stops after the last transactions.
This isn’t the correct fix. You should be able to run your environment for any period of time after your sequence is completed with no errors.
Your problem is that your driver doesn’t de-assert the ‘rd’ signal when the transaction is complete, so you continue reading from the fifo while time continues. The correct solution is to fix your driver so that it de-asserts ‘rd’ and ‘wr’ after each transaction.
In reply to cgales:
Ok thank you, I did de-assert ‘rd’ and ‘wr’ and it does solve my problem, but there is another problem arising that there are still some failure cases, it might be in driving/sampling data from interface from/in driver/monitor. I don’t understand when exactly to do that, like you can see in my monitor’s logic I have used a workaround by using count variable,
forever begin
fifo_seq_item trans;
trans=new();
@(posedge vif.MONITOR.clk);
wait(`MON_IF.wr==1 || `MON_IF.rd==1);
begin
if(`MON_IF.wr==1) begin
trans.wr=`MON_IF.wr;
trans.data_in=`MON_IF.data_in;
trans.full=`MON_IF.full;
@(posedge vif.MONITOR.clk);
end
if(`MON_IF.rd==1) begin
count++;
trans.rd=`MON_IF.rd;
if(count==1) begin
@(posedge vif.MONITOR.clk);
end
@(posedge vif.MONITOR.clk);
trans.data_out=`MON_IF.data_out;
trans.empty=`MON_IF.empty;
end
ap.write(trans);
end
because I noticed that in monitor the data is being sampled 2 clock cycle later for first read, but from second read it is being sampled on every next cycle. I’m still getting failure on some matches while success on others. I wan’t to correct this but without using count variable.
If you can please help me with that.
When using clocking blocks, you don’t want to use use the clock signal as a reference. Instead, you want to use the clocking block itself:
forever begin
fifo_seq_item trans;
trans=new();
@(`MON_IF);
wait(`MON_IF.wr==1 || `MON_IF.rd==1);
begin
if(`MON_IF.wr==1) begin
trans.wr=`MON_IF.wr;
trans.data_in=`MON_IF.data_in;
trans.full=`MON_IF.full;
@(`MON_IF);
end
if(`MON_IF.rd==1) begin
count++;
trans.rd=`MON_IF.rd;
if(count==1) begin
@(`MON_IF);
end
@(`MON_IF);
trans.data_out=`MON_IF.data_out;
trans.empty=`MON_IF.empty;
end
ap.write(trans);
end
In reply to cgales:
because I noticed that in monitor the data is being sampled 2 clock cycle later for first read, but from second read it is being sampled on every next cycle. I’m still getting failure on some matches while success on others. I wan’t to correct this but without using count variable.
If you can please help me with that.
Your mechanism with the queue que and the mem is not working correctly. See some details here
I recommend to use an associative array in the scoreboard instead of the queue. This allows you to store the date in a non-consecutive order when using the addr as index.
In reply to AJ_287:
When using clocking blocks, you don’t want to use use the clock signal as a reference. Instead, you want to use the clocking block itself:
I saw you are sending back the response to the sequence. In this case you do not need any scoreboard and monitor. Because you can do the compare inside the sequence. This is very specific but it works. I have implemented thid mechanism in a UVM testbench for a DDR RAM.
If you need more guidance please let me know.