diff --git a/docs/library/axi_clock_monitor/index.rst b/docs/library/axi_clock_monitor/index.rst new file mode 100644 index 0000000000..4c9e0f583e --- /dev/null +++ b/docs/library/axi_clock_monitor/index.rst @@ -0,0 +1,132 @@ +.. _axi_clock_monitor: + +AXI Clock Monitor +=============================================================================== + +.. hdl-component-diagram:: + +The :git-hdl:`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 ` +* the :git-hdl:`AXI handling interface ` + +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 `. 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] diff --git a/docs/library/index.rst b/docs/library/index.rst index 95baf93bb9..23b23fd064 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -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 diff --git a/library/axi_clock_monitor/axi_clock_monitor_ip.tcl b/library/axi_clock_monitor/axi_clock_monitor_ip.tcl index 8b8ab9908f..9dab5ea28a 100755 --- a/library/axi_clock_monitor/axi_clock_monitor_ip.tcl +++ b/library/axi_clock_monitor/axi_clock_monitor_ip.tcl @@ -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 ############################################################################### @@ -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