Assertion: Expected data check // A review from a user's question

I’m trying to code an assertion that when go == 1 (from 0->1) or
when go ==1 (for more than 1 clock) data is held until is checked later when ready==1.
Maybe I shouldn’t create an assertion this way or choose a better control signal.
Could I modify the sva coding to handle this go condition?

 property abc ;
logic [WIDTH-1:0] v;
@(posedge clk) disable iff (rst)
(go, v = data) |=> ##[1:$] (ready ==1) ##0 (out == v) );
endproperty
assert_abc_check : assert  property (abc)
$info ("@%0d ns : PASS : out = %h , data = %h" , $time, out, data);
else
$info ("@%0d ns : FAIL : out = %h", $time, out);

There are several problems with the way you wrote the property

  • Multithreading and data capture When you write (go, v = data) |=> …
    At every clocking event go==1 you save into v the value of data. This creates multiple threads. That means that if @cycle1 go==1, and data==5, and then @cycle 2 go==1 and data==7, then what your property is expressing is that at some points in the future (e.g., @ cycle 20 ready==1 && out== 5 (or 7), and then some cycle(s) later (e.g., @cycle30) ready is again ==1, and out == 7 (or 5 if out was 7 @cyle 20). If you are not looking for the first occurrence of go then I would use the $rose; thus ($rose(go), v = data) |=> …[
  • Uniqueness This is *exclusivity or uniqueness of each attempted thread sequences).*I explain this issue in my SVA Handbook 4th Edition, I also addressed that topic at
    Counting number of events on clock a, while clock o is forbidden - SystemVerilog - Verification Academy
    Hint: use the module variables int ticket, now_serving;
  • **|=> ##[1:] (ready ==1)** This property can **never be false** because of the ##(1:) because if the ending conditions are false, the simulator will keep on checking for naother possible success. Also, Why the |=> ##(1:… ? |=> is same as 1’b1 ##1 |->
    I would rewire that property as

property abc ;
logic [WIDTH-1:0] v;
@(posedge clk) disable iff (rst)
($rose(go), v = data) |->
first_match(##[:$] (ready ==1)) ##0 (out == v) );
endproperty
// May prefer this instead
($rose(go), v = data) |->
ready[->1] ##0 (out == v) ); // OK too

  • For your info and error displays, I would use UVM messaging. Examples, from my book.
import uvm_pkg::*; `include "uvm_macros.svh"
module uvm_sva_ex; // /ch4/4.2/uvm_sva_ex.sv
bit clk, a, b, c, req, ack;
parameter CLK_HPERIOD = 10;
string tID="UART ";
initial begin : clk_gen forever #CLK_HPERIOD clk <= !clk; end : clk_gen
default clocking def_cb @ (posedge clk); endclocking : def_cb
ap_FULL: assert property(a) else
`uvm_info(tID,$sformatf("%m : error in a %b", a), UVM_FULL); // Line 15
ap_test2: assert property(a) else
`uvm_error(tID,$sformatf("%m : error in a %b", a)); // Line 17

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


In reply to ben@SystemVerilog.us:

Nice solution Ben, thank you very much for sharing as this seems to be a commonly needed assertion.

-R

Thanks Ben for your feedback.

I have another problem related to this assertion.

Turns out the logic I’m testing has a 2 deep pipeline.

So when $rose(go) occurred twice, the payload was also updated twice before ready == 1.

When ready ==1, the payload had 2nd data but ready==1 with out was expecting the 1st data.

So I got a FAIL in simulator.

How to update the assertion to add a pipeline or FIFO so that the payload data gets

properly matched up with corresponding ready ?

Also, maybe make the FIFO/pipeline generic enough to have an N-deep and store more levels.

In reply to davidct:
The following code may help you. You need to dig in to understand it.
The ticket, my_ticket, now_serving stuff emulates what happens in something you experienced in a hardware store, like the paint dpt where every customer wants service, but there is only one attendant. So the ticket system provides exclusivity.
In this model, @go, data → Q. @ rdy, out==1st element of the Q. Other assertions do ot respond to this rdy because they do not have the “right ticket”, i.e., one customer to each rdy.
// Model also at http://SystemVerilog.us/vf/question2.sv
Also, see my paper at
PAPER: Understanding the SVA Engine + Simple alternate solutions | Verification Academy
Abstract: Understanding the engine behind SVA provides not only a better appreciation and limitations of SVA, but in some situations provide features that cannot be simply implemented with the current definition of SVA. This paper first explains, by example, how a relatively simple assertion example can be written without SVA with the use of SystemVerilog tasks; this provides the basis for understanding the concepts of multithreading and exit of threads upon a condition, such as an error in the assertion. The paper then provides examples that uses computational variables within threads; those variables can cause, in some cases, errors in SVA. The strictly emulation model with tasks solves this issue.


import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	bit clk, go, ready, rst=0;  
	int now_serving=1, ticket=0; 
	int q_data[$], data, pipe1, pipe2, out;
	initial forever #10 clk=!clk;  
	function automatic void push_data(int data); 
		q_data.push_back(data); 
	endfunction : push_data 
	function automatic int get_ticket(); 
	    ticket=ticket+1'b1;
		return ticket; 
	endfunction : get_ticket  	
	/* ap_go_ready: assert property(
	  @(posedge clk) disable iff (rst)
		($rose(go), push_data(data)) |-> 
		 ready[->1] ##0 out == q_data.pop_front());*/ 
	// * Error: question2.sv(11): The method 'pop_front' is not allowed in assertions as it has side effects.
	
	task automatic t_check_data(int my_ticket); 
		forever begin 
			@(posedge clk) if(ready && my_ticket==now_serving) begin : is_ready	
					a_data_check: assert(out == q_data.pop_front());
					$display("@ %t my_ticket", $time, my_ticket); 
					now_serving <= now_serving+1'b1;
					return;
				end 
				// ready[->1] ##0 out == q_data.pop_front());
		end 
	endtask 	
	
	property p_go_ready;
		int my_ticket;
		@(posedge clk) disable iff (rst)
		($rose(go), push_data(data), my_ticket=get_ticket()) |-> 
                      (1,t_check_data(my_ticket)); 
	endproperty
	
	ap_go_ready: assert property(p_go_ready);	
	always_ff  @(posedge clk)  begin 
		if(go) begin 
			pipe1 <= data; 
			pipe2 <= pipe1;
		end
	end 	
	/* So when $rose(go) occurred twice, the payload was also updated twice before ready == 1.
When ready ==1, the payload had 2nd data but ready==1 with out was expecting the 1st data.
So I got a FAIL in simulator.
How to update the assertion to add a pipeline or FIFO so that the payload data gets
properly matched up with corresponding ready ?
Also, maybe make the FIFO/pipeline generic enough to have an N-deep and store more levels.*/


	initial begin 
		repeat(200) begin 
			@(posedge clk);   
			if (!randomize(data, go, ready)  with 
					{ data inside {[1:200]};
					  go dist {1'b1:=1, 1'b0:=3};
					  ready dist {1'b1:=1, 1'b0:=7};

					}) `uvm_error("MYERR", "This is a randomize error")
					end 
					$stop; 
		end 
endmodule  
/* simulation 
** Error: Assertion error.
#    Time: 350 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  350 my_ticket          1
# ** Error: Assertion error.
#    Time: 370 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  370 my_ticket          2
# ** Error: Assertion error.
#    Time: 390 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  390 my_ticket          3
# ** Error: Assertion error.
#    Time: 550 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  550 my_ticket          4
# ** Error: Assertion error.
#    Time: 770 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  770 my_ticket          5
# ** Error: Assertion error.
#    Time: 790 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  790 my_ticket          6
# ** Error: Assertion error.
#    Time: 850 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  850 my_ticket          7
# ** Error: Assertion error.
#    Time: 870 ns  Scope: top.t_check_data.is_ready.a_data_check File: question2.sv Line: 23
# @                  870 my_ticket          8
# ** Error: Assertion error. */  

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


In reply to ben@SystemVerilog.us:

Hi Ben,

I tried to run your code with Cadence Incisive 15.2.
I got this error:

			($rose(go), push_data(data), my_ticket=get_ticket()) |-> (1,t_check_data(my_ticket)); 
			                                                                       |

ncvlog: *E,SFLNOS (tb.sv,35|75): Delays or wait statements in match item task calls are not supported.

What’s the workaround?

David

In reply to davidct:

In reply to ben@SystemVerilog.us:
Hi Ben,
I tried to run your code with Cadence Incisive 15.2.
I got this error:
($rose(go), push_data(data), my_ticket=get_ticket()) |-> (1,t_check_data(my_ticket));
|
ncvlog: *E,SFLNOS (tb.sv,35|75): Delays or wait statements in match item task calls are not supported.
What’s the workaround?
David

  • This is a tool issue, task calls are supported by 1800’2012

sequence_match_item ::= operator_assignment | inc_or_dec_expression | subroutine_call
subroutine_call ::=    tf_call | system_tf_call | method_call | [ std:: ] randomize_call
tf_call(note 37) ::= ps_or_hierarchical_tf_identifier { attribute_instance } [ ( list_of_arguments ) ]
Note 37: It shall be illegal to omit the parentheses in a tf_call unless the subroutine is a task, void function, or class method. If the subroutine is a nonvoid class function method, it shall be illegal to omit the parentheses if the call is directly
recursive. 

import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	bit clk, go, ready, rst=0;  
	int now_serving=1, ticket=0; 
	int q_data[$], data, pipe1, pipe2, out;
	initial forever #10 clk=!clk;  
	function automatic void push_data(int data); 
		q_data.push_back(data); 
	endfunction : push_data 
	function automatic int get_ticket(); 
	    ticket=ticket+1'b1;
		return ticket; 
	endfunction : get_ticket  	
	/* ap_go_ready: assert property(
	  @(posedge clk) disable iff (rst)
		($rose(go), push_data(data)) |-> 
		 ready[->1] ##0 out == q_data.pop_front());*/ 
	// * Error: question2.sv(11): The method 'pop_front' is not allowed in assertions as it has side effects.
	
	task automatic t_go_ready(); 
	  automatic int my_ticket;
		if($rose(go, @(posedge clk))) begin 
			 push_data(data);
			 my_ticket=get_ticket();
			 t_check_data(my_ticket); 
		end 
		else return;
	endtask 	
	
	task automatic t_check_data(int my_ticket); 
		forever begin 
			@(posedge clk) if(ready && my_ticket==now_serving) begin : is_ready	
					a_data_check: assert(out == q_data.pop_front());
					$display("@ %t my_ticket", $time, my_ticket); 
					now_serving <= now_serving+1'b1;
					return;
				end 
				// ready[->1] ##0 out == q_data.pop_front());
		end 
	endtask 	
	
	always_ff  @(posedge clk)  begin 
		fork 
			 t_go_ready();
		join
	end 	
	
	property p_go_ready;
		int my_ticket;
			@(posedge clk) disable iff (rst)
				($rose(go), push_data(data), my_ticket=get_ticket()) |-> (1,t_check_data(my_ticket)); 
	endproperty
	
	// ap_go_ready: assert property(p_go_ready);	
	always_ff  @(posedge clk)  begin 
		if(go) begin 
			pipe1 <= data; 
			pipe2 <= pipe1;
		end
	end 	
	/* So when $rose(go) occurred twice, the payload was also updated twice before ready == 1.
When ready ==1, the payload had 2nd data but ready==1 with out was expecting the 1st data.
So I got a FAIL in simulator.
How to update the assertion to add a pipeline or FIFO so that the payload data gets
properly matched up with corresponding ready ?
Also, maybe make the FIFO/pipeline generic enough to have an N-deep and store more levels.*/


	initial begin 
		repeat(200) begin 
			@(posedge clk);   
			if (!randomize(data, go, ready)  with 
					{ data inside {[1:200]};
					  go dist {1'b1:=1, 1'b0:=3};
					  ready dist {1'b1:=1, 1'b0:=7};

					}) `uvm_error("MYERR", "This is a randomize error")
					end 
					$stop; 
		end 
endmodule   

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


In reply to ben@SystemVerilog.us:

Hi Ben,

I just tried to compile with Cadence Incisive 15.2 (uses uvm1.1d)
and got a different error now.

irun(64): 15.20-s032: (c) Copyright 1995-2017 Cadence Design Systems, Inc.
Compiling UVM packages (uvm_pkg.sv cdns_uvm_pkg.sv) using uvmhome location /cad/installs/INCISIVE152/tools/methodology/UVM/CDNS-1.1d

	if($rose(go, @(posedge clk))) begin 
	       |

ncvlog: *E,ILLSVF (tb.sv,22|9): Illegal use of sampled value function outside concurrent assertions and procedural blocks.

Any other workarounds ?

Thanks,

David

In reply to davidct:

What you have is a tool issue. Please contact your vendor on this.
All the code I wrote in this reply is compliant with 1800’2012.
On the $rose, you can emulate this by using the current and past values.
You can use a FF or $past for that.
Ben Ben@systemverilog.us

Vendor replied with this simple test case.
Their remedy is similar to your fork and join.

//====TESTCASE ============

package om;
reg b;
event a;
endpackage

module top();
import om::*;
reg clk;
task report_period();
    om::b = 1'b1;
    -> om::a;
    @(negedge clk)   //THIS IS CAUSING THE ERROR ncvlog: *E,SFLNOS
    om::b  = 1'b0;
endtask
reg mm2s_err;
property p1;
       @(posedge clk)
                  $rose(mm2s_err) |-> (1'b1, report_period());
       endproperty
assert property(p1);
endmodule

//========TESTCASE ENDS=========

----------------------------------Output:-------------------------------------------
$rose(mm2s_err) |-> (1’b1, report_period());
|
ncvlog: *E,SFLNOS (test_1.sv,18|45): Delays or wait statements in match item task calls are not supported.

You can use following work-around to get away this limitation, using function wrapper to invoke/fork the time-consuming task from within the assertion.

Please refer to the following modified code :

package om;
reg b;
event a;
endpackage

module top();
import om::*;
reg clk;
task report_period();
    om::b = 1'b1;
    -> om::a;
    @(negedge clk)   //THIS IS CAUSING THE ERROR ncvlog: *E,SFLNOS
    om::b  = 1'b0;
endtask

function smi_report_period();
  fork
    report_period();
  join_none
  return 1;
endfunction

reg mm2s_err;
property p1;
  reg ret_val=1;
       @(posedge clk)
                  $rose(mm2s_err) |-> (1'b1, ret_val=smi_report_period()) ##0 ret_val;
endproperty
assert property(p1);

endmodule

This is similar to your fork/join solution.
But your fork/join was not within the function.

Now I need to figure out how to tie this coding workaround into your code.

In reply to davidct:
Some comments:

  • On the $rose(a), you can use
    $past(a, 1, 1, @(posedge clk))==1’b0 &&a // Same as $rose(a)
  • On the vendor lack of support (or the many NYI Not Yet Implemented], you need to put pressure on him to start better supporting 1800-2012
  • Below is code that works with your tool
    See Edit code - EDA Playground
    I had to emulate the $rose by creating a past_go with
    always_ff @(posedge clk) past_go <= go;
    Also, had to use always instead of always_ff where I used to fork join.
    Cadence says Fork-join illegal within an always_ff construct., but other tools do not put this restriction. Sounds like a tool issue from the tool you use.> The always_ff procedure imposes the restriction that it contains one and only one event control and no blocking timing controls. Variables on the left-hand side of assignments within an always_ff procedure, including variables from the contents of a called function, shall not be written to by any other process.
    Software tools should perform additional checks to warn if the behavior within an always_ff procedure does not represent sequential logic.]

import uvm_pkg::*; 
`include "uvm_macros.svh" 
module top; 
	bit clk, go, ready, rst=0, past_go;  
	int now_serving=1, ticket=0; 
	int q_data[$], data, pipe1, pipe2, out;
	initial forever #10 clk=!clk;  
	function automatic void push_data(int data); 
		q_data.push_back(data); 
	endfunction : push_data 
	function automatic int get_ticket(); 
	    ticket=ticket+1'b1;
		return ticket; 
	endfunction : get_ticket  	
	/* ap_go_ready: assert property(
	  @(posedge clk) disable iff (rst)
		($rose(go), push_data(data)) |-> 
		 ready[->1] ##0 out == q_data.pop_front());*/ 
	// * Error: question2.sv(11): The method 'pop_front' is not allowed in assertions as it has side effects.
 
	task automatic t_go_ready(); 
	  automatic int my_ticket;
      //if( $rose(go, @(posedge clk))) begin
      // if($past(go, 1,1, @(posedge clk))==1'b0  && go) begin
      if(past_go==1'b0  && go) begin
			 push_data(data);
			 my_ticket=get_ticket();
			 t_check_data(my_ticket); 
		end 
		else return;
	endtask 	
 
	task automatic t_check_data(int my_ticket); 
		forever begin 
			@(posedge clk) if(ready && my_ticket==now_serving) begin : is_ready	
					a_data_check: assert(out == q_data.pop_front());
					$display("@ %t my_ticket", $time, my_ticket); 
					now_serving <= now_serving+1'b1;
					return;
				end 
				// ready[->1] ##0 out == q_data.pop_front());
		end 
	endtask 	
    
  always_ff  @(posedge clk) past_go <= go; 
  
  always  @(posedge clk)  begin 
		fork 
			 t_go_ready();
		join
	end 	
 
	/* property p_go_ready;
		int my_ticket;
			@(posedge clk) disable iff (rst)
				($rose(go), push_data(data), my_ticket=get_ticket()) |-> (1,t_check_data(my_ticket)); 
	endproperty */ 
 
	// ap_go_ready: assert property(p_go_ready);	
	always_ff  @(posedge clk)  begin 
		if(go) begin 
			pipe1 <= data; 
			pipe2 <= pipe1;
		end
	end 	
	/* So when $rose(go) occurred twice, the payload was also updated twice before ready == 1.
When ready ==1, the payload had 2nd data but ready==1 with out was expecting the 1st data.
So I got a FAIL in simulator.
How to update the assertion to add a pipeline or FIFO so that the payload data gets
properly matched up with corresponding ready ?
Also, maybe make the FIFO/pipeline generic enough to have an N-deep and store more levels.*/
 
 
	initial begin 
		repeat(200) begin 
			@(posedge clk);   
			if (!randomize(data, go, ready)  with 
					{ data inside {[1:200]};
					  go dist {1'b1:=1, 1'b0:=3};
					  ready dist {1'b1:=1, 1'b0:=7};
 
					}) `uvm_error("MYERR", "This is a randomize error")
					end 
					$stop; 
		end 
endmodule   
 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


Hi Ben,

Thanks again so much for your time and valuable feedback.

I got it to compile now and I’m analyzing your code and results.

I will get your assertions book to add to my collection of technical books.

David

It runs now but results are not correct.
out is always 0 and assertion will trigger

out = 00000000

@50 ns : $rose(go) : PUSH_DATA : data = 59
@50 ns : q_data[0] = 59, q_data[1] = 0
@70 ns : data = 0000003b, pipe1 = 00000000, pipe2 = 00000000
ncsim: *E,ASRTST (./tb.sv,48): (time 70 NS) Assertion top.t_check_data.is_ready.a_data_check has failed
@70 ns : out = 00000000
@70 ns : my_ticket = 00000000000000000000000000000001
@70 ns : now_serving = 00000000000000000000000000000001

I added more debugging output to the original code

//In reply to davidct:
//Some comments:
// On the $rose(a), you can use $past(a, 1, 1, @(posedge clk))==1’b0 &&a // Same as $rose(a)
// On the vendor lack of support (or the many NYI Not Yet Implemented], you need ot put pressure on him to start better supporting 1800-2012
// Below is code that works with your tool See Edit code - EDA Playground
// I had to emulate the rose by creating a past_go with // always_ff @(posedge clk) past_go <= go; // Also, had to use always instead of always_ff whenre I used to fork join. import uvm_pkg::*; `include "uvm_macros.svh" module top; bit clk, go, ready, rst=0, past_go; int now_serving=1, ticket=0; int q_data[], data, pipe1, pipe2, out;
initial forever #10 clk=!clk;
function automatic void push_data(int data);
q_data.push_back(data);
$display(“@%0d ns : $rose(go) : PUSH_DATA : data = %0d”, $time, data);
$display(“@%0d ns : q_data[0] = %0d, q_data[1] = %0d”, $time, q_data[0], q_data[1]);
endfunction : push_data
function automatic int get_ticket();
ticket=ticket+1’b1;
return ticket;
endfunction : get_ticket
/* ap_go_ready: assert property(
@(posedge clk) disable iff (rst)
($rose(go), push_data(data)) |->
ready[->1] ##0 out == q_data.pop_front());*/
// * Error: question2.sv(11): The method ‘pop_front’ is not allowed in assertions as it has side effects.

    task automatic t_go_ready();
      automatic int my_ticket;
  //if( $rose(go, @(posedge clk))) begin
  // if($past(go, 1,1, @(posedge clk))==1'b0  && go) begin

// create a one shot in sv to behave like $rose(go)
if(past_go==1’b0 && go) begin
push_data(data); // occurs immediately since using function
my_ticket=get_ticket(); // occurs immediately since using function
t_check_data(my_ticket); // using task with clk which consumes time so it will be processed sequentially by simulator
end
else return;
endtask

    task automatic t_check_data(int my_ticket);
            forever begin
                    @(posedge clk) if(ready && my_ticket==now_serving) begin : is_ready
                                    a_data_check: assert(out == q_data.pop_front());
                                    $display("@%0d ns : out = %h", $time, out);
                                    $display("@%0d ns : my_ticket = %b", $time, my_ticket);
                                    now_serving <= now_serving+1'b1;
                                    $display("@%0d ns : now_serving = %b", $time, now_serving);
                                    return;
                            end
                            // ready[->1] ##0 out == q_data.pop_front());
            end
    endtask

// use to create one shot equivalent for creating $rose(go)
always_ff @(posedge clk)
past_go <= go;

always @(posedge clk) begin
fork
t_go_ready();
join
end

    /* property p_go_ready;
            int my_ticket;
                    @(posedge clk) disable iff (rst)
                            ($rose(go), push_data(data), my_ticket=get_ticket()) |-> (1,t_check_data(my_ticket)); 
    endproperty */

    // ap_go_ready: assert property(p_go_ready);    
    always_ff  @(posedge clk)  begin
            if(go) begin
                    pipe1 <= data;
                    pipe2 <= pipe1;
                    $display("@%0d ns : data = %h, pipe1 = %h, pipe2 = %h", $time, data, pipe1, pipe2);
            end
    end

    /* So when $rose(go) occurred twice, the payload was also updated twice before ready == 1.

When ready ==1, the payload had 2nd data but ready==1 with out was expecting the 1st data.
So I got a FAIL in simulator.
How to update the assertion to add a pipeline or FIFO so that the payload data gets
properly matched up with corresponding ready ?
Also, maybe make the FIFO/pipeline generic enough to have an N-deep and store more levels.*/

    initial begin
            repeat(200) begin
                    @(posedge clk);
                    if (!randomize(data, go, ready)  with
                                    { data inside {[1:200]};
                                      go dist {1'b1:=1, 1'b0:=3};
                                      ready dist {1'b1:=1, 1'b0:=7};

                                    }) `uvm_error("MYERR", "This is a randomize error")
                                    end
                                    $stop;
            end

initial begin
$shm_open(“waves.shm”);
$shm_probe(“ASM”);
end

endmodule

Hi Ben,

One last thing is related to the dist function.

I don’t want a back to back 1 on “go” and no back to back 1 on “ready”.

“go” and “ready” should go high for one clock pulse only, never 2 or greater clock cycles consecutively of high.

How to modify the sv code to do this?

Thanks,

David

In reply to davidct:

Hi Ben,
One last thing is related to the dist function.
I don’t want a back to back 1 on “go” and no back to back 1 on “ready”.
“go” and “ready” should go high for one clock pulse only, never 2 or greater clock cycles consecutively of high.
How to modify the sv code to do this?

The goals of my code were to demonstrate exclusivity in the assertions, in that each thread is independent of other threads, and the termination of one does not terminate the others.
Since data is piped, I used a ques ndeep, where “n” is infinite, but you can declare a queue of 2.
On the testbench, I created a quick and dirty one to verify the concepts. There are many ways to generate a Testbench, including directed tests. That should be an exercise that you need to do. If you want to use my quick and dirty model, change the constraints. I did not address the “out” signal.

A comment about your questions, please take these in a positive, constructive manner:

  • It seems that you lack some design experience; I say this because you should have been able to create a $rose(a) using an always_ff and combinational logic. Edge detect is elementary.
  • If you need more knowledge in design, may I recommend my book Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn 978-1539769712 ? That book addresses a lot of logic design concepts needed by every design engineer. See the TOC http://systemverilog.us/RealChipDesign_preface.pdf , but they include the various types of counters, EDAC, metastability, async FIFO, building a CPU using FSMs or microcode, arithmetic machines, etc. It also includes some tb design approaches. Those testbench approaches, though old and are replaced by UVM, they essentially have the same concepts of transaction, drives, etc.

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr