# Clock Monitor

## Introduction

The Clock Monitor is a SystemVerilog UVM module which can be used to
monitor the clock that is produced by a DUT (a PLL, clock divider, etc.).

The user connects this monitor to the clock to be monitored (clk_to_check)
and another clock (clk) that must always be present (generated by the 
test-bench, if required). Then the user can query the clock to find : (i) 
the frequency of the clock, (ii) whether the clock is flat, (iii) 
whether the clock is stable.

The user can also specify a minimum and maximum acceptable clock period,
and the monitor can automatically and continously check that the clock
period is respected.

## API

The class provides the following functions:

```
    function void enable_auto_clk_monitor(int min_freq_Hz, int max_freq_Hz);
```

This function makes the clock monitor continously check that the clock
has a frequency in the specified range.


```
    function void disable_clk_monitor();
````

This function disables the above check.

```
    function int clk_is_stable();
```

This function returns true, if the clock period has been stable for
NUMBER_OF_CLK_STABLE consecutive pulses, which is a parameter of the class.

```
    function logic is_clk_flat( longint flat_duration_in_ps );
```

This function returns true, if the clock has had zero transitions during
the last flat_duration_in_ps picoseconds.

```
    function longint get_clk_freq_Hz();
```

This function returns the frequency of the clock, in Hertz.

## Assertion Checks

In the interface, there are assertion which check that the clock under
test is never 'X' and that there are never any glitches (under 300ps).


## Integration guide
Following is an example of a TB which monitors two clocks, CLK_A and CLK_B

### 1. In the top ENV: Instantiate and create clock configuration class. 

```
	import clock_monitor_pkg::*;
	
	clock_monitor_config_c        clk_mon_CLK_A_cfg;
	clock_monitor_config_c        clk_mon_CLK_B_cfg;

```

#### Build phase	

```
	clk_mon_CLK_A_cfg = clock_monitor_config_c::type_id::create("clk_mon_CLK_A_cfg", this );
	clk_mon_CLK_B_cfg = clock_monitor_config_c::type_id::create("clk_mon_CLK_B_cfg", this );
```

#### En of elaboration phase	

```
	if (!clk_mon_CLK_A_cfg.randomize() with {m_clock_monitor_enable == 1; m_clock_monitor_sva_enable == 0;}) begin
		`uvm_error("End of elaboration", "Randomization failed");
	end
    
	if (!clk_mon_CLK_B_cfg.randomize() with {m_clock_monitor_enable == 1; m_clock_monitor_sva_enable == 0;}) begin
		`uvm_error("End of elaboration", "Randomization failed");
	end

```

### 2. In the TestBench Top

```
	import clock_monitor_pkg::*;
	
	bit reset;
	logic  clk;
	bit post_shutdown_phase;
	logic  rst_n;
	wire   NRESET;

	xrtl_clock_mon_vif clk_mon_CLK_A_if(.clk(clk),
		.reset_n(NRESET),
		.pll_clk_out(<hdl_path>.CLK_A));

	xrtl_clock_mon_vif clk_mon_CLK_B_if(.clk(clk),
		.reset_n(NRESET),
		.pll_clk_out(<hdl_path>.CLK_B));

	initial begin
		$timeformat(-9,0," ns", 7);
		uvm_config_db #( virtual xrtl_clock_mon_vif )::set(uvm_root::get() , "*" , "CLK_A_mon" , clk_mon_CLK_A_if);	
		uvm_config_db #( virtual xrtl_clock_mon_vif )::set(uvm_root::get() , "*" , "CLK_B_mon" , clk_mon_CLK_B_if);

		run_test();
	end  

```

### 3. In the base test

```
	class test_base extends uvm_test; 
	
		virtual xrtl_clock_mon_vif	clk_mon_CLK_A_if;
		virtual xrtl_clock_mon_vif	clk_mon_CLK_B_if;
		
		...
		
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);		

			if(!uvm_config_db#(virtual xrtl_clock_mon_vif)::get(this, "", "CLK_A_mon", clk_mon_CLK_A_if)) begin
				`uvm_error("NOVIF", {"Unable to get vif tb from configuration database for: ",
				get_full_name( ), ".clk_mon_CLK_A_if"})
			end
			if(!uvm_config_db#(virtual xrtl_clock_mon_vif)::get(this, "", "CLK_B_mon", clk_mon_CLK_B_if)) begin
				`uvm_error("NOVIF", {"Unable to get vif tb from configuration database for: ",
				get_full_name( ), ".clk_mon_CLK_B_if"})
			end
		endfunction: build_phase
		
		...
	endclass
```

## Licensing
The clock_mon is released under the Apache License, Version 2.0.
Please refer to the [LICENSE](LICENSE) file for further information.
