‘count’ is loaded with 0 or count_value when load_counter is true(based on up or down counter mode) and is incremented/decremented every clk_en.
‘count_reached’ is generated combinationally as shown above. The problem is, when load_counter is set (with non-zero skew), count_reached changes immediately(if counter mode or count_values are different). This causes mismatch against expected count_reached in scoreboard for that clk.
I believe, this tend to happen with comb logic and don’t see any solution on TB side to handle it. Just wanted to check, if there is any way TB could handle this?
Please let me know.
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
wait(counter_vif.reset == 1);
fork
forever begin
@(counter_vif.counter_cb);
if (counter_vif.reset == 1) begin
updn_counter_seq_item seq_item_collected =new;
seq_item_collected.count_value = counter_vif.count_value;
seq_item_collected.load_counter = counter_vif.load_counter;
seq_item_collected.up_counter = counter_vif.up_counter;
seq_item_collected.run_counter = counter_vif.run_counter;
items.push_back(seq_item_collected);
end //if reset
end //forever
forever begin
@(counter_vif.counter_cb);
if (counter_vif.reset == 1) begin
if(items.size() > 0) begin
updn_counter_seq_item seq_item_collected = items.pop_front();
seq_item_collected.current_value = counter_vif.counter_cb.current_value;
seq_item_collected.count_reached = counter_vif.counter_cb.count_reached;
//TLM Fifo
trans_collected_port.write(seq_item_collected);
end // item.size
end //reset
end //forever
join //fork
scoreboard
virtual task run_phase(uvm_phase phase);
updn_counter_seq_item counter_pkt;
forever begin
wait(mon_pkt_qu.size() > 0);
counter_pkt = mon_pkt_qu.pop_front();
if(counter_pkt.load_counter) begin //load_counter =1
:
// load the local counter based on up/down counter
:
end //if load_counter
else begin //load_counter =0
if(scb_count_reached ) begin // count_reached == 1
:
// load the local counter based on up/down counter
:
end // //count_reached
else begin //, no count_reached
if(counter_pkt.up_counter) begin//up_counter mode
if(counter_pkt.run_counter )
scb_count = scb_count + 1;
end
else begin //down_counter
if(counter_pkt.run_counter) begin
scb_count = scb_count - 1;
end //run_counter
end //down_counter
end// no count_reached
end //if no load_counter
if ((counter_pkt.up_counter && (scb_count == counter_pkt.count_value -1)) || (!counter_pkt.up_counter && scb_count == 8'h00))
scb_count_reached = 1'b1;
else
scb_count_reached = 1'b0;
:
:
//compare logic
:
:
endtask
count_reached generation is a combinational logic in RTL. Any non-zero skew would set it immediately(i.e.not at the clock edge) when load_counter is true in the middle of counting(count_value can change with load_counter). Scoreboard cannot predict this and hence the mismatch.
Hope, its clear now. Sorry, if the info was incomplete earlier.
Your problem is with respect to your clocking block. First, #0 is not recommended because it is progressing only a step in the SV scheduler.
In the monitor you are considering the cb in in some other parts not (review the monitor code).
In your interface the compiler should complain about the inpout based on logic.
@chr_sue: 1. if you see, there is a commented line with non-zero delays in clocking block. Since it was causing the above stated problem, i ran the test with #0 and things are good with that. The comb logic in RTL is causing mismatch with non-zero delays in cb. That is my main intention of this question.
2. And about the monitor, I have used
@(counter_vif.counter_cb); in both the threads. Not sure which part you have mentioned about.
My driver is as below:
virtual task drive();
//drive with the clock
@( counter_vif.counter_cb);
if (counter_vif.reset ==1) begin
counter_vif.counter_cb.load_counter <= req.load_counter;
counter_vif.counter_cb.count_value <= req.count_value;
counter_vif.counter_cb.up_counter <= req.up_counter;
// pass clk_en as run_counter
counter_vif.counter_cb.run_counter <= counter_vif.clk_en;
end //if reset
endtask
3. Compiler didn’t throw any error for above case.
Thanks chr_sue for pointing them out. Since, our design uses different clocks, i accessed reset as vif.reset. is it really necessary to pass all the inputs through clocking_block? In that case, i can pass reset through fastest clock clocking block(clocks are in sync though).
So far, I have just used initial reset and that’s the reason didn’t face any issue with this.
clk_en is like another slower clock here. So, i didn’t pass it through clocking_block. Should we do that? In that, i may have to review some other code too.
I get your point. My point was, since we assign other variables directly from req(transaction) as below (on right hand side):
counter_vif.counter_cb.load_counter <= req.load_counter;
counter_vif.counter_cb.count_value <= req.count_value;
Thought,
And one more thing, if we have multiple clocking blocks, do we have corresponding clockVar for reset for all the clocking blocks? Because, we may have to refer to reset with any of the clocking block.