Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs/library: Add axi_clock_monitor IP doc & Update IP GUI #1466

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions docs/library/axi_clock_monitor/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
.. _axi_clock_monitor:

AXI Clock Monitor
===============================================================================

.. hdl-component-diagram::

The :git-hdl:`AXI Clock Monitor <library/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
--------------------------------------------------------------------------------

.. list-table::
:header-rows: 1

* - Name
- Description
* - :git-hdl:`library/axi_clock_monitor/axi_clock_monitor.v`
- Verilog source for the instance
* - :git-hdl:`library/axi_clock_monitor/axi_clock_monitor_ip.tcl`
- Tcl source describing the instance for Vivado
* - :git-hdl:`library/axi_clock_monitor/axi_clock_monitor_hw.tcl`
- Tcl source describing the instance for Quartus

Configuration Parameters
--------------------------------------------------------------------------------

.. hdl-parameters::
:path: library/axi_clock_monitor

.. _axi_clock_monitor interface:

Interface
--------------------------------------------------------------------------------

.. hdl-interfaces::
:path: library/axi_clock_monitor

Detailed Description
--------------------------------------------------------------------------------

The top module instantiates:

* the :git-hdl:`clock monitor module <library/common/up_clock_mon.v>`
* the :git-hdl:`AXI handling interface <library/common/up_axi.v>`

How to instantiate it in your project:

#. build this IP by going to the :git-hdl:`library/axi_clock_monitor` folder
and running `make`. For more details on building this, check out our
:ref:`guide <build_hdl>`. Another requirement is to have your desired
project already built.
#. 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"
#. configure your IP by specifying how many clocks you want to monitor
#. connect the IP to the AXI interface
#. assign a base address to the IP core, such that it doesn't overlap with other
components
#. assign clock signals to the clock inputs
#. build again the HDL (now containing this module as well) by clicking
"Generate Bitstream" from "Program and Debug" section in Vivado

Register Map
--------------------------------------------------------------------------------

.. hdl-regmap::
:name: axi_clock_monitor
:no-type-info:

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:

.. code-block:: C
:linenos:

void clock_monitor_info (uint32_t core_base_addr, uint32_t axi_clock_speed_mhz) {
uint32_t clock_ratio = 0;
uint32_t clk1_addr = 0x40;
uint32_t n_clocks = 0;
uint32_t info_var = 0;
uint8_t n = 0;

info_var = axi_io_read(core_base_addr);
printf("PCORE_VERSION = %d\n", info_var);

info_var = axi_io_read(core_base_addr, 4);
printf("ID = %d\n", info_var);

n_clocks = axi_io_read((core_base_addr, 12));
printf("n clocks = %d\n", n_clocks);

info_var = axi_io_read(core_base_addr, 16);
printf("RESET OUT = %d\n", info_var);

while (n < n_clocks & n < 16) {
clock_ratio = axi_io_read((core_base_addr, clk1_addr + 4*n));

if (clock_ratio == 0) {
printf("Measured clock_%d: off\n", n);
} else {
printf("Measured clock_%d: %d MHz\n", n,
(clock_ratio * axi_clock_speed_mhz + 0x7fff) >> 16);
}
n++;
}
}

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]
1 change: 1 addition & 0 deletions docs/library/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Utilities
axi_adc_trigger/index
axi_adxcvr/index
axi_clkgen/index
axi_clock_monitor/index
axi_dac_interpolate/index
axi_fan_control/index
axi_laser_driver/index
Expand Down
47 changes: 27 additions & 20 deletions library/axi_clock_monitor/axi_clock_monitor_ip.tcl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
###############################################################################
## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved.
## Copyright (C) 2022-2024 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIBSD
###############################################################################

Expand All @@ -16,41 +16,48 @@ adi_ip_files axi_clock_monitor [list \

adi_ip_properties axi_clock_monitor

set_property company_url {https://wiki.analog.com/resources/fpga/docs/axi_clock_monitor} [ipx::current_core]
set cc [ipx::current_core]
set_property display_name {AXI Clock Monitor} $cc
set_property company_url {https://analogdevicesinc.github.io/hdl/library/axi_clock_monitor/index.html} $cc

set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 1} \
[ipx::get_ports *_1* -of_objects [ipx::current_core]]
[ipx::get_ports *_1* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 2} \
[ipx::get_ports *_2* -of_objects [ipx::current_core]]
[ipx::get_ports *_2* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 3} \
[ipx::get_ports *_3* -of_objects [ipx::current_core]]
[ipx::get_ports *_3* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 4} \
[ipx::get_ports *_4* -of_objects [ipx::current_core]]
[ipx::get_ports *_4* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 5} \
[ipx::get_ports *_5* -of_objects [ipx::current_core]]
[ipx::get_ports *_5* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 6} \
[ipx::get_ports *_6* -of_objects [ipx::current_core]]
[ipx::get_ports *_6* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 7} \
[ipx::get_ports *_7* -of_objects [ipx::current_core]]
[ipx::get_ports *_7* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 8 } \
[ipx::get_ports *_8* -of_objects [ipx::current_core]]
[ipx::get_ports *_8* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 9 } \
[ipx::get_ports *_9* -of_objects [ipx::current_core]]
[ipx::get_ports *_9* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 10} \
[ipx::get_ports *_10* -of_objects [ipx::current_core]]
[ipx::get_ports *_10* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 11} \
[ipx::get_ports *_11* -of_objects [ipx::current_core]]
[ipx::get_ports *_11* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 12} \
[ipx::get_ports *_12* -of_objects [ipx::current_core]]
[ipx::get_ports *_12* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 13} \
[ipx::get_ports *_13* -of_objects [ipx::current_core]]
[ipx::get_ports *_13* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 14} \
[ipx::get_ports *_14* -of_objects [ipx::current_core]]
[ipx::get_ports *_14* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 15} \
[ipx::get_ports *_15* -of_objects [ipx::current_core]]
[ipx::get_ports *_15* -of_objects $cc]

ipx::infer_bus_interface reset xilinx.com:signal:reset_rtl:1.0 [ipx::current_core]

ipx::save_core [ipx::current_core]
set_property widget {textEdit} [ipgui::get_guiparamspec -name "NUM_OF_CLOCKS" -component [ipx::current_core] ]
set_property -dict [list \
"value_validation_type" "range_long" \
"value_validation_range_minimum" "1" \
"value_validation_range_maximum" "16"
] [ipx::get_user_parameters NUM_OF_CLOCKS -of_objects $cc]

ipx::infer_bus_interface reset xilinx.com:signal:reset_rtl:1.0 $cc

ipx::save_core $cc
Loading