diff --git a/library/Makefile b/library/Makefile index 705062d0a..3d6902040 100644 --- a/library/Makefile +++ b/library/Makefile @@ -39,6 +39,7 @@ clean: $(MAKE) -C axi_adrv9001 clean $(MAKE) -C axi_adrv9009 clean $(MAKE) -C axi_clkgen clean + $(MAKE) -C axi_clock_monitor clean $(MAKE) -C axi_dac_interpolate clean $(MAKE) -C axi_dmac clean $(MAKE) -C axi_fan_control clean @@ -165,6 +166,7 @@ lib: $(MAKE) -C axi_adrv9001 $(MAKE) -C axi_adrv9009 $(MAKE) -C axi_clkgen + $(MAKE) -C axi_clock_monitor $(MAKE) -C axi_dac_interpolate $(MAKE) -C axi_dmac $(MAKE) -C axi_fan_control diff --git a/library/axi_clock_monitor/Makefile b/library/axi_clock_monitor/Makefile new file mode 100755 index 000000000..b47ee320e --- /dev/null +++ b/library/axi_clock_monitor/Makefile @@ -0,0 +1,20 @@ +#################################################################################### +## Copyright (c) 2018 - 2021 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_clock_monitor + +GENERIC_DEPS += ../common/up_axi.v +GENERIC_DEPS += axi_clock_monitor.v + +XILINX_DEPS += ../common/up_clock_mon.v +XILINX_DEPS += axi_clock_monitor_constr.xdc +XILINX_DEPS += axi_clock_monitor_ip.tcl + +INTEL_DEPS += ../intel/common/up_clock_mon_constr.sdc +INTEL_DEPS += ../intel/common/up_rst_constr.sdc +INTEL_DEPS += axi_clock_monitor_hw.tcl + +include ../scripts/library.mk diff --git a/library/axi_clock_monitor/README.md b/library/axi_clock_monitor/README.md new file mode 100644 index 000000000..f1989aa03 --- /dev/null +++ b/library/axi_clock_monitor/README.md @@ -0,0 +1 @@ +https://wiki.analog.com/resources/fpga/docs/axi_clock_monitor \ No newline at end of file diff --git a/library/axi_clock_monitor/axi_clock_monitor.v b/library/axi_clock_monitor/axi_clock_monitor.v new file mode 100755 index 000000000..dc5bbbe91 --- /dev/null +++ b/library/axi_clock_monitor/axi_clock_monitor.v @@ -0,0 +1,271 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2022 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module axi_clock_monitor #( + + parameter ID = 0, + parameter NUM_OF_CLOCKS = 1) ( + + // clocks + + input clock_0, + input clock_1, + input clock_2, + input clock_3, + input clock_4, + input clock_5, + input clock_6, + input clock_7, + input clock_8, + input clock_9, + input clock_10, + input clock_11, + input clock_12, + input clock_13, + input clock_14, + input clock_15, + + output reset, + + // axi interface + + input s_axi_aclk, + input s_axi_aresetn, + input s_axi_awvalid, + input [15:0] s_axi_awaddr, + input [ 2:0] s_axi_awprot, + output s_axi_awready, + input s_axi_wvalid, + input [31:0] s_axi_wdata, + input [ 3:0] s_axi_wstrb, + output s_axi_wready, + output s_axi_bvalid, + output [ 1:0] s_axi_bresp, + input s_axi_bready, + input s_axi_arvalid, + input [15:0] s_axi_araddr, + input [ 2:0] s_axi_arprot, + output s_axi_arready, + output s_axi_rvalid, + output [31:0] s_axi_rdata, + output [ 1:0] s_axi_rresp, + input s_axi_rready); + + // local parameters + + localparam PCORE_VERSION = 1 + + // internal registers + + reg pass = 'd0; + reg up_wack_int = 'd0; + reg up_rack_int = 'd0; + reg up_scratch = 'd0; + reg up_reset_core = 'd0; + reg [31:0] up_rdata_int = 'd0; + + // internal signals + + wire up_clk; + wire up_rstn; + wire up_wreq_s; + wire up_rreq_s; + wire up_waddr_s; + wire up_raddr_s; + + wire clock [0:15]; + wire [20:0] clk_mon_count [0:15]; + + wire up_wreq_i_s; + wire [(PROC_ADDR_WD-1):0] up_waddr_i_s; + wire [31:0] up_wdata_i_s; + wire up_wack_o_s; + wire up_rreq_i_s; + wire [(PROC_ADDR_WD-1):0] up_raddr_i_s; + wire [31:0] up_rdata_o_s; + wire up_rack_o_s; + + // loop variables + + genvar n; + + generate + assign clock[0 ] = clock_0; + assign clock[1 ] = clock_1; + assign clock[2 ] = clock_2; + assign clock[3 ] = clock_3; + assign clock[4 ] = clock_4; + assign clock[5 ] = clock_5; + assign clock[6 ] = clock_6; + assign clock[7 ] = clock_7; + assign clock[8 ] = clock_8; + assign clock[9 ] = clock_9; + assign clock[10] = clock_10; + assign clock[11] = clock_11; + assign clock[12] = clock_12; + assign clock[13] = clock_13; + assign clock[14] = clock_14; + assign clock[15] = clock_15; + endgenerate + + assign up_clk = s_axi_aclk; + assign up_rstn = s_axi_aresetn; + assign reset = up_reset_core; + + // decode block select + + assign up_wreq_s = (up_waddr_i_s[13:8] == ID) ? up_wreq_i_s : 1'b0; + assign up_rreq_s = (up_raddr_i_s[13:8] == ID) ? up_rreq_i_s : 1'b0; + + // processor write interface + + assign up_wack_o_s = up_wack_int; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_wack_int <= 'd0; + up_reset_core <= 'd0; + end else begin + up_wack_int <= up_wreq_s; + if (up_wreq_s == 1'b1) begin + case (up_waddr_i_s[7:0]) + 8'h004: up_reset_core <= up_wdata_i_s[0]; + default: pass <= 1'h0; + endcase + end + end + end + + // processor read interface + + assign up_rack_o_s = up_rack_int; + assign up_rdata_o_s = up_rdata_int; + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rack_int <= 'd0; + up_rdata_int <= 'd0; + end else begin + up_rack_int <= up_rreq_s; + if (up_rreq_s == 1'b1) begin + case (up_raddr_i_s) + /* Standard registers */ + 12'h000: up_rdata_int <= PCORE_VERSION; + 12'h001: up_rdata_int <= ID; + + /* Core configuration */ + 12'h003: up_rdata_int <= NUM_OF_CLOCKS; + 12'h004: up_rdata_int <= up_reset_core; + + /* Clock ratios registers*/ + 12'h010: up_rdata_int <= {11'h00, clk_mon_count[ 0]}; /* Make it 16.16 */ + 12'h011: up_rdata_int <= {11'h00, clk_mon_count[ 1]}; /* Make it 16.16 */ + 12'h012: up_rdata_int <= {11'h00, clk_mon_count[ 2]}; /* Make it 16.16 */ + 12'h013: up_rdata_int <= {11'h00, clk_mon_count[ 3]}; /* Make it 16.16 */ + 12'h014: up_rdata_int <= {11'h00, clk_mon_count[ 4]}; /* Make it 16.16 */ + 12'h015: up_rdata_int <= {11'h00, clk_mon_count[ 5]}; /* Make it 16.16 */ + 12'h016: up_rdata_int <= {11'h00, clk_mon_count[ 6]}; /* Make it 16.16 */ + 12'h017: up_rdata_int <= {11'h00, clk_mon_count[ 7]}; /* Make it 16.16 */ + 12'h018: up_rdata_int <= {11'h00, clk_mon_count[ 8]}; /* Make it 16.16 */ + 12'h019: up_rdata_int <= {11'h00, clk_mon_count[ 9]}; /* Make it 16.16 */ + 12'h01a: up_rdata_int <= {11'h00, clk_mon_count[10]}; /* Make it 16.16 */ + 12'h01b: up_rdata_int <= {11'h00, clk_mon_count[11]}; /* Make it 16.16 */ + 12'h01c: up_rdata_int <= {11'h00, clk_mon_count[12]}; /* Make it 16.16 */ + 12'h01d: up_rdata_int <= {11'h00, clk_mon_count[13]}; /* Make it 16.16 */ + 12'h01e: up_rdata_int <= {11'h00, clk_mon_count[14]}; /* Make it 16.16 */ + 12'h01f: up_rdata_int <= {11'h00, clk_mon_count[15]}; /* Make it 16.16 */ + + default: up_rdata_int <= 'h00; + endcase + end + end + end + + // clock monitors + + generate + for (n = 0; n < NUM_OF_CLOCKS; n = n + 1) begin: clk_mon + up_clock_mon #( + .TOTAL_WIDTH(21) + ) i_clock_mon ( + .up_rstn(~up_reset_core), + .up_clk(up_clk), + .up_d_count(clk_mon_count[n]), + .d_rst(1'b0), + .d_clk(clock[n]) + ); + end + for (n = NUM_OF_CLOCKS; n < 16; n = n + 1) begin: clk_mon_z + assign clk_mon_count[n] = 20'd0; + end + endgenerate + + // axi interface + + up_axi i_up_axi ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_axi_awvalid (s_axi_awvalid), + .up_axi_awaddr (s_axi_awaddr), + .up_axi_awready (s_axi_awready), + .up_axi_wvalid (s_axi_wvalid), + .up_axi_wdata (s_axi_wdata), + .up_axi_wstrb (s_axi_wstrb), + .up_axi_wready (s_axi_wready), + .up_axi_bvalid (s_axi_bvalid), + .up_axi_bresp (s_axi_bresp), + .up_axi_bready (s_axi_bready), + .up_axi_arvalid (s_axi_arvalid), + .up_axi_araddr (s_axi_araddr), + .up_axi_arready (s_axi_arready), + .up_axi_rvalid (s_axi_rvalid), + .up_axi_rresp (s_axi_rresp), + .up_axi_rdata (s_axi_rdata), + .up_axi_rready (s_axi_rready), + .up_wreq (up_wreq_i_s), + .up_waddr (up_waddr_i_s), + .up_wdata (up_wdata_i_s), + .up_wack (up_wack_o_s), + .up_rreq (up_rreq_i_s), + .up_raddr (up_raddr_i_s), + .up_rdata (up_rdata_o_s), + .up_rack (up_rack_o_s)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/library/axi_clock_monitor/axi_clock_monitor_hw.tcl b/library/axi_clock_monitor/axi_clock_monitor_hw.tcl new file mode 100755 index 000000000..ed726e3c0 --- /dev/null +++ b/library/axi_clock_monitor/axi_clock_monitor_hw.tcl @@ -0,0 +1,41 @@ + + +package require qsys + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_intel.tcl + +ad_ip_create axi_clock_monitor {axi_clock_monitor} p_axi_clock_monitor + +# files +set_module_property NAME axi_clock_monitor + +ad_ip_files axi_clock_monitor [list \ + $ad_hdl_dir/library/common/up_axi.v \ + $ad_hdl_dir/library/intel/common/up_clock_mon_constr.sdc \ + $ad_hdl_dir/library/intel/common/up_rst_constr.sdc \ + axi_clock_monitor.v \ +] + +# parameters + +add_parameter NUM_OF_CLOCKS INTEGER 0 +set_parameter_property NUM_OF_CLOCKS DEFAULT_VALUE 8 +set_parameter_property NUM_OF_CLOCKS DISPLAY_NAME NUM_OF_CLOCKS +set_parameter_property NUM_OF_CLOCKS UNITS None +set_parameter_property NUM_OF_CLOCKS HDL_PARAMETER true + +# interfaces + +ad_ip_intf_s_axi s_axi_aclk s_axi_aresetn + +ad_interface reset output 1 if_reset + +proc p_axi_clock_monitor {} { + set num_of_clock [get_parameter_value NUM_OF_CLOCKS] + + for {set n 0} {$n < $num_of_clock} {incr n} { + ad_interface clock clock_${n} input 1 + } +} + diff --git a/library/axi_clock_monitor/axi_clock_monitor_ip.tcl b/library/axi_clock_monitor/axi_clock_monitor_ip.tcl new file mode 100755 index 000000000..d1a2c498b --- /dev/null +++ b/library/axi_clock_monitor/axi_clock_monitor_ip.tcl @@ -0,0 +1,52 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl + +adi_ip_create axi_clock_monitor +adi_ip_files axi_clock_monitor [list \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/common/up_clock_mon.v" \ + "axi_clock_monitor.v" \ + "axi_clock_monitor_constr.xdc" ] + +adi_ip_properties axi_clock_monitor + +set_property company_url {https://wiki.analog.com/resources/fpga/docs/axi_clock_monitor} [ipx::current_core] + +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 1} \ + [ipx::get_ports *_1* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 2} \ + [ipx::get_ports *_2* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 3} \ + [ipx::get_ports *_3* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 4} \ + [ipx::get_ports *_4* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 5} \ + [ipx::get_ports *_5* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 6} \ + [ipx::get_ports *_6* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 7} \ + [ipx::get_ports *_7* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 8 } \ + [ipx::get_ports *_8* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 9 } \ + [ipx::get_ports *_9* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 10} \ + [ipx::get_ports *_10* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 11} \ + [ipx::get_ports *_11* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 12} \ + [ipx::get_ports *_12* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 13} \ + [ipx::get_ports *_13* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 14} \ + [ipx::get_ports *_14* -of_objects [ipx::current_core]] +set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CLOCKS')) > 15} \ + [ipx::get_ports *_15* -of_objects [ipx::current_core]] + +ipx::infer_bus_interface reset xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] + +ipx::save_core [ipx::current_core] + +