A testbench and a DUT interact with each other.For Interaction with the DUT, the testbench sends a ‘valid’ signal to the DUT. For Every such ‘valid’, the DUT will later send an ‘ack’ signal. Both ‘valid’ and ‘ack’ are 1 clock wide pulses, they are active high signals and synchronous to the same clock.
The maximum possible rate of ‘valid’ is 1 ‘valid’ in 3 consective clock cycles. The maximum possible rate of ‘ack’ is also 1 ‘ack’ in 3 consective clock cycles. As DUT may take variable amount of time to process the valid sent by testbench the ‘ack’ from DUT can get delayed. Every ‘valid’ for which the DUT is yet to send back the ‘ack’ treated as ‘outstanding_valid’
if the number of such outstanding valid exceed 32, then the bench can’t drive additional ‘valid’ till the number of the outstanding valid comes below 32.
In reply to Subbi Reddy:
Below is untested code. I changed your requirements because they were inconsistent.
I explain the design approach in the comments.
/* Testbench sends a 'valid' signal to the DUT.
For Every such 'valid', the DUT will later send an 'ack' signal.
Both 'valid' and 'ack' are 1 clock wide pulses, synchronous to the same clock.
The maximum (changed to minimum) rate of 'valid' is 1 'valid' in 3 consective clock cycles.
The maximum (Changed to minimum response time)
possible rate of 'ack' is also 1 'ack' in 3 consective clock cycles.
DUT may take variable amount of time to process the valid; 'ack' can get delayed.
Every 'valid' for which the DUT is yet to send back the 'ack' treated as 'outstanding_valid'
if the number of such outstanding valid exceed 32, then the bench can't drive additional 'valid' till the number of the outstanding valid comes below 32.*/
module top;
timeunit 1ns; timeprecision 100ps;
`include "uvm_macros.svh" import uvm_pkg::*;
bit clk, valid, ack, sent, reset_n;
int vld_count; // valid count
let max_delay=10;
default clocking @(posedge clk); endclocking
initial forever #10 clk = !clk;
// Three tasks
// 1) Send valid task
// - Randomided delay followed by send of valid followed by a 2 cycle delay
// 2) Count tracking, increment if sent, decrement if ack
// 3) Controller to manage the send based on the vld_count and sent
// Send the valid
task automatic send_valid();
int delay;
if (!randomize(delay) with
{delay inside {[0:10]};}
) `uvm_error("MYERR", "This is a randomize error");
repeat(delay) @(posedge clk); //
valid <= 1; @(posedge clk) valid<=0;
repeat(2) @(posedge clk);
sent <=1; @(posedge clk) sent <= 0;
endtask: send_valid
// Valid Count tracking
always_ff @(posedge clk) begin: the_count
if(sent && !ack) vld_count <= vld_count +1;
if(ack && !sent) vld_count <= vld_count -1;
am_count: assert(vld_count >=0 && vld_count <33);
end: the_count
always @(posedge clk) begin: controller
send_valid();
@(sent) if(vld_count==32) wait(vld_count < 32);
end: controller
initial begin
repeat(100) begin
@(posedge clk);
if(valid) begin
repeat(4) @(posedge clk);
ack <= 1;
@(posedge clk) ack <= 0;
end
$finish;
end
end
endmodule