AXI Clock Monitor

s_axis_axi_aclks_axi_aresetnclock_*resetaxi_clock_monitor

The AXI Clock Monitor IP is used to measure clocks in the system. It allows up to 16 clocks to be measured at a time.

Features

  • Can measure up to 16 clocks (set to 1 by default)

  • AXI-based configuration

  • Vivado and Quartus compatible

Files

Name

Description

library/axi_clock_monitor/axi_clock_monitor.v

Verilog source for the instance

library/axi_clock_monitor/axi_clock_monitor_ip.tcl

Tcl source describing the instance for Vivado

library/axi_clock_monitor/axi_clock_monitor_hw.tcl

Tcl source describing the instance for Quartus

Configuration Parameters

Name

Description

Default Value

Choices/Range

ID

Id.

0

NUM_OF_CLOCKS

Num Of Clocks.

1

From 1 to 16.

Interface

Physical Port

Logical Port

Direction

Dependency

s_axi_awaddr AWADDR

in [15:0]

s_axi_awprot AWPROT

in [2:0]

s_axi_awvalid AWVALID

in

s_axi_awready AWREADY

out

s_axi_wdata WDATA

in [31:0]

s_axi_wstrb WSTRB

in [3:0]

s_axi_wvalid WVALID

in

s_axi_wready WREADY

out

s_axi_bresp BRESP

out [1:0]

s_axi_bvalid BVALID

out

s_axi_bready BREADY

in

s_axi_araddr ARADDR

in [15:0]

s_axi_arprot ARPROT

in [2:0]

s_axi_arvalid ARVALID

in

s_axi_arready ARREADY

out

s_axi_rdata RDATA

out [31:0]

s_axi_rresp RRESP

out [1:0]

s_axi_rvalid RVALID

out

s_axi_rready RREADY

in

Physical Port

Logical Port

Direction

Dependency

s_axi_aclk CLK

in

Physical Port

Logical Port

Direction

Dependency

s_axi_aresetn RST

in

Physical Port

Logical Port

Direction

Dependency

reset RST

out

Physical Port

Direction

Dependency

Description

clock_*

in

Detailed Description

The top module instantiates:

How to instantiate it in your project:

  1. build this IP by going to the library/axi_clock_monitor folder and running make. For more details on building this, check out our guide. Another requirement is to have your desired project already built.

  2. import the IP core to your block design, by opening the Block Design of the already built project, right-clicking in the Diagram then “Add IP” (or CTRL + I) and typing “axi_clock_monitor”

  3. configure your IP by specifying how many clocks you want to monitor

  4. connect the IP to the AXI interface

  5. assign a base address to the IP core, such that it doesn’t overlap with other components

  6. assign clock signals to the clock inputs

  7. build again the HDL (now containing this module as well) by clicking “Generate Bitstream” from “Program and Debug” section in Vivado

Register Map

DWORD

BYTE

Reg Name

Description

BITS

Field Name

Type

Default Value

Description

0x0 0x0 PCORE_VERSION

PCORE Version Registers

[31:0] PCORE_VERSION RO 0x00000001

PCORE Version number

0x1 0x4 ID

ID Registers

[31:0] ID RW 0x00000000

Instance identifier number

0x3 0xc NUM_OF_CLOCKS

Number of Clocks Registers

[31:0] NUM_OF_CLOCKS RW 0x00000008

Number of clock inputs

0x4 0x10 OUT_RESET

Reset Control Registers

[0] RESET RW 0x0

Control the out reset signal

0x10 + 0x1*n 0x40 + 0x4*n CLOCK_n

Measured clock_n Where n is from 0 to 15.

[31:0] CLOCK_n RO 0x00000000

Measured frequency of clock_n

Software Guidelines

Note

Only no-OS software is supported.

We use software to access the core’s registers to get the data from the IP.

The following example contains a simple function that reads all the info from the IP and prints it on the serial terminal:

 1void clock_monitor_info (uint32_t core_base_addr, uint32_t axi_clock_speed_mhz) {
 2   uint32_t clock_ratio = 0;
 3   uint32_t clk1_addr = 0x40;
 4   uint32_t n_clocks = 0;
 5   uint32_t info_var = 0;
 6   uint8_t n = 0;
 7
 8   info_var = axi_io_read(core_base_addr);
 9   printf("PCORE_VERSION = %d\n", info_var);
10
11   info_var = axi_io_read(core_base_addr, 4);
12   printf("ID = %d\n", info_var);
13
14   n_clocks = axi_io_read((core_base_addr, 12));
15   printf("n clocks = %d\n", n_clocks);
16
17   info_var = axi_io_read(core_base_addr, 16);
18   printf("RESET OUT = %d\n", info_var);
19
20   while (n < n_clocks & n < 16) {
21      clock_ratio = axi_io_read((core_base_addr, clk1_addr + 4*n));
22
23      if (clock_ratio == 0) {
24         printf("Measured clock_%d: off\n", n);
25      } else {
26         printf("Measured clock_%d: %d MHz\n", n,
27            (clock_ratio * axi_clock_speed_mhz + 0x7fff) >> 16);
28      }
29      n++;
30   }
31}

To call the function, consider the following parameters:

  • core_base_addr will take the value of the base address set at step 5 of the HDL instantiation

  • axi_clock_speed_mhz will be the reference frequency. In most cases, we assume this parameter to be 100 [MHz]