From 64f6762a05521dd0ac174fb9bd7a89ea38f2b046 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Tue, 2 Jun 2020 07:27:27 +0100 Subject: [PATCH] library:axi_adrv9001: Initial version ADRV9001 interfacing IP supports the following modes on Xilinx devices: A B C D E F G H CSSI__1-lane 1 32 80 80 2.5 SDR 8 CSSI__1-lane 1 32 160 80 5 DDR 4 CSSI__4-lane 4 8 80 80 10 SDR 2 CSSI__4-lane 4 8 160 80 20 DDR 1 LSSI__1-lane 1 32 983.04 491.52 30.72 DDR 4 LSSI__2-lane 2 16 983.04 491.52 61.44 DDR 2 Columns description: A - SSI Modes B - Data Lanes Per Channel C - Serialization factor Per data lane D - Max data lane rate(MHz) E - Max Clock rate (MHz) F - Max Sample Rate for I/Q (MHz) G - Data Type H - DDS Rate CSSI - CMOS Source Synchronous Interface LSSI - LVDS Source Synchronous Interface Intel devices supports only CSSI modes. --- library/Makefile | 2 + library/axi_adrv9001/Makefile | 66 +++ library/axi_adrv9001/adrv9001_aligner4.v | 82 +++ library/axi_adrv9001/adrv9001_aligner8.v | 90 +++ library/axi_adrv9001/adrv9001_pack.v | 86 +++ library/axi_adrv9001/adrv9001_rx.v | 270 +++++++++ library/axi_adrv9001/adrv9001_rx_link.v | 325 +++++++++++ library/axi_adrv9001/adrv9001_tx.v | 238 ++++++++ library/axi_adrv9001/adrv9001_tx_link.v | 198 +++++++ library/axi_adrv9001/axi_adrv9001.v | 522 ++++++++++++++++++ library/axi_adrv9001/axi_adrv9001_constr.sdc | 6 + library/axi_adrv9001/axi_adrv9001_constr.xdc | 5 + library/axi_adrv9001/axi_adrv9001_core.v | 501 +++++++++++++++++ library/axi_adrv9001/axi_adrv9001_hw.tcl | 225 ++++++++ library/axi_adrv9001/axi_adrv9001_if.v | 438 +++++++++++++++ library/axi_adrv9001/axi_adrv9001_ip.tcl | 80 +++ library/axi_adrv9001/axi_adrv9001_rx.v | 372 +++++++++++++ .../axi_adrv9001/axi_adrv9001_rx_channel.v | 324 +++++++++++ library/axi_adrv9001/axi_adrv9001_tx.v | 381 +++++++++++++ .../axi_adrv9001/axi_adrv9001_tx_channel.v | 251 +++++++++ library/axi_adrv9001/intel/adrv9001_rx.v | 150 +++++ library/axi_adrv9001/intel/adrv9001_tx.v | 135 +++++ 22 files changed, 4747 insertions(+) create mode 100644 library/axi_adrv9001/Makefile create mode 100644 library/axi_adrv9001/adrv9001_aligner4.v create mode 100644 library/axi_adrv9001/adrv9001_aligner8.v create mode 100644 library/axi_adrv9001/adrv9001_pack.v create mode 100644 library/axi_adrv9001/adrv9001_rx.v create mode 100644 library/axi_adrv9001/adrv9001_rx_link.v create mode 100644 library/axi_adrv9001/adrv9001_tx.v create mode 100644 library/axi_adrv9001/adrv9001_tx_link.v create mode 100644 library/axi_adrv9001/axi_adrv9001.v create mode 100644 library/axi_adrv9001/axi_adrv9001_constr.sdc create mode 100644 library/axi_adrv9001/axi_adrv9001_constr.xdc create mode 100644 library/axi_adrv9001/axi_adrv9001_core.v create mode 100644 library/axi_adrv9001/axi_adrv9001_hw.tcl create mode 100644 library/axi_adrv9001/axi_adrv9001_if.v create mode 100644 library/axi_adrv9001/axi_adrv9001_ip.tcl create mode 100644 library/axi_adrv9001/axi_adrv9001_rx.v create mode 100644 library/axi_adrv9001/axi_adrv9001_rx_channel.v create mode 100644 library/axi_adrv9001/axi_adrv9001_tx.v create mode 100644 library/axi_adrv9001/axi_adrv9001_tx_channel.v create mode 100644 library/axi_adrv9001/intel/adrv9001_rx.v create mode 100644 library/axi_adrv9001/intel/adrv9001_tx.v diff --git a/library/Makefile b/library/Makefile index e174ee10e..7126404fe 100644 --- a/library/Makefile +++ b/library/Makefile @@ -33,6 +33,7 @@ clean: $(MAKE) -C axi_ad9963 clean $(MAKE) -C axi_adc_decimate clean $(MAKE) -C axi_adc_trigger clean + $(MAKE) -C axi_adrv9001 clean $(MAKE) -C axi_adrv9009 clean $(MAKE) -C axi_clkgen clean $(MAKE) -C axi_dac_interpolate clean @@ -146,6 +147,7 @@ lib: $(MAKE) -C axi_ad9963 $(MAKE) -C axi_adc_decimate $(MAKE) -C axi_adc_trigger + $(MAKE) -C axi_adrv9001 $(MAKE) -C axi_adrv9009 $(MAKE) -C axi_clkgen $(MAKE) -C axi_dac_interpolate diff --git a/library/axi_adrv9001/Makefile b/library/axi_adrv9001/Makefile new file mode 100644 index 000000000..d83638d25 --- /dev/null +++ b/library/axi_adrv9001/Makefile @@ -0,0 +1,66 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_adrv9001 + +GENERIC_DEPS += adrv9001_rx.v +GENERIC_DEPS += adrv9001_rx_link.v +GENERIC_DEPS += adrv9001_tx.v +GENERIC_DEPS += adrv9001_tx_link.v +GENERIC_DEPS += adrv9001_aligner4.v +GENERIC_DEPS += adrv9001_aligner8.v +GENERIC_DEPS += axi_adrv9001.v +GENERIC_DEPS += axi_adrv9001_core.v +GENERIC_DEPS += axi_adrv9001_if.v +GENERIC_DEPS += axi_adrv9001_rx.v +GENERIC_DEPS += axi_adrv9001_rx_channel.v +GENERIC_DEPS += axi_adrv9001_tx.v +GENERIC_DEPS += axi_adrv9001_tx_channel.v +GENERIC_DEPS += adrv9001_pack.v + +XILINX_DEPS += ../common/ad_datafmt.v +XILINX_DEPS += ../common/ad_dds.v +XILINX_DEPS += ../common/ad_dds_1.v +XILINX_DEPS += ../common/ad_dds_2.v +XILINX_DEPS += ../common/ad_dds_cordic_pipe.v +XILINX_DEPS += ../common/ad_dds_sine.v +XILINX_DEPS += ../common/ad_dds_sine_cordic.v +XILINX_DEPS += ../common/ad_pngen.v +XILINX_DEPS += ../common/ad_pnmon.v +XILINX_DEPS += ../common/ad_rst.v +XILINX_DEPS += ../common/up_adc_channel.v +XILINX_DEPS += ../common/up_adc_common.v +XILINX_DEPS += ../common/up_axi.v +XILINX_DEPS += ../common/up_clock_mon.v +XILINX_DEPS += ../common/up_dac_channel.v +XILINX_DEPS += ../common/up_dac_common.v +XILINX_DEPS += ../common/up_delay_cntrl.v +XILINX_DEPS += ../common/up_xfer_cntrl.v +XILINX_DEPS += ../common/up_xfer_status.v +XILINX_DEPS += ../xilinx/common/ad_mmcm_drp.v +XILINX_DEPS += ../xilinx/common/ad_mul.v +XILINX_DEPS += ../xilinx/common/ad_rst_constr.xdc +XILINX_DEPS += ../xilinx/common/ad_serdes_clk.v +XILINX_DEPS += ../xilinx/common/ad_serdes_in.v +XILINX_DEPS += ../xilinx/common/ad_serdes_out.v +XILINX_DEPS += ../xilinx/common/up_clock_mon_constr.xdc +XILINX_DEPS += ../xilinx/common/up_xfer_cntrl_constr.xdc +XILINX_DEPS += ../xilinx/common/up_xfer_status_constr.xdc +XILINX_DEPS += axi_adrv9001_constr.xdc +XILINX_DEPS += axi_adrv9001_ip.tcl + +XILINX_LIB_DEPS += util_cdc + +INTEL_DEPS += ../intel/common/ad_mul.v +INTEL_DEPS += ../intel/common/up_clock_mon_constr.sdc +INTEL_DEPS += ../intel/common/up_rst_constr.sdc +INTEL_DEPS += ../intel/common/up_xfer_cntrl_constr.sdc +INTEL_DEPS += ../intel/common/up_xfer_status_constr.sdc +INTEL_DEPS += intel/adrv9001_rx.v +INTEL_DEPS += intel/adrv9001_tx.v +INTEL_DEPS += axi_adrv9001_constr.sdc +INTEL_DEPS += axi_adrv9001_hw.tcl + +include ../scripts/library.mk diff --git a/library/axi_adrv9001/adrv9001_aligner4.v b/library/axi_adrv9001/adrv9001_aligner4.v new file mode 100644 index 000000000..33b4cc158 --- /dev/null +++ b/library/axi_adrv9001/adrv9001_aligner4.v @@ -0,0 +1,82 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_aligner4 ( + input clk, + input [3:0] idata, + input ivalid, + input [3:0] strobe, + output reg [3:0] odata, + output ovalid +); + + reg [3:0] idata_d = 'b0; + reg ivalid_d = 'b0; + + always @(posedge clk) begin + if (ivalid) begin + idata_d <= idata; + end + ivalid_d <= ivalid; + end + + reg [1:0] phase = 'h0; + always @(posedge clk) begin + if (ivalid) begin + if ((strobe != 'b1111) && (strobe != 'b0000)) begin + casex (strobe) + 'b1xxx : phase <= 0; + 'b01xx : phase <= 1; + 'b001x : phase <= 2; + 'b0001 : phase <= 3; + default : phase <= phase; + endcase + end + end + end + + always @(posedge clk) begin + case (phase) + 0 : odata <= idata_d; + 1 : odata <= {idata_d[2:0],idata[3:3]}; + 2 : odata <= {idata_d[1:0],idata[3:2]}; + 3 : odata <= {idata_d[0:0],idata[3:1]}; + endcase + end + assign ovalid = ivalid_d; + +endmodule diff --git a/library/axi_adrv9001/adrv9001_aligner8.v b/library/axi_adrv9001/adrv9001_aligner8.v new file mode 100644 index 000000000..43a90c889 --- /dev/null +++ b/library/axi_adrv9001/adrv9001_aligner8.v @@ -0,0 +1,90 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_aligner8 ( + input clk, + input [7:0] idata, + input ivalid, + input [7:0] strobe, + output reg [7:0] odata, + output ovalid +); + + reg [7:0] idata_d = 'b0; + reg ivalid_d = 'b0; + + always @(posedge clk) begin + if (ivalid) begin + idata_d <= idata; + end + ivalid_d <= ivalid; + end + + reg [2:0] phase = 'h0; + always @(posedge clk) begin + if (ivalid) begin + if ((strobe != 'b1111_1111) && (strobe != 'b0000_0000)) begin + casex (strobe) + 'b1xxx_xxxx : phase <= 0; + 'b01xx_xxxx : phase <= 1; + 'b001x_xxxx : phase <= 2; + 'b0001_xxxx : phase <= 3; + 'b0000_1xxx : phase <= 4; + 'b0000_01xx : phase <= 5; + 'b0000_001x : phase <= 6; + 'b0000_0001 : phase <= 7; + default : phase <= phase; + endcase + end + end + end + + always @(posedge clk) begin + case (phase) + 0 : odata <= idata_d; + 1 : odata <= {idata_d[6:0],idata[7:7]}; + 2 : odata <= {idata_d[5:0],idata[7:6]}; + 3 : odata <= {idata_d[4:0],idata[7:5]}; + 4 : odata <= {idata_d[3:0],idata[7:4]}; + 5 : odata <= {idata_d[2:0],idata[7:3]}; + 6 : odata <= {idata_d[1:0],idata[7:2]}; + 7 : odata <= {idata_d[0:0],idata[7:1]}; + endcase + end + assign ovalid = ivalid_d; + +endmodule diff --git a/library/axi_adrv9001/adrv9001_pack.v b/library/axi_adrv9001/adrv9001_pack.v new file mode 100644 index 000000000..f038f906d --- /dev/null +++ b/library/axi_adrv9001/adrv9001_pack.v @@ -0,0 +1,86 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 + +// +// Pack two input beats into one and align it based on start of frame +// +// Frame size 2 beats: +// Temporal ordering of input: +// idata : MS Beat, LS Beat, MS Beat, LS Beat, ... +// sof : 1, 0, 1, 0, ... +// Format of output beats: {MS Beat, LS Beat} +// +// Frame size 4 beats: +// Temporal ordering of input: +// idata : MS Beat, LS Beat, MS Beat, LS Beat, MS Beat, LS Beat, ... +// sof : 1, 0, 0, 0, 1, 0, ... + +module adrv9001_pack #( + parameter WIDTH = 8 +)( + input clk, // Input clock + input sof, // Start of frame indicator marking the MS Beat + input [WIDTH-1:0] idata, // Input data beat + input ivalid, // Input data qualifier + output reg [WIDTH*2-1:0] odata, // Output data beat + output reg ovalid, // Output data qualifier + output reg osof // Output Start of frame indicator +); + + reg [WIDTH-1:0] idata_d = {WIDTH{1'b0}}; + always @(posedge clk) begin + if (ivalid) begin + idata_d <= idata; + end + end + + // Single clock mode: + reg [6:0] sof_d = 7'b000; + // Use sof_d[2] for frame size of 4 beats + // Use sof_d[4,6] for frame size of 8 beats + always @(posedge clk) begin + if (ivalid) begin + sof_d <= {sof_d[5:0],sof}; + end + if (ivalid &(sof_d[0] | sof_d[2] | sof_d[4] | sof_d[6])) begin + odata <= {idata_d,idata}; + end + ovalid <= ivalid & (sof_d[0] | sof_d[2] | sof_d[4] | sof_d[6]); + osof <= ivalid & sof_d[0]; + end + +endmodule diff --git a/library/axi_adrv9001/adrv9001_rx.v b/library/axi_adrv9001/adrv9001_rx.v new file mode 100644 index 000000000..0174ab6b1 --- /dev/null +++ b/library/axi_adrv9001/adrv9001_rx.v @@ -0,0 +1,270 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_rx #( + parameter CMOS_LVDS_N = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter NUM_LANES = 3, + parameter DRP_WIDTH = 5, + parameter IODELAY_CTRL = 0, + parameter IO_DELAY_GROUP = "dev_if_delay_group" +) ( + // device interface + input rx_dclk_in_n_NC, + input rx_dclk_in_p_dclk_in, + input rx_idata_in_n_idata0, + input rx_idata_in_p_idata1, + input rx_qdata_in_n_qdata2, + input rx_qdata_in_p_qdata3, + input rx_strobe_in_n_NC, + input rx_strobe_in_p_strobe_in, + + // internal reset and clocks + input adc_rst, + output adc_clk, + output adc_clk_div, + output [7:0] adc_data_0, + output [7:0] adc_data_1, + output [7:0] adc_data_2, + output [7:0] adc_data_3, + output [7:0] adc_data_strobe, + output adc_valid, + + // delay interface (for IDELAY macros) + input up_clk, + input [NUM_LANES-1:0] up_adc_dld, + input [DRP_WIDTH*NUM_LANES-1:0] up_adc_dwdata, + output [DRP_WIDTH*NUM_LANES-1:0] up_adc_drdata, + input delay_clk, + input delay_rst, + output delay_locked, + + input mssi_sync, + output ssi_sync_out, + input ssi_sync_in, + output ssi_rst +); + + // Use always DDR mode + localparam DDR_OR_SDR_N = 1; + + localparam SEVEN_SERIES = 1; + localparam ULTRASCALE = 2; + localparam ULTRASCALE_PLUS = 3; + + // internal wire + wire clk_in_s; + wire [NUM_LANES-1:0] serdes_in_p; + wire [NUM_LANES-1:0] serdes_in_n; + wire [NUM_LANES-1:0] data_s0; + wire [NUM_LANES-1:0] data_s1; + wire [NUM_LANES-1:0] data_s2; + wire [NUM_LANES-1:0] data_s3; + wire [NUM_LANES-1:0] data_s4; + wire [NUM_LANES-1:0] data_s5; + wire [NUM_LANES-1:0] data_s6; + wire [NUM_LANES-1:0] data_s7; + wire adc_clk_in_fast; + + // internal registers + + // data interface + ad_serdes_in #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .IODELAY_CTRL (IODELAY_CTRL), + .IODELAY_GROUP (IO_DELAY_GROUP), + .DDR_OR_SDR_N (DDR_OR_SDR_N), + .DATA_WIDTH (NUM_LANES), + .DRP_WIDTH (DRP_WIDTH), + .SERDES_FACTOR (8)) + i_serdes ( + .rst (adc_rst|ssi_rst), + .clk (adc_clk_in_fast), + .div_clk (adc_clk_div), + .loaden (1'b0), + .phase (8'b0), + .locked (1'b0), + .data_s0 (data_s0), + .data_s1 (data_s1), + .data_s2 (data_s2), + .data_s3 (data_s3), + .data_s4 (data_s4), + .data_s5 (data_s5), + .data_s6 (data_s6), + .data_s7 (data_s7), + .data_in_p (serdes_in_p), + .data_in_n (serdes_in_n), + .up_clk (up_clk), + .up_dld (up_adc_dld), + .up_dwdata (up_adc_dwdata), + .up_drdata (up_adc_drdata), + .delay_clk (delay_clk), + .delay_rst (delay_rst), + .delay_locked (delay_locked)); + + generate + if (CMOS_LVDS_N == 0) begin + + IBUFGDS i_clk_in_ibuf ( + .I (rx_dclk_in_p_dclk_in), + .IB (rx_dclk_in_n_NC), + .O (clk_in_s)); + + assign {adc_data_strobe[0],adc_data_1[0],adc_data_0[0]} = data_s0; + assign {adc_data_strobe[1],adc_data_1[1],adc_data_0[1]} = data_s1; + assign {adc_data_strobe[2],adc_data_1[2],adc_data_0[2]} = data_s2; + assign {adc_data_strobe[3],adc_data_1[3],adc_data_0[3]} = data_s3; + assign {adc_data_strobe[4],adc_data_1[4],adc_data_0[4]} = data_s4; + assign {adc_data_strobe[5],adc_data_1[5],adc_data_0[5]} = data_s5; + assign {adc_data_strobe[6],adc_data_1[6],adc_data_0[6]} = data_s6; + assign {adc_data_strobe[7],adc_data_1[7],adc_data_0[7]} = data_s7; + + assign serdes_in_p = {rx_strobe_in_p_strobe_in, + rx_qdata_in_p_qdata3, + rx_idata_in_p_idata1}; + assign serdes_in_n = {rx_strobe_in_n_NC, + rx_qdata_in_n_qdata2, + rx_idata_in_n_idata0}; + + end else begin + + IBUF i_clk_in_ibuf ( + .I (rx_dclk_in_p_dclk_in), + .O (clk_in_s)); + + assign {adc_data_strobe[0],adc_data_3[0],adc_data_2[0],adc_data_1[0],adc_data_0[0]} = data_s0; + assign {adc_data_strobe[1],adc_data_3[1],adc_data_2[1],adc_data_1[1],adc_data_0[1]} = data_s1; + assign {adc_data_strobe[2],adc_data_3[2],adc_data_2[2],adc_data_1[2],adc_data_0[2]} = data_s2; + assign {adc_data_strobe[3],adc_data_3[3],adc_data_2[3],adc_data_1[3],adc_data_0[3]} = data_s3; + assign {adc_data_strobe[4],adc_data_3[4],adc_data_2[4],adc_data_1[4],adc_data_0[4]} = data_s4; + assign {adc_data_strobe[5],adc_data_3[5],adc_data_2[5],adc_data_1[5],adc_data_0[5]} = data_s5; + assign {adc_data_strobe[6],adc_data_3[6],adc_data_2[6],adc_data_1[6],adc_data_0[6]} = data_s6; + assign {adc_data_strobe[7],adc_data_3[7],adc_data_2[7],adc_data_1[7],adc_data_0[7]} = data_s7; + + assign serdes_in_p = {rx_strobe_in_p_strobe_in, + rx_qdata_in_p_qdata3, + rx_qdata_in_n_qdata2, + rx_idata_in_p_idata1, + rx_idata_in_n_idata0}; + assign serdes_in_n = 5'b0; + + end + endgenerate + + generate + if (FPGA_TECHNOLOGY == SEVEN_SERIES) begin + + BUFIO i_clk_buf ( + .I (clk_in_s), + .O (adc_clk_in_fast)); + + BUFR #(.BUFR_DIVIDE("4")) i_div_clk_buf ( + .CLR (mssi_sync), + .CE (1'b1), + .I (clk_in_s), + .O (adc_clk_div)); + + assign ssi_rst = mssi_sync; + + end else begin + wire adc_clk_in; + + reg mssi_sync_d = 1'b0; + reg mssi_sync_2d = 1'b0; + reg mssi_sync_3d = 1'b0; + reg mssi_sync_edge = 1'b0; + reg mssi_sync_out_neg = 1'b0; + always @(posedge adc_clk_in) begin + mssi_sync_d <= mssi_sync; + mssi_sync_2d <= mssi_sync_d; + mssi_sync_3d <= mssi_sync_2d; + mssi_sync_edge <= mssi_sync_2d & ~mssi_sync_3d; + end + always @(negedge adc_clk_in) begin + mssi_sync_out_neg <= mssi_sync_edge; + end + + assign ssi_sync_out = mssi_sync_out_neg; + + reg ssi_rst_pos; + always @(posedge adc_clk_in) begin + ssi_rst_pos <= ssi_sync_in; + end + + BUFGCE #( + .CE_TYPE ("SYNC"), + .IS_CE_INVERTED (1'b0), + .IS_I_INVERTED (1'b0) + ) i_clk_buf ( + .O (adc_clk_in), + .CE (1'b1), + .I (clk_in_s) + ); + + BUFGCE #( + .CE_TYPE ("SYNC"), + .IS_CE_INVERTED (1'b0), + .IS_I_INVERTED (1'b0) + ) i_clk_buf_fast ( + .O (adc_clk_in_fast), + .CE (1'b1), + .I (adc_clk_in) + ); + + BUFGCE_DIV #( + .BUFGCE_DIVIDE (4), + .IS_CE_INVERTED (1'b0), + .IS_CLR_INVERTED (1'b0), + .IS_I_INVERTED (1'b0) + ) i_div_clk_buf ( + .O (adc_clk_div), + .CE (1'b1), + .CLR (ssi_rst), + .I (adc_clk_in) + ); + + assign ssi_rst = ssi_rst_pos; + + end + + endgenerate + + assign adc_clk = adc_clk_in_fast; + assign adc_valid = 1'b1; + +endmodule diff --git a/library/axi_adrv9001/adrv9001_rx_link.v b/library/axi_adrv9001/adrv9001_rx_link.v new file mode 100644 index 000000000..15616c60b --- /dev/null +++ b/library/axi_adrv9001/adrv9001_rx_link.v @@ -0,0 +1,325 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_rx_link #( + parameter CMOS_LVDS_N = 0 +) ( + + input adc_clk_div, + input [7:0] adc_data_0, + input [7:0] adc_data_1, + input [7:0] adc_data_2, + input [7:0] adc_data_3, + input [7:0] adc_data_strobe, + input adc_valid, + + // upper layer data interface + output rx_clk, + output rx_data_valid, + output [15:0] rx_data_i, + output [15:0] rx_data_q, + + // Config interface + input rx_sdr_ddr_n, + input rx_single_lane +); + + wire [7:0] data_0; + wire [7:0] data_1; + wire [7:0] data_2; + wire [7:0] data_3; + wire [7:0] data_strobe; + wire data_valid; + + assign rx_clk = adc_clk_div; + + // CMOS can operate in SDR or DDR mode + generate if (CMOS_LVDS_N) begin : cmos_4_to_8 + wire [3:0] sdr_data_0; + wire [3:0] sdr_data_1; + wire [3:0] sdr_data_2; + wire [3:0] sdr_data_3; + wire [3:0] sdr_data_strobe; + wire sdr_data_valid; + + wire [3:0] sdr_data_0_aligned; + wire [3:0] sdr_data_1_aligned; + wire [3:0] sdr_data_2_aligned; + wire [3:0] sdr_data_3_aligned; + wire [3:0] sdr_data_strobe_aligned; + + wire [7:0] sdr_data_0_packed; + wire [7:0] sdr_data_1_packed; + wire [7:0] sdr_data_2_packed; + wire [7:0] sdr_data_3_packed; + wire [7:0] sdr_data_strobe_packed; + + wire aligner4_ovalid; + + // For SDR drop every second DDR bit + + assign sdr_data_0 = {adc_data_0[7],adc_data_0[5],adc_data_0[3],adc_data_0[1]}; + assign sdr_data_1 = {adc_data_1[7],adc_data_1[5],adc_data_1[3],adc_data_1[1]}; + assign sdr_data_2 = {adc_data_2[7],adc_data_2[5],adc_data_2[3],adc_data_2[1]}; + assign sdr_data_3 = {adc_data_3[7],adc_data_3[5],adc_data_3[3],adc_data_3[1]}; + assign sdr_data_strobe = {adc_data_strobe[7],adc_data_strobe[5],adc_data_strobe[3],adc_data_strobe[1]}; + + adrv9001_aligner4 i_rx_aligner4_0 ( + .clk (adc_clk_div), + .idata (sdr_data_0), + .ivalid (adc_valid), + .strobe (sdr_data_strobe), + .odata (sdr_data_0_aligned) + ); + + adrv9001_aligner4 i_rx_aligner4_1 ( + .clk (adc_clk_div), + .idata (sdr_data_1), + .ivalid (adc_valid), + .strobe (sdr_data_strobe), + .odata (sdr_data_1_aligned) + ); + + adrv9001_aligner4 i_rx_aligner4_2 ( + .clk (adc_clk_div), + .idata (sdr_data_2), + .ivalid (adc_valid), + .strobe (sdr_data_strobe), + .odata (sdr_data_2_aligned) + ); + + adrv9001_aligner4 i_rx_aligner4_3 ( + .clk (adc_clk_div), + .idata (sdr_data_3), + .ivalid (adc_valid), + .strobe (sdr_data_strobe), + .odata (sdr_data_3_aligned) + ); + + adrv9001_aligner4 i_rx_aligner4_strobe ( + .clk (adc_clk_div), + .idata (sdr_data_strobe), + .ivalid (adc_valid), + .strobe (sdr_data_strobe), + .ovalid (aligner4_ovalid), + .odata (sdr_data_strobe_aligned) + ); + + adrv9001_pack #( + .WIDTH(4) + ) i_rx_pack_4_to_8_0 ( + .clk (adc_clk_div), + .idata (sdr_data_0_aligned), + .ivalid (aligner4_ovalid), + .sof (sdr_data_strobe_aligned[3]), + .odata (sdr_data_0_packed), + .ovalid (sdr_data_valid) + ); + + adrv9001_pack #( + .WIDTH(4) + ) i_rx_pack_4_to_8_1 ( + .clk (adc_clk_div), + .idata (sdr_data_1_aligned), + .ivalid (aligner4_ovalid), + .sof (sdr_data_strobe_aligned[3]), + .odata (sdr_data_1_packed), + .ovalid () + ); + + adrv9001_pack #( + .WIDTH(4) + ) i_rx_pack_4_to_8_2 ( + .clk (adc_clk_div), + .idata (sdr_data_2_aligned), + .ivalid (aligner4_ovalid), + .sof (sdr_data_strobe_aligned[3]), + .odata (sdr_data_2_packed), + .ovalid () + ); + + adrv9001_pack #( + .WIDTH(4) + ) i_rx_pack_4_to_8_3 ( + .clk (adc_clk_div), + .idata (sdr_data_3_aligned), + .ivalid (aligner4_ovalid), + .sof (sdr_data_strobe_aligned[3]), + .odata (sdr_data_3_packed), + .ovalid () + ); + + adrv9001_pack #( + .WIDTH(4) + ) i_rx_pack_4_to_8_strobe ( + .clk (adc_clk_div), + .idata (sdr_data_strobe_aligned), + .ivalid (aligner4_ovalid), + .sof (sdr_data_strobe_aligned[3]), + .odata (sdr_data_strobe_packed), + .ovalid () + ); + assign data_0 = rx_sdr_ddr_n ? sdr_data_0_packed : adc_data_0; + assign data_1 = rx_sdr_ddr_n ? sdr_data_1_packed : adc_data_1; + assign data_2 = rx_sdr_ddr_n ? sdr_data_2_packed : adc_data_2; + assign data_3 = rx_sdr_ddr_n ? sdr_data_3_packed : adc_data_3; + assign data_strobe = rx_sdr_ddr_n ? sdr_data_strobe_packed : adc_data_strobe; + assign data_valid = rx_sdr_ddr_n ? sdr_data_valid : adc_valid; + end else begin + assign data_0 = adc_data_0; + assign data_1 = adc_data_1; + assign data_2 = adc_data_2; + assign data_3 = adc_data_3; + assign data_strobe = adc_data_strobe; + assign data_valid = adc_valid; + end + endgenerate + + // ADC + + wire [7:0] rx_data8_0_aligned; + wire [7:0] rx_data8_1_aligned; + wire [7:0] rx_data8_2_aligned; + wire [7:0] rx_data8_3_aligned; + wire [7:0] rx_data8_strobe_aligned; + wire rx_data8_0_aligned_valid; + wire rx_data8_1_aligned_valid; + + wire [15:0] rx_data16_0_packed; + wire [15:0] rx_data16_1_packed; + wire rx_data16_0_packed_valid; + wire rx_data16_0_packed_osof; + + wire [31:0] rx_data32_0_packed; + wire rx_data32_0_packed_valid; + + adrv9001_aligner8 i_rx_aligner8_0( + .clk (adc_clk_div), + .idata (data_0), + .ivalid (data_valid), + .strobe (data_strobe), + .odata (rx_data8_0_aligned), + .ovalid (rx_data8_0_aligned_valid) + ); + + adrv9001_aligner8 i_rx_aligner8_1( + .clk (adc_clk_div), + .ivalid (data_valid), + .idata (data_1), + .strobe (data_strobe), + .odata (rx_data8_1_aligned), + .ovalid (rx_data8_1_aligned_valid) + ); + + generate if (CMOS_LVDS_N) begin : cmos_aligner8 + adrv9001_aligner8 i_rx_aligner8_2( + .clk (adc_clk_div), + .idata (data_2), + .ivalid (data_valid), + .strobe (data_strobe), + .odata (rx_data8_2_aligned) + ); + adrv9001_aligner8 i_rx_aligner8_3( + .clk (adc_clk_div), + .idata (data_3), + .ivalid (data_valid), + .strobe (data_strobe), + .odata (rx_data8_3_aligned) + ); + end + endgenerate + + adrv9001_aligner8 i_rx_strobe_aligner( + .clk (adc_clk_div), + .idata (data_strobe), + .ivalid (data_valid), + .strobe (data_strobe), + .odata (rx_data8_strobe_aligned) + ); + + adrv9001_pack #( + .WIDTH (8) + ) i_rx_pack_8_to_16_0 ( + .clk (adc_clk_div), + .ivalid (rx_data8_0_aligned_valid), + .idata (rx_data8_0_aligned), + .sof (rx_data8_strobe_aligned[7]), + .odata (rx_data16_0_packed), + .ovalid (rx_data16_0_packed_valid), + .osof (rx_data16_0_packed_osof) + ); + + adrv9001_pack #( + .WIDTH (8) + ) i_rx_pack_8_to_16_1 ( + .clk (adc_clk_div), + .ivalid (rx_data8_1_aligned_valid), + .idata (rx_data8_1_aligned), + .sof (rx_data8_strobe_aligned[7]), + .odata (rx_data16_1_packed), + .ovalid () + ); + + adrv9001_pack #( + .WIDTH (16) + ) i_rx_pack_16_to_32_0 ( + .clk (adc_clk_div), + .ivalid (rx_data16_0_packed_valid), + .idata (rx_data16_0_packed), + .sof (rx_data16_0_packed_osof), + .odata (rx_data32_0_packed), + .ovalid (rx_data32_0_packed_valid) + ); + + generate if (CMOS_LVDS_N) begin + assign rx_data_i = ~rx_single_lane ? {rx_data8_1_aligned,rx_data8_0_aligned} : + rx_data32_0_packed[31:16]; + assign rx_data_q = ~rx_single_lane ? {rx_data8_3_aligned,rx_data8_2_aligned} : + rx_data32_0_packed[15:0]; + assign rx_data_valid = ~rx_single_lane ? rx_data8_0_aligned_valid : + rx_data32_0_packed_valid; + end else begin + assign rx_data_i = ~rx_single_lane ? rx_data16_0_packed : + rx_data32_0_packed[31:16]; + assign rx_data_q = ~rx_single_lane ? rx_data16_1_packed : + rx_data32_0_packed[15:0]; + assign rx_data_valid = ~rx_single_lane ? rx_data16_0_packed_valid : + rx_data32_0_packed_valid; + end + endgenerate + +endmodule diff --git a/library/axi_adrv9001/adrv9001_tx.v b/library/axi_adrv9001/adrv9001_tx.v new file mode 100644 index 000000000..a5c131c9e --- /dev/null +++ b/library/axi_adrv9001/adrv9001_tx.v @@ -0,0 +1,238 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_tx #( + parameter CMOS_LVDS_N = 0, + parameter NUM_LANES = 4, + parameter FPGA_TECHNOLOGY = 0, + parameter USE_RX_CLK_FOR_TX = 0 +) ( + input ref_clk, + input up_clk, + + input mssi_sync, + input tx_output_enable, + + // physical interface (transmit) + output tx_dclk_out_n_NC, + output tx_dclk_out_p_dclk_out, + input tx_dclk_in_n_NC, + input tx_dclk_in_p_dclk_in, + output tx_idata_out_n_idata0, + output tx_idata_out_p_idata1, + output tx_qdata_out_n_qdata2, + output tx_qdata_out_p_qdata3, + output tx_strobe_out_n_NC, + output tx_strobe_out_p_strobe_out, + + input rx_clk_div, + input rx_clk, + input rx_ssi_rst, + + // internal resets and clocks + + input dac_rst, + output dac_clk_div, + + input [7:0] dac_data_0, + input [7:0] dac_data_1, + input [7:0] dac_data_2, + input [7:0] dac_data_3, + input [7:0] dac_data_strb, + input [7:0] dac_data_clk, + input dac_data_valid +); + + localparam SEVEN_SERIES = 1; + localparam ULTRASCALE = 2; + localparam ULTRASCALE_PLUS = 3; + + // internal wire + wire tx_dclk_in_s; + wire dac_fast_clk; + wire [NUM_LANES-1:0] serdes_out_p; + wire [NUM_LANES-1:0] serdes_out_n; + wire [NUM_LANES-1:0] data_s0; + wire [NUM_LANES-1:0] data_s1; + wire [NUM_LANES-1:0] data_s2; + wire [NUM_LANES-1:0] data_s3; + wire [NUM_LANES-1:0] data_s4; + wire [NUM_LANES-1:0] data_s5; + wire [NUM_LANES-1:0] data_s6; + wire [NUM_LANES-1:0] data_s7; + wire ssi_rst; + + ad_serdes_out #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .DDR_OR_SDR_N(1), + .DATA_WIDTH(NUM_LANES), + .SERDES_FACTOR(8), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY)) + i_serdes ( + .rst (dac_rst|ssi_rst), + .clk (dac_fast_clk), + .div_clk (dac_clk_div), + .loaden (1'b0), + .data_oe (tx_output_enable), + .data_s0 (data_s0), + .data_s1 (data_s1), + .data_s2 (data_s2), + .data_s3 (data_s3), + .data_s4 (data_s4), + .data_s5 (data_s5), + .data_s6 (data_s6), + .data_s7 (data_s7), + .data_out_se (), + .data_out_p (serdes_out_p), + .data_out_n (serdes_out_n)); + + generate + if (CMOS_LVDS_N == 0) begin + + IBUFGDS i_dac_clk_in_ibuf ( + .I (tx_dclk_in_p_dclk_in), + .IB (tx_dclk_in_n_NC), + .O (tx_dclk_in_s)); + + assign data_s0 = {dac_data_clk[7],dac_data_strb[7],dac_data_1[7],dac_data_0[7]}; + assign data_s1 = {dac_data_clk[6],dac_data_strb[6],dac_data_1[6],dac_data_0[6]}; + assign data_s2 = {dac_data_clk[5],dac_data_strb[5],dac_data_1[5],dac_data_0[5]}; + assign data_s3 = {dac_data_clk[4],dac_data_strb[4],dac_data_1[4],dac_data_0[4]}; + assign data_s4 = {dac_data_clk[3],dac_data_strb[3],dac_data_1[3],dac_data_0[3]}; + assign data_s5 = {dac_data_clk[2],dac_data_strb[2],dac_data_1[2],dac_data_0[2]}; + assign data_s6 = {dac_data_clk[1],dac_data_strb[1],dac_data_1[1],dac_data_0[1]}; + assign data_s7 = {dac_data_clk[0],dac_data_strb[0],dac_data_1[0],dac_data_0[0]}; + + assign {tx_dclk_out_p_dclk_out, + tx_strobe_out_p_strobe_out, + tx_qdata_out_p_qdata3, + tx_idata_out_p_idata1} = serdes_out_p; + + assign {tx_dclk_out_n_NC, + tx_strobe_out_n_NC, + tx_qdata_out_n_qdata2, + tx_idata_out_n_idata0} = serdes_out_n; + end else begin + + IBUF i_dac_clk_in_ibuf ( + .I (tx_dclk_in_p_dclk_in), + .O (tx_dclk_in_s)); + + assign data_s0 = {dac_data_clk[7],dac_data_strb[7],dac_data_3[7],dac_data_2[7],dac_data_1[7],dac_data_0[7]}; + assign data_s1 = {dac_data_clk[6],dac_data_strb[6],dac_data_3[6],dac_data_2[6],dac_data_1[6],dac_data_0[6]}; + assign data_s2 = {dac_data_clk[5],dac_data_strb[5],dac_data_3[5],dac_data_2[5],dac_data_1[5],dac_data_0[5]}; + assign data_s3 = {dac_data_clk[4],dac_data_strb[4],dac_data_3[4],dac_data_2[4],dac_data_1[4],dac_data_0[4]}; + assign data_s4 = {dac_data_clk[3],dac_data_strb[3],dac_data_3[3],dac_data_2[3],dac_data_1[3],dac_data_0[3]}; + assign data_s5 = {dac_data_clk[2],dac_data_strb[2],dac_data_3[2],dac_data_2[2],dac_data_1[2],dac_data_0[2]}; + assign data_s6 = {dac_data_clk[1],dac_data_strb[1],dac_data_3[1],dac_data_2[1],dac_data_1[1],dac_data_0[1]}; + assign data_s7 = {dac_data_clk[0],dac_data_strb[0],dac_data_3[0],dac_data_2[0],dac_data_1[0],dac_data_0[0]}; + + assign {tx_dclk_out_p_dclk_out, + tx_strobe_out_p_strobe_out, + tx_qdata_out_p_qdata3, + tx_qdata_out_n_qdata2, + tx_idata_out_p_idata1, + tx_idata_out_n_idata0} = serdes_out_p; + + assign {tx_dclk_out_n_NC, + tx_strobe_out_n_NC} = 2'b0; + end + + if (USE_RX_CLK_FOR_TX == 0) begin + + if (FPGA_TECHNOLOGY == SEVEN_SERIES) begin + + // SERDES fast clock + BUFIO i_dac_clk_in_gbuf ( + .I (tx_dclk_in_s), + .O (dac_fast_clk)); + + // SERDES slow clock + BUFR #(.BUFR_DIVIDE("4")) i_dac_div_clk_rbuf ( + .CLR (mssi_sync), + .CE (1'b1), + .I (tx_dclk_in_s), + .O (dac_clk_div)); + + assign ssi_rst = mssi_sync; + + end else begin + + reg mssi_sync_d = 1'b0; + reg mssi_sync_2d = 1'b0; + always @(posedge dac_fast_clk) begin + mssi_sync_d <= mssi_sync; + mssi_sync_2d <= mssi_sync_d; + end + + BUFGCE #( + .CE_TYPE ("SYNC"), + .IS_CE_INVERTED (1'b0), + .IS_I_INVERTED (1'b0) + ) i_dac_clk_in_gbuf ( + .O (dac_fast_clk), + .CE (1'b1), + .I (tx_dclk_in_s) + ); + + BUFGCE_DIV #( + .BUFGCE_DIVIDE (4), + .IS_CE_INVERTED (1'b0), + .IS_CLR_INVERTED (1'b0), + .IS_I_INVERTED (1'b0) + ) i_dac_div_clk_rbuf ( + .O (dac_clk_div), + .CE (1'b1), + .CLR (mssi_sync_2d), + .I (tx_dclk_in_s) + ); + + assign ssi_rst = mssi_sync_2d; + + end + + end else begin + + assign dac_fast_clk = rx_clk; + assign dac_clk_div = rx_clk_div; + assign ssi_rst = rx_ssi_rst; + + end + + endgenerate + +endmodule diff --git a/library/axi_adrv9001/adrv9001_tx_link.v b/library/axi_adrv9001/adrv9001_tx_link.v new file mode 100644 index 000000000..d6d40bd75 --- /dev/null +++ b/library/axi_adrv9001/adrv9001_tx_link.v @@ -0,0 +1,198 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_tx_link #( + parameter CMOS_LVDS_N = 0, + parameter CLK_DIV_IS_FAST_CLK = 0 +) ( + input dac_clk_div, + output [7:0] dac_data_0, + output [7:0] dac_data_1, + output [7:0] dac_data_2, + output [7:0] dac_data_3, + output [7:0] dac_data_strobe, + output [7:0] dac_data_clk, + output dac_data_valid, + + // upper layer data interface + output tx_clk, + input tx_rst, + input tx_data_valid, + input [15:0] tx_data_i, + input [15:0] tx_data_q, + + // Config interface + input tx_sdr_ddr_n, + input tx_single_lane +); + + assign tx_clk = dac_clk_div; + + wire [7:0] data32sdr; + wire [7:0] strobe32sdr; + + wire [7:0] data8sdr_0; + wire [7:0] data8sdr_1; + wire [7:0] data8sdr_2; + wire [7:0] data8sdr_3; + wire [7:0] strobe8sdr; + wire ld_next; + + reg [31:0] data32 = 32'b0; + reg [31:0] strobe32 = 32'b0; + reg [15:0] data16_0 = 16'b0; + reg [15:0] data16_1 = 16'b0; + reg [15:0] strobe16 = 16'b0; + reg [7:0] data8_0 = 8'b0; + reg [7:0] data8_1 = 8'b0; + reg [7:0] data8_2 = 8'b0; + reg [7:0] data8_3 = 8'b0; + reg [7:0] strobe8 = 8'b0; + reg [3:0] valid_gen = 4'b0; + + // Serialization factor Per data lane 32 + always @(posedge tx_clk) begin + if (tx_data_valid) begin + data32 <= {tx_data_i,tx_data_q}; + strobe32 <= {1'b1,31'b0}; + end else if (ld_next) begin + if (tx_sdr_ddr_n) begin + data32 <= {data32,4'b0}; + strobe32 <= {strobe32,4'b0}; + end else begin + data32 <= {data32,8'b0}; + strobe32 <= {strobe32,8'b0}; + end + end + end + + // Double each bit due the DDR PHY + assign data32sdr = {data32[31],data32[31], + data32[30],data32[30], + data32[29],data32[29], + data32[28],data32[28]}; + assign strobe32sdr = {strobe32[31],strobe32[31], + strobe32[30],strobe32[30], + strobe32[29],strobe32[29], + strobe32[28],strobe32[28]}; + + // Serialization factor Per data lane 16 + always @(posedge tx_clk) begin + if (tx_data_valid) begin + data16_0 <= tx_data_i; + data16_1 <= tx_data_q; + strobe16 <= {1'b1,15'b0}; + end else if (ld_next) begin + data16_0 <= {data16_0,8'b0}; + data16_1 <= {data16_1,8'b0}; + strobe16 <= {strobe16,8'b0}; + end + end + + // Serialization factor Per data lane 8 + always @(posedge tx_clk) begin + if (tx_data_valid) begin + data8_0 <= tx_data_i[7:0]; + data8_1 <= tx_data_i[15:8]; + data8_2 <= tx_data_q[7:0]; + data8_3 <= tx_data_q[15:8]; + strobe8 <= {1'b1,7'b0}; + end else if (ld_next) begin + data8_0 <= {data8_0,4'b0}; + data8_1 <= {data8_1,4'b0}; + data8_2 <= {data8_2,4'b0}; + data8_3 <= {data8_3,4'b0}; + strobe8 <= {strobe16,4'b0}; + end + end + + // Double each bit due the DDR PHY + assign data8sdr_0 = {data8_0[7],data8_0[7], + data8_0[6],data8_0[6], + data8_0[5],data8_0[5], + data8_0[4],data8_0[4]}; + assign data8sdr_1 = {data8_1[7],data8_1[7], + data8_1[6],data8_1[6], + data8_1[5],data8_1[5], + data8_1[4],data8_1[4]}; + assign data8sdr_2 = {data8_2[7],data8_2[7], + data8_2[6],data8_2[6], + data8_2[5],data8_2[5], + data8_2[4],data8_2[4]}; + assign data8sdr_3 = {data8_3[7],data8_3[7], + data8_3[6],data8_3[6], + data8_3[5],data8_3[5], + data8_3[4],data8_3[4]}; + assign strobe8sdr = {strobe8[7],strobe8[7], + strobe8[6],strobe8[6], + strobe8[5],strobe8[5], + strobe8[4],strobe8[4]}; + + assign dac_data_0 = tx_single_lane ? (tx_sdr_ddr_n ? data32sdr : data32[31-:8]) : + (CMOS_LVDS_N ? (tx_sdr_ddr_n ? data8sdr_0 : data8_0) : + data16_0[15-:8]); + + assign dac_data_1 = tx_single_lane ? 'b0 : + (CMOS_LVDS_N ? (tx_sdr_ddr_n ? data8sdr_1 : data8_1) : + data16_1[15-:8]); + + assign dac_data_2 = tx_single_lane ? 'b0 : + (CMOS_LVDS_N ? (tx_sdr_ddr_n ? data8sdr_2 : data8_2) : + 1'b0); + + assign dac_data_3 = tx_single_lane ? 'b0 : + (CMOS_LVDS_N ? (tx_sdr_ddr_n ? data8sdr_3 : data8_3) : + 1'b0); + + assign dac_data_strobe = tx_single_lane ? (tx_sdr_ddr_n ? strobe32sdr : strobe32[31-:8]) : + (CMOS_LVDS_N ? (tx_sdr_ddr_n ? strobe8sdr : strobe8) : + strobe16[15-:8]); + + assign dac_data_clk = {4{1'b1,1'b0}}; + + assign dac_data_valid = (CLK_DIV_IS_FAST_CLK == 0) ? 1'b1 : valid_gen[3]; + + always @(posedge tx_clk) begin + if (tx_data_valid) begin + valid_gen <= 4'b1000; + end else begin + valid_gen <= {valid_gen[2:0],valid_gen[3]}; + end + end + assign ld_next = (CLK_DIV_IS_FAST_CLK == 0) ? 1'b1 : valid_gen[2]; + +endmodule diff --git a/library/axi_adrv9001/axi_adrv9001.v b/library/axi_adrv9001/axi_adrv9001.v new file mode 100644 index 000000000..2b8de2538 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001.v @@ -0,0 +1,522 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_adrv9001 #( + parameter ID = 0, + parameter CMOS_LVDS_N = 0, + parameter IO_DELAY_GROUP = "dev_if_delay_group", + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter USE_RX_CLK_FOR_TX = 0 +) ( + input ref_clk, + input mssi_sync, + input tx_output_enable, + + // physical interface + input rx1_dclk_in_n_NC, + input rx1_dclk_in_p_dclk_in, + input rx1_idata_in_n_idata0, + input rx1_idata_in_p_idata1, + input rx1_qdata_in_n_qdata2, + input rx1_qdata_in_p_qdata3, + input rx1_strobe_in_n_NC, + input rx1_strobe_in_p_strobe_in, + + input rx2_dclk_in_n_NC, + input rx2_dclk_in_p_dclk_in, + input rx2_idata_in_n_idata0, + input rx2_idata_in_p_idata1, + input rx2_qdata_in_n_qdata2, + input rx2_qdata_in_p_qdata3, + input rx2_strobe_in_n_NC, + input rx2_strobe_in_p_strobe_in, + + output tx1_dclk_out_n_NC, + output tx1_dclk_out_p_dclk_out, + input tx1_dclk_in_n_NC, + input tx1_dclk_in_p_dclk_in, + output tx1_idata_out_n_idata0, + output tx1_idata_out_p_idata1, + output tx1_qdata_out_n_qdata2, + output tx1_qdata_out_p_qdata3, + output tx1_strobe_out_n_NC, + output tx1_strobe_out_p_strobe_out, + + output tx2_dclk_out_n_NC, + output tx2_dclk_out_p_dclk_out, + input tx2_dclk_in_n_NC, + input tx2_dclk_in_p_dclk_in, + output tx2_idata_out_n_idata0, + output tx2_idata_out_p_idata1, + output tx2_qdata_out_n_qdata2, + output tx2_qdata_out_p_qdata3, + output tx2_strobe_out_n_NC, + output tx2_strobe_out_p_strobe_out, + + input delay_clk, + + // user interface + + output adc_1_clk, + output adc_1_rst, + + output adc_1_valid_i0, + output adc_1_enable_i0, + output [15:0] adc_1_data_i0, + output adc_1_valid_q0, + output adc_1_enable_q0, + output [15:0] adc_1_data_q0, + output adc_1_valid_i1, + output adc_1_enable_i1, + output [15:0] adc_1_data_i1, + output adc_1_valid_q1, + output adc_1_enable_q1, + output [15:0] adc_1_data_q1, + input adc_1_dovf, + + output adc_2_clk, + output adc_2_rst, + output adc_2_valid_i0, + output adc_2_enable_i0, + output [15:0] adc_2_data_i0, + output adc_2_valid_q0, + output adc_2_enable_q0, + output [15:0] adc_2_data_q0, + input adc_2_dovf, + + output dac_1_clk, + output dac_1_rst, + output dac_1_valid_i0, + output dac_1_enable_i0, + input [15:0] dac_1_data_i0, + output dac_1_valid_q0, + output dac_1_enable_q0, + input [15:0] dac_1_data_q0, + output dac_1_valid_i1, + output dac_1_enable_i1, + input [15:0] dac_1_data_i1, + output dac_1_valid_q1, + output dac_1_enable_q1, + input [15:0] dac_1_data_q1, + input dac_1_dunf, + + output dac_2_clk, + output dac_2_rst, + output dac_2_valid_i0, + output dac_2_enable_i0, + input [15:0] dac_2_data_i0, + output dac_2_valid_q0, + output dac_2_enable_q0, + input [15:0] dac_2_data_q0, + input dac_2_dunf, + + // axi interface + input s_axi_aclk, + input s_axi_aresetn, + input s_axi_awvalid, + input [15:0] s_axi_awaddr, + 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, + output s_axi_arready, + output s_axi_rvalid, + output [ 1:0] s_axi_rresp, + output [31:0] s_axi_rdata, + input s_axi_rready, + input [ 2:0] s_axi_awprot, + input [ 2:0] s_axi_arprot +); + + localparam SEVEN_SERIES = 1; + localparam ULTRASCALE = 2; + localparam ULTRASCALE_PLUS = 3; + + localparam DRP_WIDTH = FPGA_TECHNOLOGY == ULTRASCALE ? 9 : + FPGA_TECHNOLOGY == ULTRASCALE_PLUS ? 9 : 5; + + localparam NUM_LANES = CMOS_LVDS_N ? 5 : 3; + + // internal signals + wire up_wreq_s; + wire up_rreq_s; + wire [13:0] up_waddr_s; + wire [13:0] up_raddr_s; + wire [31:0] up_wdata_s; + wire [31:0] up_rdata_s; + wire up_wack_s; + wire up_rack_s; + + wire [15:0] rx1_data_i; + wire [15:0] rx1_data_q; + wire rx1_data_valid; + wire rx1_single_lane; + wire rx1_sdr_ddr_n; + wire [15:0] rx2_data_i; + wire [15:0] rx2_data_q; + wire rx2_data_valid; + wire rx2_single_lane; + wire rx2_sdr_ddr_n; + + wire [15:0] tx1_data_i; + wire [15:0] tx1_data_q; + wire tx1_data_valid; + wire tx1_single_lane; + wire tx1_sdr_ddr_n; + wire [15:0] tx2_data_i; + wire [15:0] tx2_data_q; + wire tx2_data_valid; + wire tx2_single_lane; + wire tx2_sdr_ddr_n; + + wire adc_1_valid; + wire adc_2_valid; + wire dac_1_valid; + wire dac_2_valid; + + // internal clocks & resets + wire up_rstn; + wire up_clk; + + // clock/reset assignments + assign up_clk = s_axi_aclk; + assign up_rstn = s_axi_aresetn; + + wire [NUM_LANES-1:0] up_rx1_dld; + wire [DRP_WIDTH*NUM_LANES-1:0] up_rx1_dwdata; + wire [DRP_WIDTH*NUM_LANES-1:0] up_rx1_drdata; + wire [NUM_LANES-1:0] up_rx2_dld; + wire [DRP_WIDTH*NUM_LANES-1:0] up_rx2_dwdata; + wire [DRP_WIDTH*NUM_LANES-1:0] up_rx2_drdata; + wire delay_rx1_rst; + wire delay_rx2_rst; + wire delay_rx1_locked; + wire delay_rx2_locked; + + axi_adrv9001_if #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .NUM_LANES (NUM_LANES), + .DRP_WIDTH (DRP_WIDTH), + .IO_DELAY_GROUP (IO_DELAY_GROUP), + .USE_RX_CLK_FOR_TX (USE_RX_CLK_FOR_TX) + ) i_if( + + // + // Physical interface + // + .ref_clk (ref_clk), + .mssi_sync (mssi_sync), + .tx_output_enable (tx_output_enable), + + .rx1_dclk_in_n_NC (rx1_dclk_in_n_NC), + .rx1_dclk_in_p_dclk_in (rx1_dclk_in_p_dclk_in), + .rx1_idata_in_n_idata0 (rx1_idata_in_n_idata0), + .rx1_idata_in_p_idata1 (rx1_idata_in_p_idata1), + .rx1_qdata_in_n_qdata2 (rx1_qdata_in_n_qdata2), + .rx1_qdata_in_p_qdata3 (rx1_qdata_in_p_qdata3), + .rx1_strobe_in_n_NC (rx1_strobe_in_n_NC), + .rx1_strobe_in_p_strobe_in (rx1_strobe_in_p_strobe_in), + + .rx2_dclk_in_n_NC (rx2_dclk_in_n_NC), + .rx2_dclk_in_p_dclk_in (rx2_dclk_in_p_dclk_in), + .rx2_idata_in_n_idata0 (rx2_idata_in_n_idata0), + .rx2_idata_in_p_idata1 (rx2_idata_in_p_idata1), + .rx2_qdata_in_n_qdata2 (rx2_qdata_in_n_qdata2), + .rx2_qdata_in_p_qdata3 (rx2_qdata_in_p_qdata3), + .rx2_strobe_in_n_NC (rx2_strobe_in_n_NC), + .rx2_strobe_in_p_strobe_in (rx2_strobe_in_p_strobe_in), + + .tx1_dclk_out_n_NC (tx1_dclk_out_n_NC), + .tx1_dclk_out_p_dclk_out (tx1_dclk_out_p_dclk_out), + .tx1_dclk_in_n_NC (tx1_dclk_in_n_NC), + .tx1_dclk_in_p_dclk_in (tx1_dclk_in_p_dclk_in), + .tx1_idata_out_n_idata0 (tx1_idata_out_n_idata0), + .tx1_idata_out_p_idata1 (tx1_idata_out_p_idata1), + .tx1_qdata_out_n_qdata2 (tx1_qdata_out_n_qdata2), + .tx1_qdata_out_p_qdata3 (tx1_qdata_out_p_qdata3), + .tx1_strobe_out_n_NC (tx1_strobe_out_n_NC), + .tx1_strobe_out_p_strobe_out (tx1_strobe_out_p_strobe_out), + + .tx2_dclk_out_n_NC (tx2_dclk_out_n_NC), + .tx2_dclk_out_p_dclk_out (tx2_dclk_out_p_dclk_out), + .tx2_dclk_in_n_NC (tx2_dclk_in_n_NC), + .tx2_dclk_in_p_dclk_in (tx2_dclk_in_p_dclk_in), + .tx2_idata_out_n_idata0 (tx2_idata_out_n_idata0), + .tx2_idata_out_p_idata1 (tx2_idata_out_p_idata1), + .tx2_qdata_out_n_qdata2 (tx2_qdata_out_n_qdata2), + .tx2_qdata_out_p_qdata3 (tx2_qdata_out_p_qdata3), + .tx2_strobe_out_n_NC (tx2_strobe_out_n_NC), + .tx2_strobe_out_p_strobe_out (tx2_strobe_out_p_strobe_out), + + // + // Control interface + // + + // delay interface (for IDELAY macros) + .delay_clk (delay_clk), + .delay_rx1_rst (delay_rx1_rst), + .delay_rx2_rst (delay_rx2_rst), + .delay_rx1_locked (delay_rx1_locked), + .delay_rx2_locked (delay_rx2_locked), + .up_clk (up_clk), + .up_rx1_dld (up_rx1_dld), + .up_rx1_dwdata (up_rx1_dwdata), + .up_rx1_drdata (up_rx1_drdata), + + .up_rx2_dld (up_rx2_dld), + .up_rx2_dwdata (up_rx2_dwdata), + .up_rx2_drdata (up_rx2_drdata), + + // + // Transport layer interface + // + + // ADC interface + .rx1_clk (adc_1_clk), + .rx1_rst (adc_1_rst), + .rx1_data_valid (rx1_data_valid), + .rx1_data_i (rx1_data_i), + .rx1_data_q (rx1_data_q), + + .rx1_single_lane (rx1_single_lane), + .rx1_sdr_ddr_n (rx1_sdr_ddr_n), + + .rx2_clk (adc_2_clk), + .rx2_rst (adc_2_rst), + .rx2_data_valid (rx2_data_valid), + .rx2_data_i (rx2_data_i), + .rx2_data_q (rx2_data_q), + + .rx2_single_lane (rx2_single_lane), + .rx2_sdr_ddr_n (rx2_sdr_ddr_n), + + // DAC interface + .tx1_clk (dac_1_clk), + .tx1_rst (dac_1_rst), + .tx1_data_valid (tx1_data_valid), + .tx1_data_i (tx1_data_i), + .tx1_data_q (tx1_data_q), + + .tx1_single_lane (tx1_single_lane), + .tx1_sdr_ddr_n (tx1_sdr_ddr_n), + + .tx2_clk (dac_2_clk), + .tx2_rst (dac_2_rst), + .tx2_data_valid (tx2_data_valid), + .tx2_data_i (tx2_data_i), + .tx2_data_q (tx2_data_q), + + .tx2_single_lane (tx2_single_lane), + .tx2_sdr_ddr_n (tx2_sdr_ddr_n) + ); + + // common processor control + axi_ad9001_core #( + .ID (ID), + .NUM_LANES (NUM_LANES), + .CMOS_LVDS_N (CMOS_LVDS_N), + .DRP_WIDTH (DRP_WIDTH), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE) + ) i_core ( + // ADC interface + .rx1_clk (adc_1_clk), + .rx1_rst (adc_1_rst), + .rx1_data_valid (rx1_data_valid), + .rx1_data_i (rx1_data_i), + .rx1_data_q (rx1_data_q), + + .rx1_single_lane (rx1_single_lane), + .rx1_sdr_ddr_n (rx1_sdr_ddr_n), + + .rx2_clk (adc_2_clk), + .rx2_rst (adc_2_rst), + .rx2_data_valid (rx2_data_valid), + .rx2_data_i (rx2_data_i), + .rx2_data_q (rx2_data_q), + + .rx2_single_lane (rx2_single_lane), + .rx2_sdr_ddr_n (rx2_sdr_ddr_n), + + //DAC interface + .tx1_clk (dac_1_clk), + .tx1_rst (dac_1_rst), + .tx1_data_valid (tx1_data_valid), + .tx1_data_i (tx1_data_i), + .tx1_data_q (tx1_data_q), + + .tx1_single_lane (tx1_single_lane), + .tx1_sdr_ddr_n (tx1_sdr_ddr_n), + + .tx2_clk (dac_2_clk), + .tx2_rst (dac_2_rst), + .tx2_data_valid (tx2_data_valid), + .tx2_data_i (tx2_data_i), + .tx2_data_q (tx2_data_q), + + .tx2_single_lane (tx2_single_lane), + .tx2_sdr_ddr_n (tx2_sdr_ddr_n), + + // + // User layer interface + // + .adc_1_valid (adc_1_valid), + .adc_1_enable_i0 (adc_1_enable_i0), + .adc_1_data_i0 (adc_1_data_i0), + .adc_1_enable_q0 (adc_1_enable_q0), + .adc_1_data_q0 (adc_1_data_q0), + .adc_1_enable_i1 (adc_1_enable_i1), + .adc_1_data_i1 (adc_1_data_i1), + .adc_1_enable_q1 (adc_1_enable_q1), + .adc_1_data_q1 (adc_1_data_q1), + .adc_1_dovf (adc_1_dovf), + + .adc_2_valid (adc_2_valid), + .adc_2_enable_i (adc_2_enable_i0), + .adc_2_data_i (adc_2_data_i0), + .adc_2_enable_q (adc_2_enable_q0), + .adc_2_data_q (adc_2_data_q0), + .adc_2_dovf (adc_2_dovf), + + .dac_1_valid (dac_1_valid), + .dac_1_enable_i0 (dac_1_enable_i0), + .dac_1_data_i0 (dac_1_data_i0), + .dac_1_enable_q0 (dac_1_enable_q0), + .dac_1_data_q0 (dac_1_data_q0), + .dac_1_enable_i1 (dac_1_enable_i1), + .dac_1_data_i1 (dac_1_data_i1), + .dac_1_enable_q1 (dac_1_enable_q1), + .dac_1_data_q1 (dac_1_data_q1), + .dac_1_dunf (dac_1_dunf), + + .dac_2_valid (dac_2_valid), + .dac_2_enable_i0 (dac_2_enable_i0), + .dac_2_data_i0 (dac_2_data_i0), + .dac_2_enable_q0 (dac_2_enable_q0), + .dac_2_data_q0 (dac_2_data_q0), + .dac_2_dunf (dac_2_dunf), + + .delay_clk (delay_clk), + + .up_rx1_dld (up_rx1_dld), + .up_rx1_dwdata (up_rx1_dwdata), + .up_rx1_drdata (up_rx1_drdata), + .delay_rx1_rst (delay_rx1_rst), + .delay_rx1_locked (delay_rx1_locked), + + .up_rx2_dld (up_rx2_dld), + .up_rx2_dwdata (up_rx2_dwdata), + .up_rx2_drdata (up_rx2_drdata), + .delay_rx2_rst (delay_rx2_rst), + .delay_rx2_locked (delay_rx2_locked), + + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq_s), + .up_waddr (up_waddr_s), + .up_wdata (up_wdata_s), + .up_wack (up_wack_s), + .up_rreq (up_rreq_s), + .up_raddr (up_raddr_s), + .up_rdata (up_rdata_s), + .up_rack (up_rack_s) + ); + + assign adc_1_valid_i0 = adc_1_valid; + assign adc_1_valid_q0 = adc_1_valid; + assign adc_1_valid_i1 = adc_1_valid; + assign adc_1_valid_q1 = adc_1_valid; + assign adc_2_valid_i0 = adc_2_valid; + assign adc_2_valid_q0 = adc_2_valid; + + assign dac_1_valid_i0 = dac_1_valid; + assign dac_1_valid_q0 = dac_1_valid; + assign dac_1_valid_i1 = dac_1_valid; + assign dac_1_valid_q1 = dac_1_valid; + assign dac_2_valid_i0 = dac_2_valid; + assign dac_2_valid_q0 = dac_2_valid; + + // up bus interface + up_axi #( + .AXI_ADDRESS_WIDTH(15) + ) i_up_axi ( + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_axi_awvalid (s_axi_awvalid), + .up_axi_awaddr (s_axi_awaddr[14:0]), + .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[14:0]), + .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_s), + .up_waddr (up_waddr_s[12:0]), + .up_wdata (up_wdata_s), + .up_rdata (up_rdata_s), + .up_wack (up_wack_s), + .up_raddr (up_raddr_s[12:0]), + .up_rreq (up_rreq_s), + .up_rack (up_rack_s) + ); + + // Alias Rx/Tx peripherals @ 0x8000 + assign up_raddr_s[13] = 1'b0; + assign up_waddr_s[13] = 1'b0; + +endmodule diff --git a/library/axi_adrv9001/axi_adrv9001_constr.sdc b/library/axi_adrv9001/axi_adrv9001_constr.sdc new file mode 100644 index 000000000..77095d969 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_constr.sdc @@ -0,0 +1,6 @@ + +set_false_path -from [get_registers *i_dev_if|up_enable_int*] -to [get_registers *i_dev_if|enable_up_m1*] +set_false_path -from [get_registers *i_dev_if|up_txnrx_int*] -to [get_registers *i_dev_if|txnrx_up_m1*] +set_false_path -from [get_registers *up_xfer_cntrl:i_xfer_tdd_control|d_xfer_toggle*] -to [get_registers *up_xfer_cntrl:i_xfer_tdd_control|up_xfer_state_m1*] +set_false_path -from [get_registers *up_xfer_cntrl:i_xfer_tdd_control|up_xfer_toggle*] -to [get_registers *up_xfer_cntrl:i_xfer_tdd_control|d_xfer_toggle_m1*] +set_false_path -from [get_registers *up_xfer_cntrl:i_xfer_tdd_control|up_xfer_data*] -to [get_registers *up_xfer_cntrl:i_xfer_tdd_control|d_data_cntrl*] diff --git a/library/axi_adrv9001/axi_adrv9001_constr.xdc b/library/axi_adrv9001/axi_adrv9001_constr.xdc new file mode 100644 index 000000000..1eddedaa6 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_constr.xdc @@ -0,0 +1,5 @@ +set_false_path -quiet -from [get_cells -quiet -hier *in_toggle_d1_reg* -filter {NAME =~ *i_serdes* && IS_SEQUENTIAL}] +set_false_path -quiet -from [get_cells -quiet -hier *out_toggle_d1_reg* -filter {NAME =~ *i_serdes* && IS_SEQUENTIAL}] + +set_false_path -through [get_pins -hier *i_idelay/CNTVALUEOUT] +set_false_path -through [get_pins -hier *i_idelay/CNTVALUEIN] diff --git a/library/axi_adrv9001/axi_adrv9001_core.v b/library/axi_adrv9001/axi_adrv9001_core.v new file mode 100644 index 000000000..67c4deb18 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_core.v @@ -0,0 +1,501 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_ad9001_core #( + parameter ID = 0, + parameter CMOS_LVDS_N = 0, + parameter NUM_LANES = 3, + parameter DRP_WIDTH = 5, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + + parameter DAC_DDS_TYPE = 1, + parameter DAC_DDS_CORDIC_DW = 20, + parameter DAC_DDS_CORDIC_PHASE_DW = 18 +) ( + // ADC interface + input rx1_clk, + output rx1_rst, + input rx1_data_valid, + input [15:0] rx1_data_i, + input [15:0] rx1_data_q, + + output rx1_single_lane, + output rx1_sdr_ddr_n, + + input rx2_clk, + output rx2_rst, + input rx2_data_valid, + input [15:0] rx2_data_i, + input [15:0] rx2_data_q, + + output rx2_single_lane, + output rx2_sdr_ddr_n, + + // DAC interface + input tx1_clk, + output tx1_rst, + output tx1_data_valid, + output [15:0] tx1_data_i, + output [15:0] tx1_data_q, + + output tx1_single_lane, + output tx1_sdr_ddr_n, + + input tx2_clk, + output tx2_rst, + output tx2_data_valid, + output [15:0] tx2_data_i, + output [15:0] tx2_data_q, + + output tx2_single_lane, + output tx2_sdr_ddr_n, + + // DMA interface + output adc_1_valid, + output adc_1_enable_i0, + output [15:0] adc_1_data_i0, + output adc_1_enable_q0, + output [15:0] adc_1_data_q0, + output adc_1_enable_i1, + output [15:0] adc_1_data_i1, + output adc_1_enable_q1, + output [15:0] adc_1_data_q1, + input adc_1_dovf, + + output adc_2_valid, + output adc_2_enable_i, + output [15:0] adc_2_data_i, + output adc_2_enable_q, + output [15:0] adc_2_data_q, + input adc_2_dovf, + + output dac_1_valid, + output dac_1_enable_i0, + input [15:0] dac_1_data_i0, + output dac_1_enable_q0, + input [15:0] dac_1_data_q0, + output dac_1_enable_i1, + input [15:0] dac_1_data_i1, + output dac_1_enable_q1, + input [15:0] dac_1_data_q1, + input dac_1_dunf, + + output dac_2_valid, + output dac_2_enable_i0, + input [15:0] dac_2_data_i0, + output dac_2_enable_q0, + input [15:0] dac_2_data_q0, + input dac_2_dunf, + + // delay interface + + input delay_clk, + output delay_rx1_rst, + input delay_rx1_locked, + output delay_rx2_rst, + input delay_rx2_locked, + + output [NUM_LANES-1:0] up_rx1_dld, + output [DRP_WIDTH*NUM_LANES-1:0] up_rx1_dwdata, + input [DRP_WIDTH*NUM_LANES-1:0] up_rx1_drdata, + + output [NUM_LANES-1:0] up_rx2_dld, + output [DRP_WIDTH*NUM_LANES-1:0] up_rx2_dwdata, + input [DRP_WIDTH*NUM_LANES-1:0] up_rx2_drdata, + + // processor interface + + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [13:0] up_raddr, + output reg [31:0] up_rdata, + output reg up_rack +); + + wire up_wack_s[0:5]; + wire [31:0] up_rdata_s[0:5]; + wire up_rack_s[0:5]; + + wire tx1_data_valid_A; + wire [15:0] tx1_data_i_A; + wire [15:0] tx1_data_q_A; + wire tx1_data_valid_B; + wire [15:0] tx1_data_i_B; + wire [15:0] tx1_data_q_B; + wire tx2_data_valid_A; + wire [15:0] tx2_data_i_A; + wire [15:0] tx2_data_q_A; + wire rx1_r1_mode; + wire rx2_rst_loc; + wire rx2_single_lane_loc; + wire rx2_sdr_ddr_n_loc; + wire tx1_r1_mode; + wire tx2_rst_loc; + wire tx2_single_lane_loc; + wire tx2_sdr_ddr_n_loc; + + reg tx1_data_valid_A_d; + reg [15:0] tx1_data_i_A_d; + reg [15:0] tx1_data_q_A_d; + reg tx1_data_valid_B_d; + reg [15:0] tx1_data_i_B_d; + reg [15:0] tx1_data_q_B_d; + reg tx2_data_valid_A_d; + reg [15:0] tx2_data_i_A_d; + reg [15:0] tx2_data_q_A_d; + + // rx1_r1_mode and tx1_r1_mode considered static during operation + // rx1_r1_mode should be 0 only when rx1_clk and rx2_clk have the same frequency + // tx1_r1_mode should be 0 only when tx1_clk and tx2_clk have the same frequency + + assign rx2_rst = rx1_r1_mode ? rx2_rst_loc : rx1_rst; + assign rx2_single_lane = rx1_r1_mode ? rx2_single_lane_loc : rx1_single_lane; + assign rx2_sdr_ddr_n = rx1_r1_mode ? rx2_sdr_ddr_n_loc : rx1_sdr_ddr_n; + + assign tx2_rst = tx1_r1_mode ? tx2_rst_loc : tx1_rst; + assign tx2_single_lane = tx1_r1_mode ? tx2_single_lane_loc : tx1_single_lane; + assign tx2_sdr_ddr_n = tx1_r1_mode ? tx2_sdr_ddr_n_loc : tx1_sdr_ddr_n; + + assign tx1_data_valid = tx1_data_valid_A_d; + assign tx1_data_i = tx1_data_i_A_d; + assign tx1_data_q = tx1_data_q_A_d; + + assign tx2_data_valid = tx1_r1_mode ? tx2_data_valid_A_d : tx1_data_valid_B_d; + assign tx2_data_i = tx1_r1_mode ? tx2_data_i_A_d : tx1_data_i_B_d; + assign tx2_data_q = tx1_r1_mode ? tx2_data_q_A_d : tx1_data_q_B_d; + + always @(posedge tx1_clk) begin + tx1_data_valid_A_d <= tx1_data_valid_A; + tx1_data_i_A_d <= tx1_data_i_A; + tx1_data_q_A_d <= tx1_data_q_A; + end + + always @(posedge tx2_clk) begin + tx2_data_valid_A_d <= tx2_data_valid_A; + tx2_data_i_A_d <= tx2_data_i_A; + tx2_data_q_A_d <= tx2_data_q_A; + end + + // Use tx1_r1_mode as clock enable when the two clocks have different frequency + always @(posedge tx2_clk) begin + if (tx1_r1_mode==0) begin + tx1_data_valid_B_d <= tx1_data_valid_B; + tx1_data_i_B_d <= tx1_data_i_B; + tx1_data_q_B_d <= tx1_data_q_B; + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_rdata <= 'd0; + up_rack <= 'd0; + up_wack <= 'd0; + end else begin + up_rdata <= up_rdata_s[0] | up_rdata_s[1] | up_rdata_s[2] | up_rdata_s[3] | up_rdata_s[4] | up_rdata_s[5]; + up_rack <= up_rack_s[0] | up_rack_s[1] | up_rack_s[2] | up_rack_s[3] | up_rack_s[4] | up_rack_s[5]; + up_wack <= up_wack_s[0] | up_wack_s[1] | up_wack_s[2] | up_wack_s[3] | up_wack_s[4] | up_wack_s[5]; + end + end + + axi_adrv9001_rx #( + .ID (ID), + .CMOS_LVDS_N (CMOS_LVDS_N), + .COMMON_BASE_ADDR(6'h00), + .CHANNEL_BASE_ADDR(6'h01), + .MODE_R1 (0), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE), + .DATAFORMAT_DISABLE (0), + .DCFILTER_DISABLE (1), + .IQCORRECTION_DISABLE (1)) + i_rx1 ( + .adc_rst (rx1_rst), + .adc_clk (rx1_clk), + .adc_valid_A (rx1_data_valid), + .adc_data_i_A (rx1_data_i), + .adc_data_q_A (rx1_data_q), + + .adc_valid_B (rx2_data_valid), + .adc_data_i_B (rx2_data_i), + .adc_data_q_B (rx2_data_q), + + .adc_single_lane (rx1_single_lane), + .adc_sdr_ddr_n (rx1_sdr_ddr_n), + .adc_r1_mode (rx1_r1_mode), + + .dac_data_valid_A (tx1_data_valid_A), + .dac_data_i_A (tx1_data_i_A), + .dac_data_q_A (tx1_data_q_A), + .dac_data_valid_B (tx1_data_valid_B), + .dac_data_i_B (tx1_data_i_B), + .dac_data_q_B (tx1_data_q_B), + + .adc_valid (adc_1_valid), + + .adc_enable_i0 (adc_1_enable_i0), + .adc_data_i0 (adc_1_data_i0[15:0]), + .adc_enable_q0 (adc_1_enable_q0), + .adc_data_q0 (adc_1_data_q0[15:0]), + + .adc_enable_i1 (adc_1_enable_i1), + .adc_data_i1 (adc_1_data_i1[15:0]), + .adc_enable_q1 (adc_1_enable_q1), + .adc_data_q1 (adc_1_data_q1[15:0]), + + .adc_dovf (adc_1_dovf), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[0]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[0]), + .up_rack (up_rack_s[0])); + + axi_adrv9001_rx #( + .ID (ID), + .CMOS_LVDS_N (CMOS_LVDS_N), + .COMMON_BASE_ADDR(6'h04), + .CHANNEL_BASE_ADDR(6'h05), + .MODE_R1 (1), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE), + .DATAFORMAT_DISABLE (0), + .DCFILTER_DISABLE (1), + .IQCORRECTION_DISABLE (1)) + i_rx2 ( + .adc_rst (rx2_rst_loc), + .adc_clk (rx2_clk), + .adc_valid_A (rx2_data_valid), + .adc_data_i_A (rx2_data_i), + .adc_data_q_A (rx2_data_q), + + .adc_valid_B (1'b0), + .adc_data_i_B (16'b0), + .adc_data_q_B (16'b0), + + .adc_single_lane (rx2_single_lane_loc), + .adc_sdr_ddr_n (rx2_sdr_ddr_n_loc), + + .dac_data_valid_A (tx2_data_valid_A), + .dac_data_i_A (tx2_data_i_A), + .dac_data_q_A (tx2_data_q_A), + .dac_data_valid_B (1'b0), + .dac_data_i_B (16'b0), + .dac_data_q_B (16'b0), + + .adc_valid (adc_2_valid), + + .adc_enable_i0 (adc_2_enable_i), + .adc_data_i0 (adc_2_data_i[15:0]), + .adc_enable_q0 (adc_2_enable_q), + .adc_data_q0 (adc_2_data_q[15:0]), + + .adc_dovf (adc_2_dovf), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[1]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[1]), + .up_rack (up_rack_s[1])); + + axi_adrv9001_tx #( + .ID (ID), + .CMOS_LVDS_N (CMOS_LVDS_N), + .COMMON_BASE_ADDR ('h08), + .CHANNEL_BASE_ADDR ('h09), + .MODE_R1 (0), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE), + .DDS_DISABLE (0), + .IQCORRECTION_DISABLE (1), + .DAC_DDS_TYPE (DAC_DDS_TYPE), + .DAC_DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), + .DAC_DDS_CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW)) + i_tx1 ( + .dac_rst (tx1_rst), + .dac_clk (tx1_clk), + .dac_data_valid_A (tx1_data_valid_A), + .dac_data_i_A (tx1_data_i_A), + .dac_data_q_A (tx1_data_q_A), + .dac_data_valid_B (tx1_data_valid_B), + .dac_data_i_B (tx1_data_i_B), + .dac_data_q_B (tx1_data_q_B), + .dac_single_lane (tx1_single_lane), + .dac_sdr_ddr_n (tx1_sdr_ddr_n), + .dac_r1_mode (tx1_r1_mode), + .dac_sync_in (1'b0), + .dac_sync_out (), + .dac_enable_i0 (dac_1_enable_i0), + .dac_valid (dac_1_valid), + .dac_data_i0 (dac_1_data_i0[15:0]), + .dac_enable_q0 (dac_1_enable_q0), + .dac_data_q0 (dac_1_data_q0[15:0]), + .dac_enable_i1 (dac_1_enable_i1), + .dac_data_i1 (dac_1_data_i1[15:0]), + .dac_enable_q1 (dac_1_enable_q1), + .dac_data_q1 (dac_1_data_q1[15:0]), + .dac_dunf (dac_1_dunf), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[2]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[2]), + .up_rack (up_rack_s[2])); + + axi_adrv9001_tx #( + .ID (ID), + .CMOS_LVDS_N (CMOS_LVDS_N), + .COMMON_BASE_ADDR ('h10), + .CHANNEL_BASE_ADDR ('h11), + .MODE_R1 (1), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE), + .DDS_DISABLE (0), + .IQCORRECTION_DISABLE (1), + .DAC_DDS_TYPE (DAC_DDS_TYPE), + .DAC_DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), + .DAC_DDS_CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW)) + i_tx2 ( + .dac_rst (tx2_rst_loc), + .dac_clk (tx2_clk), + .dac_data_valid_A (tx2_data_valid_A), + .dac_data_i_A (tx2_data_i_A), + .dac_data_q_A (tx2_data_q_A), + .dac_data_valid_B (), + .dac_data_i_B (), + .dac_data_q_B (), + .dac_single_lane (tx2_single_lane_loc), + .dac_sdr_ddr_n (tx2_sdr_ddr_n_loc), + .dac_sync_in (1'b0), + .dac_sync_out (), + .dac_valid (dac_2_valid), + .dac_enable_i0 (dac_2_enable_i0), + .dac_data_i0 (dac_2_data_i0[15:0]), + .dac_enable_q0 (dac_2_enable_q0), + .dac_data_q0 (dac_2_data_q0[15:0]), + .dac_enable_i1 (), + .dac_data_i1 (16'b0), + .dac_enable_q1 (), + .dac_data_q1 (16'b0), + .dac_dunf (dac_2_dunf), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[3]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[3]), + .up_rack (up_rack_s[3])); + + // adc delay control + up_delay_cntrl #( + .DATA_WIDTH(NUM_LANES), + .DRP_WIDTH(DRP_WIDTH), + .BASE_ADDRESS(6'h02)) + i_delay_cntrl_rx1 ( + .delay_clk (delay_clk), + .delay_rst (delay_rx1_rst), + .delay_locked (delay_rx1_locked), + .up_dld (up_rx1_dld), + .up_dwdata (up_rx1_dwdata), + .up_drdata (up_rx1_drdata), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[4]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[4]), + .up_rack (up_rack_s[4])); + + up_delay_cntrl #( + .DATA_WIDTH(NUM_LANES), + .DRP_WIDTH(DRP_WIDTH), + .BASE_ADDRESS(6'h06)) + i_delay_cntrl_rx2 ( + .delay_clk (delay_clk), + .delay_rst (delay_rx2_rst), + .delay_locked (delay_rx2_locked), + .up_dld (up_rx2_dld), + .up_dwdata (up_rx2_dwdata), + .up_drdata (up_rx2_drdata), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[5]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[5]), + .up_rack (up_rack_s[5])); + +endmodule + diff --git a/library/axi_adrv9001/axi_adrv9001_hw.tcl b/library/axi_adrv9001/axi_adrv9001_hw.tcl new file mode 100644 index 000000000..3df858a03 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_hw.tcl @@ -0,0 +1,225 @@ +package require qsys +package require quartus::device + +source ../scripts/adi_env.tcl +source ../scripts/adi_ip_intel.tcl + +ad_ip_create axi_adrv9001 {AXI ADRV9001 Interface} axi_adrv9001_elab +set_module_property VALIDATION_CALLBACK info_param_validate + +ad_ip_files axi_adrv9001 [list\ + "$ad_hdl_dir/library/intel/common/ad_mul.v" \ + "$ad_hdl_dir/library/common/ad_dds_cordic_pipe.v" \ + "$ad_hdl_dir/library/common/ad_dds_sine_cordic.v" \ + "$ad_hdl_dir/library/common/ad_dds_sine.v" \ + "$ad_hdl_dir/library/common/ad_dds_1.v" \ + "$ad_hdl_dir/library/common/ad_dds_2.v" \ + "$ad_hdl_dir/library/common/ad_dds.v" \ + "$ad_hdl_dir/library/common/ad_datafmt.v" \ + "$ad_hdl_dir/library/common/ad_rst.v" \ + "$ad_hdl_dir/library/common/up_xfer_cntrl.v" \ + "$ad_hdl_dir/library/common/up_xfer_status.v" \ + "$ad_hdl_dir/library/common/up_clock_mon.v" \ + "$ad_hdl_dir/library/common/up_delay_cntrl.v" \ + "$ad_hdl_dir/library/common/up_adc_common.v" \ + "$ad_hdl_dir/library/common/up_adc_channel.v" \ + "$ad_hdl_dir/library/common/up_dac_common.v" \ + "$ad_hdl_dir/library/common/up_dac_channel.v" \ + "$ad_hdl_dir/library/common/ad_pnmon.v" \ + "$ad_hdl_dir/library/common/ad_pngen.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/intel/common/up_xfer_cntrl_constr.sdc" \ + "$ad_hdl_dir/library/intel/common/up_xfer_status_constr.sdc" \ + "$ad_hdl_dir/library/intel/common/up_clock_mon_constr.sdc" \ + "$ad_hdl_dir/library/intel/common/up_rst_constr.sdc" \ + "intel/adrv9001_rx.v" \ + "intel/adrv9001_tx.v" \ + "adrv9001_pack.v" \ + "adrv9001_aligner4.v" \ + "adrv9001_aligner8.v" \ + "adrv9001_rx_link.v" \ + "adrv9001_tx_link.v" \ + "axi_adrv9001_rx.v" \ + "axi_adrv9001_rx_channel.v" \ + "axi_adrv9001_if.v" \ + "axi_adrv9001_tx.v" \ + "axi_adrv9001_tx_channel.v" \ + "axi_adrv9001_core.v" \ + "axi_adrv9001_constr.sdc" \ + "axi_adrv9001.v" ] + +# parameters + +ad_ip_parameter ID INTEGER 0 +ad_ip_parameter CMOS_LVDS_N INTEGER 0 +ad_ip_parameter IO_DELAY_GROUP STRING {dev_if_delay_group} + +adi_add_auto_fpga_spec_params + +# interfaces + +ad_ip_intf_s_axi s_axi_aclk s_axi_aresetn + +#ad_interface clock delay_clk input 1 +ad_interface clock adc_1_clk output 1 +ad_interface clock adc_2_clk output 1 +ad_interface clock dac_1_clk output 1 +ad_interface clock dac_2_clk output 1 + +ad_interface reset adc_1_rst output 1 if_adc_1_clk +ad_interface reset adc_2_rst output 1 if_adc_2_clk +ad_interface reset dac_1_rst output 1 if_dac_1_clk +ad_interface reset dac_2_rst output 1 if_dac_2_clk + +add_interface adc_1_ch_0 conduit end +add_interface_port adc_1_ch_0 adc_1_enable_i0 enable Output 1 +add_interface_port adc_1_ch_0 adc_1_valid_i0 valid Output 1 +add_interface_port adc_1_ch_0 adc_1_data_i0 data Output 16 + +add_interface adc_1_ch_1 conduit end +add_interface_port adc_1_ch_1 adc_1_enable_q0 enable Output 1 +add_interface_port adc_1_ch_1 adc_1_valid_q0 valid Output 1 +add_interface_port adc_1_ch_1 adc_1_data_q0 data Output 16 + +add_interface adc_1_ch_2 conduit end +add_interface_port adc_1_ch_2 adc_1_enable_i1 enable Output 1 +add_interface_port adc_1_ch_2 adc_1_valid_i1 valid Output 1 +add_interface_port adc_1_ch_2 adc_1_data_i1 data Output 16 + +add_interface adc_1_ch_3 conduit end +add_interface_port adc_1_ch_3 adc_1_enable_q1 enable Output 1 +add_interface_port adc_1_ch_3 adc_1_valid_q1 valid Output 1 +add_interface_port adc_1_ch_3 adc_1_data_q1 data Output 16 + +ad_interface signal adc_1_dovf input 1 ovf + +set_interface_property adc_1_ch_0 associatedClock if_adc_1_clk +set_interface_property adc_1_ch_1 associatedClock if_adc_1_clk +set_interface_property adc_1_ch_2 associatedClock if_adc_1_clk +set_interface_property adc_1_ch_3 associatedClock if_adc_1_clk +set_interface_property adc_1_ch_0 associatedReset adc_1_rst +set_interface_property adc_1_ch_1 associatedReset adc_1_rst +set_interface_property adc_1_ch_2 associatedReset adc_1_rst +set_interface_property adc_1_ch_3 associatedReset adc_1_rst + +add_interface adc_2_ch_0 conduit end +add_interface_port adc_2_ch_0 adc_2_enable_i0 enable Output 1 +add_interface_port adc_2_ch_0 adc_2_valid_i0 valid Output 1 +add_interface_port adc_2_ch_0 adc_2_data_i0 data Output 16 + +add_interface adc_2_ch_1 conduit end +add_interface_port adc_2_ch_1 adc_2_enable_q0 enable Output 1 +add_interface_port adc_2_ch_1 adc_2_valid_q0 valid Output 1 +add_interface_port adc_2_ch_1 adc_2_data_q0 data Output 16 + +ad_interface signal adc_2_dovf input 1 ovf + +set_interface_property adc_2_ch_0 associatedClock if_adc_2_clk +set_interface_property adc_2_ch_1 associatedClock if_adc_2_clk +set_interface_property adc_2_ch_0 associatedReset adc_2_rst +set_interface_property adc_2_ch_1 associatedReset adc_2_rst + +# DAC interfaces +add_interface dac_1_ch_0 conduit end +add_interface_port dac_1_ch_0 dac_1_enable_i0 enable Output 1 +add_interface_port dac_1_ch_0 dac_1_valid_i0 valid Output 1 +add_interface_port dac_1_ch_0 dac_1_data_i0 data Input 16 + +add_interface dac_1_ch_1 conduit end +add_interface_port dac_1_ch_1 dac_1_enable_q0 enable Output 1 +add_interface_port dac_1_ch_1 dac_1_valid_q0 valid Output 1 +add_interface_port dac_1_ch_1 dac_1_data_q0 data Input 16 + +add_interface dac_1_ch_2 conduit end +add_interface_port dac_1_ch_2 dac_1_enable_i1 enable Output 1 +add_interface_port dac_1_ch_2 dac_1_valid_i1 valid Output 1 +add_interface_port dac_1_ch_2 dac_1_data_i1 data Input 16 + +add_interface dac_1_ch_3 conduit end +add_interface_port dac_1_ch_3 dac_1_enable_q1 enable Output 1 +add_interface_port dac_1_ch_3 dac_1_valid_q1 valid Output 1 +add_interface_port dac_1_ch_3 dac_1_data_q1 data Input 16 + +set_interface_property dac_1_ch_0 associatedClock if_dac_1_clk +set_interface_property dac_1_ch_1 associatedClock if_dac_1_clk +set_interface_property dac_1_ch_2 associatedClock if_dac_1_clk +set_interface_property dac_1_ch_3 associatedClock if_dac_1_clk +set_interface_property dac_1_ch_0 associatedReset dac_1_rst +set_interface_property dac_1_ch_1 associatedReset dac_1_rst +set_interface_property dac_1_ch_2 associatedReset dac_1_rst +set_interface_property dac_1_ch_3 associatedReset dac_1_rst + +ad_interface signal dac_1_dunf input 1 unf + +add_interface dac_2_ch_0 conduit end +add_interface_port dac_2_ch_0 dac_2_enable_i0 enable Output 1 +add_interface_port dac_2_ch_0 dac_2_valid_i0 valid Output 1 +add_interface_port dac_2_ch_0 dac_2_data_i0 data Input 16 + +add_interface dac_2_ch_1 conduit end +add_interface_port dac_2_ch_1 dac_2_enable_q0 enable Output 1 +add_interface_port dac_2_ch_1 dac_2_valid_q0 valid Output 1 +add_interface_port dac_2_ch_1 dac_2_data_q0 data Input 16 + +ad_interface signal dac_2_dunf input 1 unf + +# updates + +proc axi_adrv9001_elab {} { + set m_fpga_technology [get_parameter_value "FPGA_TECHNOLOGY"] + set m_cmos_lvds_n [get_parameter_value "CMOS_LVDS_N"] + + add_hdl_instance adrv9001_gpio_in altera_gpio + set_instance_parameter_value adrv9001_gpio_in {DEVICE_FAMILY} {Arria 10} + set_instance_parameter_value adrv9001_gpio_in {PIN_TYPE_GUI} {Input} + set_instance_parameter_value adrv9001_gpio_in {SIZE} {1} + set_instance_parameter_value adrv9001_gpio_in {gui_io_reg_mode} {DDIO} + + add_hdl_instance adrv9001_gpio_out altera_gpio + set_instance_parameter_value adrv9001_gpio_out {DEVICE_FAMILY} {Arria 10} + set_instance_parameter_value adrv9001_gpio_out {PIN_TYPE_GUI} {Output} + set_instance_parameter_value adrv9001_gpio_out {SIZE} {1} + set_instance_parameter_value adrv9001_gpio_out {gui_io_reg_mode} {DDIO} + + add_hdl_instance periphery_clk_buf altclkctrl + set_instance_parameter_value periphery_clk_buf {DEVICE_FAMILY} {Arria 10} + set_instance_parameter_value periphery_clk_buf {CLOCK_TYPE} {Periphery Clock} + + add_interface device_if conduit end + set_interface_property device_if associatedClock none + set_interface_property device_if associatedReset none + + if {$m_cmos_lvds_n == 1} { + + add_interface_port device_if rx1_dclk_in_p_dclk_in rx1_dclk_in_p_dclk_in Input 1 + add_interface_port device_if rx1_idata_in_n_idata0 rx1_idata_in_n_idata0 Input 1 + add_interface_port device_if rx1_idata_in_p_idata1 rx1_idata_in_p_idata1 Input 1 + add_interface_port device_if rx1_qdata_in_n_qdata2 rx1_qdata_in_n_qdata2 Input 1 + add_interface_port device_if rx1_qdata_in_p_qdata3 rx1_qdata_in_p_qdata3 Input 1 + add_interface_port device_if rx1_strobe_in_p_strobe_in rx1_strobe_in_p_strobe_in Input 1 + + add_interface_port device_if rx2_dclk_in_p_dclk_in rx2_dclk_in_p_dclk_in Input 1 + add_interface_port device_if rx2_idata_in_n_idata0 rx2_idata_in_n_idata0 Input 1 + add_interface_port device_if rx2_idata_in_p_idata1 rx2_idata_in_p_idata1 Input 1 + add_interface_port device_if rx2_qdata_in_n_qdata2 rx2_qdata_in_n_qdata2 Input 1 + add_interface_port device_if rx2_qdata_in_p_qdata3 rx2_qdata_in_p_qdata3 Input 1 + add_interface_port device_if rx2_strobe_in_p_strobe_in rx2_strobe_in_p_strobe_in Input 1 + + add_interface_port device_if tx1_dclk_out_p_dclk_out tx1_dclk_out_p_dclk_out Output 1 + add_interface_port device_if tx1_dclk_in_p_dclk_in tx1_dclk_in_p_dclk_in Input 1 + add_interface_port device_if tx1_idata_out_n_idata0 tx1_idata_out_n_idata0 Output 1 + add_interface_port device_if tx1_idata_out_p_idata1 tx1_idata_out_p_idata1 Output 1 + add_interface_port device_if tx1_qdata_out_n_qdata2 tx1_qdata_out_n_qdata2 Output 1 + add_interface_port device_if tx1_qdata_out_p_qdata3 tx1_qdata_out_p_qdata3 Output 1 + add_interface_port device_if tx1_strobe_out_p_strobe_out tx1_strobe_out_p_strobe_out Output 1 + + add_interface_port device_if tx2_dclk_out_p_dclk_out tx2_dclk_out_p_dclk_out Output 1 + add_interface_port device_if tx2_dclk_in_p_dclk_in tx2_dclk_in_p_dclk_in Input 1 + add_interface_port device_if tx2_idata_out_n_idata0 tx2_idata_out_n_idata0 Output 1 + add_interface_port device_if tx2_idata_out_p_idata1 tx2_idata_out_p_idata1 Output 1 + add_interface_port device_if tx2_qdata_out_n_qdata2 tx2_qdata_out_n_qdata2 Output 1 + add_interface_port device_if tx2_qdata_out_p_qdata3 tx2_qdata_out_p_qdata3 Output 1 + add_interface_port device_if tx2_strobe_out_p_strobe_out tx2_strobe_out_p_strobe_out Output 1 + } +} + diff --git a/library/axi_adrv9001/axi_adrv9001_if.v b/library/axi_adrv9001/axi_adrv9001_if.v new file mode 100644 index 000000000..ca67a6a54 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_if.v @@ -0,0 +1,438 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_adrv9001_if #( + parameter CMOS_LVDS_N = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter NUM_LANES = 3, + parameter DRP_WIDTH = 5, + parameter IO_DELAY_GROUP = "dev_if_delay_group", + parameter USE_RX_CLK_FOR_TX = 0 +) ( + input ref_clk, + input tx_output_enable, + + input mssi_sync, + + // device interface + input rx1_dclk_in_n_NC, + input rx1_dclk_in_p_dclk_in, + input rx1_idata_in_n_idata0, + input rx1_idata_in_p_idata1, + input rx1_qdata_in_n_qdata2, + input rx1_qdata_in_p_qdata3, + input rx1_strobe_in_n_NC, + input rx1_strobe_in_p_strobe_in, + + input rx2_dclk_in_n_NC, + input rx2_dclk_in_p_dclk_in, + input rx2_idata_in_n_idata0, + input rx2_idata_in_p_idata1, + input rx2_qdata_in_n_qdata2, + input rx2_qdata_in_p_qdata3, + input rx2_strobe_in_n_NC, + input rx2_strobe_in_p_strobe_in, + + output tx1_dclk_out_n_NC, + output tx1_dclk_out_p_dclk_out, + input tx1_dclk_in_n_NC, + input tx1_dclk_in_p_dclk_in, + output tx1_idata_out_n_idata0, + output tx1_idata_out_p_idata1, + output tx1_qdata_out_n_qdata2, + output tx1_qdata_out_p_qdata3, + output tx1_strobe_out_n_NC, + output tx1_strobe_out_p_strobe_out, + + output tx2_dclk_out_n_NC, + output tx2_dclk_out_p_dclk_out, + input tx2_dclk_in_n_NC, + input tx2_dclk_in_p_dclk_in, + output tx2_idata_out_n_idata0, + output tx2_idata_out_p_idata1, + output tx2_qdata_out_n_qdata2, + output tx2_qdata_out_p_qdata3, + output tx2_strobe_out_n_NC, + output tx2_strobe_out_p_strobe_out, + + // delay interface (for IDELAY macros) + input delay_clk, + input delay_rx1_rst, + input delay_rx2_rst, + output delay_rx1_locked, + output delay_rx2_locked, + + input up_clk, + + input [NUM_LANES-1:0] up_rx1_dld, + input [DRP_WIDTH*NUM_LANES-1:0] up_rx1_dwdata, + output [DRP_WIDTH*NUM_LANES-1:0] up_rx1_drdata, + + input [NUM_LANES-1:0] up_rx2_dld, + input [DRP_WIDTH*NUM_LANES-1:0] up_rx2_dwdata, + output [DRP_WIDTH*NUM_LANES-1:0] up_rx2_drdata, + + // upper layer data interface + + output rx1_clk, + input rx1_rst, + output rx1_data_valid, + output [15:0] rx1_data_i, + output [15:0] rx1_data_q, + + input rx1_single_lane, + input rx1_sdr_ddr_n, + + output rx2_clk, + input rx2_rst, + output rx2_data_valid, + output [15:0] rx2_data_i, + output [15:0] rx2_data_q, + + input rx2_single_lane, + input rx2_sdr_ddr_n, + + output tx1_clk, + input tx1_rst, + input tx1_data_valid, + input [15:0] tx1_data_i, + input [15:0] tx1_data_q, + + input tx1_single_lane, + input tx1_sdr_ddr_n, + + output tx2_clk, + input tx2_rst, + input tx2_data_valid, + input [15:0] tx2_data_i, + input [15:0] tx2_data_q, + + input tx2_single_lane, + input tx2_sdr_ddr_n +); + + // Tx has an extra lane to drive the clock + localparam TX_NUM_LANES = NUM_LANES + 1; + + wire adc_1_clk_div; + wire [7:0] adc_1_data_0; + wire [7:0] adc_1_data_1; + wire [7:0] adc_1_data_2; + wire [7:0] adc_1_data_3; + wire [7:0] adc_1_data_strobe; + wire adc_1_clk; + wire adc_1_valid; + wire adc_1_ssi_rst; + + wire adc_2_clk_div; + wire [7:0] adc_2_data_0; + wire [7:0] adc_2_data_1; + wire [7:0] adc_2_data_2; + wire [7:0] adc_2_data_3; + wire [7:0] adc_2_data_strobe; + wire adc_2_clk; + wire adc_2_valid; + wire adc_2_ssi_rst; + + wire dac_1_clk_div; + wire [7:0] dac_1_data_0; + wire [7:0] dac_1_data_1; + wire [7:0] dac_1_data_2; + wire [7:0] dac_1_data_3; + wire [7:0] dac_1_data_strobe; + wire [7:0] dac_1_data_clk; + wire dac_1_data_valid; + + wire dac_2_clk_div; + wire [7:0] dac_2_data_0; + wire [7:0] dac_2_data_1; + wire [7:0] dac_2_data_2; + wire [7:0] dac_2_data_3; + wire [7:0] dac_2_data_strobe; + wire [7:0] dac_2_data_clk; + wire dac_2_data_valid; + + wire rx_ssi_sync_out; + + adrv9001_rx + #(.CMOS_LVDS_N (CMOS_LVDS_N), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .NUM_LANES (NUM_LANES), + .DRP_WIDTH (DRP_WIDTH), + .IODELAY_CTRL (1), + .IO_DELAY_GROUP ({IO_DELAY_GROUP,"_rx"}) + ) i_rx_1_phy ( + .rx_dclk_in_n_NC (rx1_dclk_in_n_NC), + .rx_dclk_in_p_dclk_in (rx1_dclk_in_p_dclk_in), + .rx_idata_in_n_idata0 (rx1_idata_in_n_idata0), + .rx_idata_in_p_idata1 (rx1_idata_in_p_idata1), + .rx_qdata_in_n_qdata2 (rx1_qdata_in_n_qdata2), + .rx_qdata_in_p_qdata3 (rx1_qdata_in_p_qdata3), + .rx_strobe_in_n_NC (rx1_strobe_in_n_NC), + .rx_strobe_in_p_strobe_in (rx1_strobe_in_p_strobe_in), + + .adc_rst (rx1_rst), + .adc_clk (adc_1_clk), + .adc_clk_div (adc_1_clk_div), + .adc_data_0 (adc_1_data_0), + .adc_data_1 (adc_1_data_1), + .adc_data_2 (adc_1_data_2), + .adc_data_3 (adc_1_data_3), + .adc_data_strobe (adc_1_data_strobe), + .adc_valid (adc_1_valid), + + .up_clk (up_clk), + .up_adc_dld (up_rx1_dld), + .up_adc_dwdata (up_rx1_dwdata), + .up_adc_drdata (up_rx1_drdata), + .delay_clk (delay_clk), + .delay_rst (delay_rx1_rst), + .delay_locked (delay_rx1_locked), + + .mssi_sync (mssi_sync), + .ssi_sync_out (rx_ssi_sync_out), + .ssi_sync_in (rx_ssi_sync_out), + .ssi_rst (adc_1_ssi_rst) + ); + + adrv9001_rx_link #( + .CMOS_LVDS_N (CMOS_LVDS_N) + ) i_rx_1_link ( + .adc_clk_div (adc_1_clk_div), + .adc_data_0 (adc_1_data_0), + .adc_data_1 (adc_1_data_1), + .adc_data_2 (adc_1_data_2), + .adc_data_3 (adc_1_data_3), + .adc_data_strobe (adc_1_data_strobe), + .adc_valid (adc_1_valid), + // ADC interface + .rx_clk (rx1_clk), + .rx_data_valid (rx1_data_valid), + .rx_data_i (rx1_data_i), + .rx_data_q (rx1_data_q), + .rx_single_lane (rx1_single_lane), + .rx_sdr_ddr_n (rx1_sdr_ddr_n) + ); + + adrv9001_rx + #(.CMOS_LVDS_N (CMOS_LVDS_N), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .NUM_LANES (NUM_LANES), + .DRP_WIDTH (DRP_WIDTH), + .IODELAY_CTRL (0), + .IO_DELAY_GROUP ({IO_DELAY_GROUP,"_rx"}) + ) i_rx_2_phy ( + .rx_dclk_in_n_NC (rx2_dclk_in_n_NC), + .rx_dclk_in_p_dclk_in (rx2_dclk_in_p_dclk_in), + .rx_idata_in_n_idata0 (rx2_idata_in_n_idata0), + .rx_idata_in_p_idata1 (rx2_idata_in_p_idata1), + .rx_qdata_in_n_qdata2 (rx2_qdata_in_n_qdata2), + .rx_qdata_in_p_qdata3 (rx2_qdata_in_p_qdata3), + .rx_strobe_in_n_NC (rx2_strobe_in_n_NC), + .rx_strobe_in_p_strobe_in (rx2_strobe_in_p_strobe_in), + + .adc_rst (rx2_rst), + .adc_clk (adc_2_clk), + .adc_clk_div (adc_2_clk_div), + .adc_data_0 (adc_2_data_0), + .adc_data_1 (adc_2_data_1), + .adc_data_2 (adc_2_data_2), + .adc_data_3 (adc_2_data_3), + .adc_data_strobe (adc_2_data_strobe), + .adc_valid (adc_2_valid), + + .up_clk (up_clk), + .up_adc_dld (up_rx2_dld), + .up_adc_dwdata (up_rx2_dwdata), + .up_adc_drdata (up_rx2_drdata), + .delay_clk (delay_clk), + .delay_rst (delay_rx2_rst), + .delay_locked (delay_rx2_locked), + + .mssi_sync (1'b0), + .ssi_sync_out (), + .ssi_sync_in (rx_ssi_sync_out), + .ssi_rst (adc_2_ssi_rst) + ); + + adrv9001_rx_link #( + .CMOS_LVDS_N (CMOS_LVDS_N) + ) i_rx_2_link ( + .adc_clk_div (adc_2_clk_div), + .adc_data_0 (adc_2_data_0), + .adc_data_1 (adc_2_data_1), + .adc_data_2 (adc_2_data_2), + .adc_data_3 (adc_2_data_3), + .adc_data_strobe (adc_2_data_strobe), + .adc_valid (adc_2_valid), + // ADC interface + .rx_clk (rx2_clk), + .rx_data_valid (rx2_data_valid), + .rx_data_i (rx2_data_i), + .rx_data_q (rx2_data_q), + .rx_single_lane (rx2_single_lane), + .rx_sdr_ddr_n (rx2_sdr_ddr_n) + ); + + adrv9001_tx #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .NUM_LANES (TX_NUM_LANES), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .USE_RX_CLK_FOR_TX (USE_RX_CLK_FOR_TX) + ) i_tx_1_phy ( + + .ref_clk (ref_clk), + .up_clk (up_clk), + + .tx_output_enable(tx_output_enable), + + .tx_dclk_out_n_NC (tx1_dclk_out_n_NC), + .tx_dclk_out_p_dclk_out (tx1_dclk_out_p_dclk_out), + .tx_dclk_in_n_NC (tx1_dclk_in_n_NC), + .tx_dclk_in_p_dclk_in (tx1_dclk_in_p_dclk_in), + .tx_idata_out_n_idata0 (tx1_idata_out_n_idata0), + .tx_idata_out_p_idata1 (tx1_idata_out_p_idata1), + .tx_qdata_out_n_qdata2 (tx1_qdata_out_n_qdata2), + .tx_qdata_out_p_qdata3 (tx1_qdata_out_p_qdata3), + .tx_strobe_out_n_NC (tx1_strobe_out_n_NC), + .tx_strobe_out_p_strobe_out (tx1_strobe_out_p_strobe_out), + + .rx_clk_div (adc_1_clk_div), + .rx_clk (adc_1_clk), + .rx_ssi_rst (adc_1_ssi_rst), + + .dac_rst (tx1_rst), + .dac_clk_div (dac_1_clk_div), + + .dac_data_0 (dac_1_data_0), + .dac_data_1 (dac_1_data_1), + .dac_data_2 (dac_1_data_2), + .dac_data_3 (dac_1_data_3), + .dac_data_strb (dac_1_data_strobe), + .dac_data_clk (dac_1_data_clk), + .dac_data_valid (dac_1_data_valid), + + .mssi_sync (mssi_sync) + ); + + adrv9001_tx_link #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .CLK_DIV_IS_FAST_CLK (FPGA_TECHNOLOGY >= 100) + ) i_tx_1_link ( + .dac_clk_div (dac_1_clk_div), + .dac_data_0 (dac_1_data_0), + .dac_data_1 (dac_1_data_1), + .dac_data_2 (dac_1_data_2), + .dac_data_3 (dac_1_data_3), + .dac_data_strobe (dac_1_data_strobe), + .dac_data_clk (dac_1_data_clk), + .dac_data_valid (dac_1_data_valid), + // DAC interface + .tx_clk (tx1_clk), + .tx_rst (tx1_rst), + .tx_data_valid (tx1_data_valid), + .tx_data_i (tx1_data_i), + .tx_data_q (tx1_data_q), + .tx_sdr_ddr_n (tx1_sdr_ddr_n), + .tx_single_lane (tx1_single_lane) + ); + + adrv9001_tx #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .NUM_LANES (TX_NUM_LANES), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .USE_RX_CLK_FOR_TX (USE_RX_CLK_FOR_TX) + ) i_tx_2_phy ( + + .ref_clk (ref_clk), + .up_clk (up_clk), + + .tx_output_enable(tx_output_enable), + + .tx_dclk_out_n_NC (tx2_dclk_out_n_NC), + .tx_dclk_out_p_dclk_out (tx2_dclk_out_p_dclk_out), + .tx_dclk_in_n_NC (tx2_dclk_in_n_NC), + .tx_dclk_in_p_dclk_in (tx2_dclk_in_p_dclk_in), + .tx_idata_out_n_idata0 (tx2_idata_out_n_idata0), + .tx_idata_out_p_idata1 (tx2_idata_out_p_idata1), + .tx_qdata_out_n_qdata2 (tx2_qdata_out_n_qdata2), + .tx_qdata_out_p_qdata3 (tx2_qdata_out_p_qdata3), + .tx_strobe_out_n_NC (tx2_strobe_out_n_NC), + .tx_strobe_out_p_strobe_out (tx2_strobe_out_p_strobe_out), + + .rx_clk_div (adc_2_clk_div), + .rx_clk (adc_2_clk), + .rx_ssi_rst (adc_2_ssi_rst), + + .dac_rst (tx2_rst), + .dac_clk_div (dac_2_clk_div), + + .dac_data_0 (dac_2_data_0), + .dac_data_1 (dac_2_data_1), + .dac_data_2 (dac_2_data_2), + .dac_data_3 (dac_2_data_3), + .dac_data_strb (dac_2_data_strobe), + .dac_data_clk (dac_2_data_clk), + .dac_data_valid (dac_2_data_valid), + + .mssi_sync (mssi_sync) + ); + + adrv9001_tx_link #( + .CMOS_LVDS_N (CMOS_LVDS_N), + .CLK_DIV_IS_FAST_CLK (FPGA_TECHNOLOGY >= 100) + ) i_tx_2_link ( + .dac_clk_div (dac_2_clk_div), + .dac_data_0 (dac_2_data_0), + .dac_data_1 (dac_2_data_1), + .dac_data_2 (dac_2_data_2), + .dac_data_3 (dac_2_data_3), + .dac_data_strobe (dac_2_data_strobe), + .dac_data_clk (dac_2_data_clk), + .dac_data_valid (dac_2_data_valid), + // DAC interface + .tx_clk (tx2_clk), + .tx_rst (tx2_rst), + .tx_data_valid (tx2_data_valid), + .tx_data_i (tx2_data_i), + .tx_data_q (tx2_data_q), + .tx_sdr_ddr_n (tx2_sdr_ddr_n), + .tx_single_lane (tx2_single_lane) + ); + +endmodule + diff --git a/library/axi_adrv9001/axi_adrv9001_ip.tcl b/library/axi_adrv9001/axi_adrv9001_ip.tcl new file mode 100644 index 000000000..f16e80c12 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_ip.tcl @@ -0,0 +1,80 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl + +adi_ip_create axi_adrv9001 +adi_ip_files axi_adrv9001 [list \ + "$ad_hdl_dir/library/xilinx/common/ad_serdes_clk.v" \ + "$ad_hdl_dir/library/xilinx/common/ad_mmcm_drp.v" \ + "$ad_hdl_dir/library/xilinx/common/ad_serdes_in.v" \ + "$ad_hdl_dir/library/xilinx/common/ad_serdes_out.v" \ + "$ad_hdl_dir/library/xilinx/common/ad_mul.v" \ + "$ad_hdl_dir/library/common/ad_dds_cordic_pipe.v" \ + "$ad_hdl_dir/library/common/ad_dds_sine_cordic.v" \ + "$ad_hdl_dir/library/common/ad_dds_sine.v" \ + "$ad_hdl_dir/library/common/ad_dds_1.v" \ + "$ad_hdl_dir/library/common/ad_dds_2.v" \ + "$ad_hdl_dir/library/common/ad_dds.v" \ + "$ad_hdl_dir/library/common/ad_datafmt.v" \ + "$ad_hdl_dir/library/common/ad_rst.v" \ + "$ad_hdl_dir/library/common/up_xfer_cntrl.v" \ + "$ad_hdl_dir/library/common/up_xfer_status.v" \ + "$ad_hdl_dir/library/common/up_clock_mon.v" \ + "$ad_hdl_dir/library/common/up_delay_cntrl.v" \ + "$ad_hdl_dir/library/common/up_adc_common.v" \ + "$ad_hdl_dir/library/common/up_adc_channel.v" \ + "$ad_hdl_dir/library/common/up_dac_common.v" \ + "$ad_hdl_dir/library/common/up_dac_channel.v" \ + "$ad_hdl_dir/library/common/ad_pnmon.v" \ + "$ad_hdl_dir/library/common/ad_pngen.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/xilinx/common/up_xfer_cntrl_constr.xdc" \ + "$ad_hdl_dir/library/xilinx/common/ad_rst_constr.xdc" \ + "$ad_hdl_dir/library/xilinx/common/up_xfer_status_constr.xdc" \ + "$ad_hdl_dir/library/xilinx/common/up_clock_mon_constr.xdc" \ + "adrv9001_rx.v" \ + "adrv9001_tx.v" \ + "adrv9001_pack.v" \ + "adrv9001_aligner4.v" \ + "adrv9001_aligner8.v" \ + "adrv9001_rx_link.v" \ + "adrv9001_tx_link.v" \ + "axi_adrv9001_rx.v" \ + "axi_adrv9001_rx_channel.v" \ + "axi_adrv9001_if.v" \ + "axi_adrv9001_tx.v" \ + "axi_adrv9001_tx_channel.v" \ + "axi_adrv9001_core.v" \ + "axi_adrv9001_constr.xdc" \ + "axi_adrv9001.v" ] + +adi_ip_properties axi_adrv9001 + +adi_init_bd_tcl +adi_ip_bd axi_adrv9001 "bd/bd.tcl" + +adi_ip_add_core_dependencies { \ + analog.com:user:util_cdc:1.0 \ +} + +ipx::infer_bus_interface delay_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface adc_1_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface adc_2_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface dac_1_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface dac_2_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface adc_1_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface adc_2_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface dac_1_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] +ipx::infer_bus_interface dac_2_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] + +ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_1_rst -of_objects [ipx::current_core]] +ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_2_rst -of_objects [ipx::current_core]] +ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_1_rst -of_objects [ipx::current_core]] +ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_2_rst -of_objects [ipx::current_core]] + +adi_add_auto_fpga_spec_params +ipx::create_xgui_files [ipx::current_core] + +ipx::save_core [ipx::current_core] + diff --git a/library/axi_adrv9001/axi_adrv9001_rx.v b/library/axi_adrv9001/axi_adrv9001_rx.v new file mode 100644 index 000000000..548d5e117 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_rx.v @@ -0,0 +1,372 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_adrv9001_rx #( + parameter ID = 0, + parameter CMOS_LVDS_N = 0, + parameter COMMON_BASE_ADDR = 'h00, + parameter CHANNEL_BASE_ADDR = 'h01, + parameter MODE_R1 = 1, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter DATAFORMAT_DISABLE = 0, + parameter DCFILTER_DISABLE = 0, + parameter IQCORRECTION_DISABLE = 1 +) ( + // adc interface + output adc_rst, + input adc_clk, + input adc_valid_A, + input [ 15:0] adc_data_i_A, + input [ 15:0] adc_data_q_A, + + input adc_valid_B, + input [ 15:0] adc_data_i_B, + input [ 15:0] adc_data_q_B, + + output adc_single_lane, + output adc_sdr_ddr_n, + output adc_r1_mode, + + // dac loopback interface + input dac_data_valid_A, + input [ 15:0] dac_data_i_A, + input [ 15:0] dac_data_q_A, + + input dac_data_valid_B, + input [ 15:0] dac_data_i_B, + input [ 15:0] dac_data_q_B, + + // dma interface + output adc_valid, + + output adc_enable_i0, + output [ 15:0] adc_data_i0, + output adc_enable_q0, + output [ 15:0] adc_data_q0, + + output adc_enable_i1, + output [ 15:0] adc_data_i1, + output adc_enable_q1, + output [ 15:0] adc_data_q1, + + input adc_dovf, + + // processor interface + input up_rstn, + input up_clk, + input up_wreq, + input [ 13:0] up_waddr, + input [ 31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [ 13:0] up_raddr, + output reg [ 31:0] up_rdata, + output reg up_rack +); + + // configuration settings + + localparam CONFIG = (CMOS_LVDS_N * 128) + + (MODE_R1 * 16) + + (DATAFORMAT_DISABLE * 4) + + (DCFILTER_DISABLE * 2) + + (IQCORRECTION_DISABLE * 1); + + // internal registers + + reg up_status_pn_err = 'd0; + reg up_status_pn_oos = 'd0; + reg up_status_or = 'd0; + + // internal signals + + wire [ 15:0] adc_data_iq_i0_s; + wire [ 15:0] adc_data_iq_q0_s; + wire [ 15:0] adc_data_iq_i1_s; + wire [ 15:0] adc_data_iq_q1_s; + wire [ 4:0] adc_num_lanes; + wire [ 3:0] up_adc_pn_err_s; + wire [ 3:0] up_adc_pn_oos_s; + wire [ 3:0] up_adc_or_s; + wire [ 4:0] up_wack_s; + wire [ 4:0] up_rack_s; + wire [ 31:0] up_rdata_s[0:4]; + wire up_adc_r1_mode; + wire adc_valid_out_i0; + wire adc_valid_out_i1; + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_status_pn_err <= 'd0; + up_status_pn_oos <= 'd0; + up_status_or <= 'd0; + up_wack <= 'd0; + up_rack <= 'd0; + up_rdata <= 'd0; + end else begin + up_status_pn_err <= up_adc_r1_mode ? | up_adc_pn_err_s[1:0] : | up_adc_pn_err_s[3:0]; + up_status_pn_oos <= up_adc_r1_mode ? | up_adc_pn_oos_s[1:0] : | up_adc_pn_oos_s[3:0]; + up_status_or <= | up_adc_or_s; + up_wack <= | up_wack_s; + up_rack <= | up_rack_s; + up_rdata <= up_rdata_s[0] | up_rdata_s[1] | up_rdata_s[2] | + up_rdata_s[3] | up_rdata_s[4]; + end + end + + // channel width is 32 bits + + assign adc_valid = adc_enable_i0 ? adc_valid_out_i0 : adc_valid_out_i1; + + // channel 0 (i) + + axi_adrv9001_rx_channel #( + .Q_OR_I_N (0), + .COMMON_ID (CHANNEL_BASE_ADDR), + .DISABLE (0), + .DATAFORMAT_DISABLE (DATAFORMAT_DISABLE), + .DCFILTER_DISABLE (DCFILTER_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DATA_WIDTH (16)) + i_rx_channel_0 ( + .adc_clk (adc_clk), + .adc_rst (adc_rst), + .adc_valid_in (adc_valid_A), + .adc_data_in (adc_data_i_A[15:0]), + .adc_valid_out (adc_valid_out_i0), + .adc_data_out (adc_data_i0), + .adc_data_iq_in (adc_data_iq_q0_s), + .adc_data_iq_out (adc_data_iq_i0_s), + .adc_enable (adc_enable_i0), + .dac_valid_in (dac_data_valid_A), + .dac_data_in (dac_data_i_A), + .up_adc_pn_err (up_adc_pn_err_s[0]), + .up_adc_pn_oos (up_adc_pn_oos_s[0]), + .up_adc_or (up_adc_or_s[0]), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[0]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[0]), + .up_rack (up_rack_s[0])); + + // channel 1 (q) + + axi_adrv9001_rx_channel #( + .Q_OR_I_N (1), + .COMMON_ID (CHANNEL_BASE_ADDR), + .CHANNEL_ID (1), + .DISABLE (0), + .DATAFORMAT_DISABLE (DATAFORMAT_DISABLE), + .DCFILTER_DISABLE (DCFILTER_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DATA_WIDTH (16)) + i_rx_channel_1 ( + .adc_clk (adc_clk), + .adc_rst (adc_rst), + .adc_valid_in (adc_valid_A), + .adc_data_in (adc_data_q_A[15:0]), + .adc_valid_out (), + .adc_data_out (adc_data_q0), + .adc_data_iq_in (adc_data_iq_i0_s), + .adc_data_iq_out (adc_data_iq_q0_s), + .adc_enable (adc_enable_q0), + .dac_valid_in (dac_data_valid_A), + .dac_data_in (dac_data_q_A), + .up_adc_pn_err (up_adc_pn_err_s[1]), + .up_adc_pn_oos (up_adc_pn_oos_s[1]), + .up_adc_or (up_adc_or_s[1]), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[1]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[1]), + .up_rack (up_rack_s[1])); + + // channel 2 (i) + + axi_adrv9001_rx_channel #( + .Q_OR_I_N (0), + .COMMON_ID (CHANNEL_BASE_ADDR), + .CHANNEL_ID (2), + .DISABLE (MODE_R1), + .DATAFORMAT_DISABLE (DATAFORMAT_DISABLE), + .DCFILTER_DISABLE (DCFILTER_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DATA_WIDTH (16)) + i_rx_channel_2 ( + .adc_clk (adc_clk), + .adc_rst (adc_rst), + .adc_valid_in (adc_valid_B), + .adc_data_in (adc_data_i_B[15:0]), + .adc_valid_out (adc_valid_out_i1), + .adc_data_out (adc_data_i1), + .adc_data_iq_in (adc_data_iq_q1_s), + .adc_data_iq_out (adc_data_iq_i1_s), + .adc_enable (adc_enable_i1), + .dac_valid_in (dac_data_valid_B), + .dac_data_in (dac_data_i_B), + .up_adc_pn_err (up_adc_pn_err_s[2]), + .up_adc_pn_oos (up_adc_pn_oos_s[2]), + .up_adc_or (up_adc_or_s[2]), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[2]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[2]), + .up_rack (up_rack_s[2])); + + // channel 3 (q) + + axi_adrv9001_rx_channel #( + .Q_OR_I_N (1), + .COMMON_ID (CHANNEL_BASE_ADDR), + .CHANNEL_ID (3), + .DISABLE (MODE_R1), + .DATAFORMAT_DISABLE (DATAFORMAT_DISABLE), + .DCFILTER_DISABLE (DCFILTER_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DATA_WIDTH (16)) + i_rx_channel_3 ( + .adc_clk (adc_clk), + .adc_rst (adc_rst), + .adc_valid_in (adc_valid_B), + .adc_data_in (adc_data_q_B[15:0]), + .adc_valid_out (), + .adc_data_out (adc_data_q1), + .adc_data_iq_in (adc_data_iq_i1_s), + .adc_data_iq_out (adc_data_iq_q1_s), + .adc_enable (adc_enable_q1), + .dac_valid_in (dac_data_valid_B), + .dac_data_in (dac_data_q_B), + .up_adc_pn_err (up_adc_pn_err_s[3]), + .up_adc_pn_oos (up_adc_pn_oos_s[3]), + .up_adc_or (up_adc_or_s[3]), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[3]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[3]), + .up_rack (up_rack_s[3])); + + // common processor control + + up_adc_common #( + .ID (ID), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE), + .COMMON_ID (COMMON_BASE_ADDR), + .CONFIG(CONFIG), + .DRP_DISABLE(1), + .USERPORTS_DISABLE(1), + .GPIO_DISABLE(1), + .START_CODE_DISABLE(1)) + i_up_adc_common ( + .mmcm_rst (), + .adc_clk (adc_clk), + .adc_rst (adc_rst), + .adc_r1_mode (adc_r1_mode), + .adc_ddr_edgesel (), + .adc_pin_mode (), + .adc_status (1'b1), + .adc_sync_status (1'd0), + .adc_status_ovf (adc_dovf), + .adc_clk_ratio (32'd1), + .adc_start_code (), + .adc_sref_sync (), + .adc_sync (), + .adc_num_lanes (adc_num_lanes), + .adc_sdr_ddr_n (adc_sdr_ddr_n), + .up_pps_rcounter(32'h0), + .up_pps_status(1'b0), + .up_pps_irq_mask(), + .up_adc_r1_mode (up_adc_r1_mode), + .up_adc_ce (), + .up_status_pn_err (up_status_pn_err), + .up_status_pn_oos (up_status_pn_oos), + .up_status_or (up_status_or), + .up_drp_sel (), + .up_drp_wr (), + .up_drp_addr (), + .up_drp_wdata (), + .up_drp_rdata (32'd0), + .up_drp_ready (1'd0), + .up_drp_locked (1'd1), + .up_usr_chanmax_out (), + .up_usr_chanmax_in (8'd3), + .up_adc_gpio_in (32'd0), + .up_adc_gpio_out (), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[4]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[4]), + .up_rack (up_rack_s[4])); + + assign adc_single_lane = adc_num_lanes[0]; + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/library/axi_adrv9001/axi_adrv9001_rx_channel.v b/library/axi_adrv9001/axi_adrv9001_rx_channel.v new file mode 100644 index 000000000..076ea6848 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_rx_channel.v @@ -0,0 +1,324 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_adrv9001_rx_channel #( + parameter Q_OR_I_N = 0, + parameter COMMON_ID = 0, + parameter CHANNEL_ID = 0, + parameter DISABLE = 0, + parameter DATAFORMAT_DISABLE = 0, + parameter DCFILTER_DISABLE = 0, + parameter IQCORRECTION_DISABLE = 0, + parameter DATA_WIDTH = 16 +) ( + // adc interface + input adc_clk, + input adc_rst, + input adc_valid_in, + input [(DATA_WIDTH-1):0] adc_data_in, + output adc_valid_out, + output [(DATA_WIDTH-1):0] adc_data_out, + input [(DATA_WIDTH-1):0] adc_data_iq_in, + output [(DATA_WIDTH-1):0] adc_data_iq_out, + output adc_enable, + + input dac_valid_in, + input [(DATA_WIDTH-1):0] dac_data_in, + + // channel interface + output up_adc_pn_err, + output up_adc_pn_oos, + output up_adc_or, + + // processor interface + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack +); + + localparam NUM_OF_SAMPLES = DATA_WIDTH/16; + + // internal signals + + wire [(NUM_OF_SAMPLES-1):0] adc_dfmt_valid_s; + wire [(DATA_WIDTH-1):0] adc_dfmt_data_s; + wire [(NUM_OF_SAMPLES-1):0] adc_dcfilter_valid_s; + wire [(DATA_WIDTH-1):0] adc_dcfilter_data_s; + wire [(NUM_OF_SAMPLES-1):0] adc_valid_out_s; + wire adc_pn_err_s; + wire adc_pn_oos_s; + wire [3:0] adc_pnseq_sel; + wire adc_dfmt_se_s; + wire adc_dfmt_type_s; + wire adc_dfmt_enable_s; + wire adc_dcfilt_enb_s; + wire [15:0] adc_dcfilt_offset_s; + wire [15:0] adc_dcfilt_coeff_s; + wire adc_iqcor_enb_s; + wire [15:0] adc_iqcor_coeff_1_s; + wire [15:0] adc_iqcor_coeff_2_s; + wire [(DATA_WIDTH-1):0] adc_data_pn; + wire [(DATA_WIDTH-1):0] pn7_data; + wire [(DATA_WIDTH-1):0] pn15_data; + wire [ 3:0] adc_data_sel_s; + wire [15:0] adc_data_in_s; + wire adc_valid_in_s; + + reg [15:0] full_ramp_counter = 'd0; + + reg adc_valid_in_d = 'h0; + reg adc_valid_in_2d = 'h0; + reg [(DATA_WIDTH-1):0] adc_data_in_d = 'h0; + reg [(DATA_WIDTH-1):0] adc_data_in_2d = 'h0; + + reg dac_valid_in_d = 'h0; + reg dac_valid_in_2d = 'h0; + reg [(DATA_WIDTH-1):0] dac_data_in_d = 'h0; + reg [(DATA_WIDTH-1):0] dac_data_in_2d = 'h0; + + // variables + genvar n; + + // input pipeline stage to protect logic if data comes from an async clock domain + always @(posedge adc_clk) begin + adc_valid_in_d <= adc_valid_in; + adc_valid_in_2d <= adc_valid_in_d; + adc_data_in_d <= adc_data_in; + adc_data_in_2d <= adc_data_in_d; + end + always @(posedge adc_clk) begin + dac_valid_in_d <= dac_valid_in; + dac_valid_in_2d <= dac_valid_in_d; + dac_data_in_d <= dac_data_in; + dac_data_in_2d <= dac_data_in_d; + end + + assign adc_data_in_s = (adc_data_sel_s == 4'h0) ? adc_data_in_2d : dac_data_in_2d; + assign adc_valid_in_s = (adc_data_sel_s == 4'h0) ? adc_valid_in_2d : dac_valid_in_2d; + + // iq correction inputs + + generate + for (n = 0; n < NUM_OF_SAMPLES; n = n + 1) begin: g_datafmt + if (DISABLE == 1 || DATAFORMAT_DISABLE == 1) begin + assign adc_dfmt_valid_s[n] = adc_valid_in_s; + assign adc_dfmt_data_s[((16*n)+15):(16*n)] = adc_data_in_s[((16*n)+15):(16*n)]; + end else begin + ad_datafmt #(.DATA_WIDTH (16)) i_ad_datafmt ( + .clk (adc_clk), + .valid (adc_valid_in_s), + .data (adc_data_in_s[((16*n)+15):(16*n)]), + .valid_out (adc_dfmt_valid_s[n]), + .data_out (adc_dfmt_data_s[((16*n)+15):(16*n)]), + .dfmt_enable (adc_dfmt_enable_s), + .dfmt_type (adc_dfmt_type_s), + .dfmt_se (adc_dfmt_se_s)); + end + end + + for (n = 0; n < NUM_OF_SAMPLES; n = n + 1) begin: g_dcfilter + if (DISABLE == 1 || DCFILTER_DISABLE == 1) begin + assign adc_dcfilter_valid_s[n] = adc_dfmt_valid_s[n]; + assign adc_dcfilter_data_s[((16*n)+15):(16*n)] = adc_dfmt_data_s[((16*n)+15):(16*n)]; + end else begin + ad_dcfilter i_ad_dcfilter ( + .clk (adc_clk), + .valid (adc_dfmt_valid_s[n]), + .data (adc_dfmt_data_s[((16*n)+15):(16*n)]), + .valid_out (adc_dcfilter_valid_s[n]), + .data_out (adc_dcfilter_data_s[((16*n)+15):(16*n)]), + .dcfilt_enb (adc_dcfilt_enb_s), + .dcfilt_coeff (adc_dcfilt_coeff_s), + .dcfilt_offset (adc_dcfilt_offset_s)); + end + end + + assign adc_valid_out = adc_valid_out_s[0]; + assign adc_data_iq_out = adc_dcfilter_data_s; + + for (n = 0; n < NUM_OF_SAMPLES; n = n + 1) begin: g_iqcor + if (DISABLE == 1 || IQCORRECTION_DISABLE == 1) begin + assign adc_valid_out_s[n] = adc_dcfilter_valid_s[n]; + assign adc_data_out[((16*n)+15):(16*n)] = adc_dcfilter_data_s[((16*n)+15):(16*n)]; + end else begin + ad_iqcor #(.Q_OR_I_N (Q_OR_I_N)) i_ad_iqcor ( + .clk (adc_clk), + .valid (adc_dcfilter_valid_s[n]), + .data_in (adc_dcfilter_data_s[((16*n)+15):(16*n)]), + .data_iq (adc_data_iq_in[((16*n)+15):(16*n)]), + .valid_out (adc_valid_out_s[n]), + .data_out (adc_data_out[((16*n)+15):(16*n)]), + .iqcor_enable (adc_iqcor_enb_s), + .iqcor_coeff_1 (adc_iqcor_coeff_1_s), + .iqcor_coeff_2 (adc_iqcor_coeff_2_s)); + end + end + + if (DISABLE == 1) begin + assign adc_enable = 1'b0; + assign up_adc_pn_err = 1'b0; + assign up_adc_pn_oos = 1'b0; + assign up_adc_or = 1'b0; + assign up_wack = 1'b0; + assign up_rdata = 32'b0; + assign up_rack = 1'b0; + end else begin + // pn oos & pn err + + // PN7 x^7 + x^6 + 1 + ad_pngen #( + .POL_MASK ( (1<<7) | (1<<6) ), + .POL_W (7), + .DW (16) + ) PN7_gen ( + .clk (adc_clk), + .reset (adc_rst), + .clk_en (adc_valid_in_s), + .pn_init (adc_pn_oos_s), + .pn_data_in (adc_data_in_s), + .pn_data_out (pn7_data) + ); + + // PN15 x^15 + x^14 + 1 + ad_pngen #( + .POL_MASK ( (1<<15) | (1<<14) ), + .POL_W (15), + .DW (16) + ) PN15_gen ( + .clk (adc_clk), + .reset (adc_rst), + .clk_en (adc_valid_in_s), + .pn_init (adc_pn_oos_s), + .pn_data_in (adc_data_in_s), + .pn_data_out (pn15_data) + ); + + // reference nibble ramp and full ramp generator + always @(posedge adc_clk) begin + if (adc_pn_oos_s) begin + full_ramp_counter <= adc_data_in_s + 16'd1; + end else if (adc_valid_in_s) begin + full_ramp_counter <= full_ramp_counter + 16'd1; + end + end + + assign adc_data_pn = adc_pnseq_sel == 4'd4 ? pn7_data : + adc_pnseq_sel == 4'd5 ? pn15_data : + adc_pnseq_sel == 4'd10 ? {4{full_ramp_counter[3:0]}} : + adc_pnseq_sel == 4'd11 ? full_ramp_counter : 'h0; + + ad_pnmon #( + .DATA_WIDTH (DATA_WIDTH), + .OOS_THRESHOLD (8), + .ALLOW_ZERO_MASKING(1) + ) i_pnmon ( + .adc_clk (adc_clk), + .adc_valid_in (adc_valid_in_s), + .adc_data_in (adc_data_in_s), + .adc_data_pn (adc_data_pn), + .adc_pattern_has_zero (adc_pnseq_sel[3]), + .adc_pn_oos (adc_pn_oos_s), + .adc_pn_err (adc_pn_err_s) + ); + + up_adc_channel #( + .COMMON_ID (COMMON_ID), + .CHANNEL_ID (CHANNEL_ID), + .USERPORTS_DISABLE(1), + .DATAFORMAT_DISABLE(DATAFORMAT_DISABLE), + .DCFILTER_DISABLE(DCFILTER_DISABLE), + .IQCORRECTION_DISABLE(IQCORRECTION_DISABLE)) + i_up_adc_channel ( + .adc_clk (adc_clk), + .adc_rst (adc_rst), + .adc_enable (adc_enable), + .adc_iqcor_enb (adc_iqcor_enb_s), + .adc_dcfilt_enb (adc_dcfilt_enb_s), + .adc_dfmt_se (adc_dfmt_se_s), + .adc_dfmt_type (adc_dfmt_type_s), + .adc_dfmt_enable (adc_dfmt_enable_s), + .adc_dcfilt_offset (adc_dcfilt_offset_s), + .adc_dcfilt_coeff (adc_dcfilt_coeff_s), + .adc_iqcor_coeff_1 (adc_iqcor_coeff_1_s), + .adc_iqcor_coeff_2 (adc_iqcor_coeff_2_s), + .adc_pnseq_sel (adc_pnseq_sel), + .adc_data_sel (adc_data_sel_s), + .adc_pn_err (adc_pn_err_s), + .adc_pn_oos (adc_pn_oos_s), + .adc_or (1'd0), + .up_adc_pn_err (up_adc_pn_err), + .up_adc_pn_oos (up_adc_pn_oos), + .up_adc_or (up_adc_or), + .up_usr_datatype_be (), + .up_usr_datatype_signed (), + .up_usr_datatype_shift (), + .up_usr_datatype_total_bits (), + .up_usr_datatype_bits (), + .up_usr_decimation_m (), + .up_usr_decimation_n (), + .adc_usr_datatype_be (1'b0), + .adc_usr_datatype_signed (1'b1), + .adc_usr_datatype_shift (8'd0), + .adc_usr_datatype_total_bits (8'd16), + .adc_usr_datatype_bits (8'd16), + .adc_usr_decimation_m (16'd1), + .adc_usr_decimation_n (16'd1), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata), + .up_rack (up_rack)); + end + endgenerate + +endmodule + +// *************************************************************************** +// *************************************************************************** + diff --git a/library/axi_adrv9001/axi_adrv9001_tx.v b/library/axi_adrv9001/axi_adrv9001_tx.v new file mode 100644 index 000000000..c23f65e16 --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_tx.v @@ -0,0 +1,381 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_adrv9001_tx #( + parameter ID = 0, + parameter CMOS_LVDS_N = 0, + parameter COMMON_BASE_ADDR = 'h10, + parameter CHANNEL_BASE_ADDR = 'h11, + parameter MODE_R1 = 1, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter DISABLE = 0, + parameter DDS_DISABLE = 0, + parameter IQCORRECTION_DISABLE = 0, + parameter DAC_DDS_TYPE = 1, + parameter DAC_DDS_CORDIC_DW = 20, + parameter DAC_DDS_CORDIC_PHASE_DW = 18 +) ( + // dac interface + output dac_rst, + input dac_clk, + output dac_data_valid_A, + output [15:0] dac_data_i_A, + output [15:0] dac_data_q_A, + + output dac_data_valid_B, + output [15:0] dac_data_i_B, + output [15:0] dac_data_q_B, + + output dac_single_lane, + output dac_sdr_ddr_n, + output dac_r1_mode, + + // master/slave + input dac_sync_in, + output dac_sync_out, + + // dma interface + output dac_valid, + + output dac_enable_i0, + input [ 15:0] dac_data_i0, + output dac_enable_q0, + input [ 15:0] dac_data_q0, + + output dac_enable_i1, + input [ 15:0] dac_data_i1, + output dac_enable_q1, + input [ 15:0] dac_data_q1, + + input dac_dunf, + + // processor interface + input up_rstn, + input up_clk, + input up_wreq, + input [ 13:0] up_waddr, + input [ 31:0] up_wdata, + output reg up_wack, + input up_rreq, + input [ 13:0] up_raddr, + output reg [ 31:0] up_rdata, + output reg up_rack +); + + // configuration settings + + localparam CONFIG = (CMOS_LVDS_N * 128) + + (MODE_R1 * 16) + + (DDS_DISABLE * 64) + + (IQCORRECTION_DISABLE * 1); + + // internal registers + + reg dac_data_sync = 'd0; + reg [15:0] dac_rate_cnt = 'd0; + reg dac_valid_int = 'd0; + + // internal signals + + wire dac_data_sync_s; + wire [ 15:0] dac_data_iq_i0_s; + wire [ 15:0] dac_data_iq_q0_s; + wire [ 15:0] dac_data_iq_i1_s; + wire [ 15:0] dac_data_iq_q1_s; + wire dac_dds_format_s; + wire [ 15:0] dac_datarate_s; + wire [4:0] dac_num_lanes; + wire [ 4:0] up_wack_s; + wire [ 4:0] up_rack_s; + wire [ 31:0] up_rdata_s[0:4]; + + // master/slave + + assign dac_data_sync_s = (ID == 0) ? dac_sync_out : dac_sync_in; + + always @(posedge dac_clk) begin + dac_data_sync <= dac_data_sync_s; + end + + // rate counters and data sync signals + + always @(posedge dac_clk) begin + if (dac_rst == 1'b1) begin + dac_rate_cnt <= 16'b0; + end else begin + if ((dac_data_sync == 1'b1) || (dac_rate_cnt == 16'd0)) begin + dac_rate_cnt <= dac_datarate_s; + end else begin + dac_rate_cnt <= dac_rate_cnt - 1'b1; + end + end + end + + // dma interface + + assign dac_data_valid_A = dac_valid_int; + assign dac_data_valid_B = dac_valid_int; + + always @(posedge dac_clk) begin + if (dac_rst == 1'b1) begin + dac_valid_int <= 1'b0; + end else begin + dac_valid_int <= (dac_rate_cnt == 16'd0) ? 1'b1 : 1'b0; + end + end + + // processor read interface + + always @(negedge up_rstn or posedge up_clk) begin + if (up_rstn == 0) begin + up_wack <= 'd0; + up_rack <= 'd0; + up_rdata <= 'd0; + end else begin + up_wack <= | up_wack_s; + up_rack <= | up_rack_s; + up_rdata <= up_rdata_s[0] | up_rdata_s[1] | up_rdata_s[2] | + up_rdata_s[3] | up_rdata_s[4]; + end + end + + // dac channel 0 + + axi_adrv9001_tx_channel #( + .CHANNEL_ID (0), + .COMMON_ID (CHANNEL_BASE_ADDR), + .Q_OR_I_N (0), + .DISABLE (DISABLE), + .DDS_DISABLE (DDS_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DAC_DDS_TYPE (DAC_DDS_TYPE), + .DAC_DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), + .DAC_DDS_CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW)) + i_tx_channel_0 ( + .dac_clk (dac_clk), + .dac_rst (dac_rst), + .dac_data_in_req (dac_valid), + .dac_data_in (dac_data_i0), + .dac_data_out_req (dac_data_valid_A), + .dac_data_out (dac_data_i_A[15:0]), + .dac_data_iq_in (dac_data_iq_q0_s), + .dac_data_iq_out (dac_data_iq_i0_s), + .dac_enable (dac_enable_i0), + .dac_data_sync (dac_data_sync), + .dac_dds_format (dac_dds_format_s), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[0]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[0]), + .up_rack (up_rack_s[0])); + + // dac channel 1 + + axi_adrv9001_tx_channel #( + .CHANNEL_ID (1), + .COMMON_ID (CHANNEL_BASE_ADDR), + .Q_OR_I_N (1), + .DISABLE (DISABLE), + .DDS_DISABLE (DDS_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DAC_DDS_TYPE (DAC_DDS_TYPE), + .DAC_DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), + .DAC_DDS_CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW)) + i_tx_channel_1 ( + .dac_clk (dac_clk), + .dac_rst (dac_rst), + .dac_data_in_req (), + .dac_data_in (dac_data_q0), + .dac_data_out_req (dac_data_valid_A), + .dac_data_out (dac_data_q_A[15:0]), + .dac_data_iq_in (dac_data_iq_i0_s), + .dac_data_iq_out (dac_data_iq_q0_s), + .dac_enable (dac_enable_q0), + .dac_data_sync (dac_data_sync), + .dac_dds_format (dac_dds_format_s), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[1]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[1]), + .up_rack (up_rack_s[1])); + + // dac channel 2 - disabled in 1R1T mode + + axi_adrv9001_tx_channel #( + .CHANNEL_ID (2), + .COMMON_ID (CHANNEL_BASE_ADDR), + .Q_OR_I_N (0), + .DISABLE (MODE_R1), + .DDS_DISABLE (DDS_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DAC_DDS_TYPE (DAC_DDS_TYPE), + .DAC_DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), + .DAC_DDS_CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW)) + i_tx_channel_2 ( + .dac_clk (dac_clk), + .dac_rst (dac_rst), + .dac_data_in_req (), + .dac_data_in (dac_data_i1), + .dac_data_out_req (dac_data_valid_B), + .dac_data_out (dac_data_i_B[15:0]), + .dac_data_iq_in (dac_data_iq_q1_s), + .dac_data_iq_out (dac_data_iq_i1_s), + .dac_enable (dac_enable_i1), + .dac_data_sync (dac_data_sync), + .dac_dds_format (dac_dds_format_s), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[2]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[2]), + .up_rack (up_rack_s[2])); + + // dac channel 3 - disabled in 1R1T mode + + axi_adrv9001_tx_channel #( + .CHANNEL_ID (3), + .COMMON_ID (CHANNEL_BASE_ADDR), + .Q_OR_I_N (1), + .DISABLE (MODE_R1), + .DDS_DISABLE (DDS_DISABLE), + .IQCORRECTION_DISABLE (IQCORRECTION_DISABLE), + .DAC_DDS_TYPE (DAC_DDS_TYPE), + .DAC_DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), + .DAC_DDS_CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW)) + i_tx_channel_3 ( + .dac_clk (dac_clk), + .dac_rst (dac_rst), + .dac_data_in_req (), + .dac_data_in (dac_data_q0), + .dac_data_out_req (dac_data_valid_B), + .dac_data_out (dac_data_q_B[15:0]), + .dac_data_iq_in (dac_data_iq_i1_s), + .dac_data_iq_out (dac_data_iq_q1_s), + .dac_enable (dac_enable_q1), + .dac_data_sync (dac_data_sync), + .dac_dds_format (dac_dds_format_s), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[3]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[3]), + .up_rack (up_rack_s[3])); + + // dac common processor interface + + up_dac_common #( + .ID (ID), + .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), + .FPGA_FAMILY (FPGA_FAMILY), + .SPEED_GRADE (SPEED_GRADE), + .DEV_PACKAGE (DEV_PACKAGE), + .CONFIG(CONFIG), + .CLK_EDGE_SEL(0), + .COMMON_ID(COMMON_BASE_ADDR), + .DRP_DISABLE(1), + .USERPORTS_DISABLE(1), + .GPIO_DISABLE(1)) + i_up_dac_common ( + .mmcm_rst (), + .dac_clk (dac_clk), + .dac_rst (dac_rst), + .dac_num_lanes (dac_num_lanes), + .dac_sdr_ddr_n (dac_sdr_ddr_n), + .dac_sync (dac_sync_out), + .dac_frame (), + .dac_clksel (), + .dac_par_type (), + .dac_par_enb (), + .dac_r1_mode (dac_r1_mode), + .dac_datafmt (dac_dds_format_s), + .dac_datarate (dac_datarate_s), + .dac_status (1'b1), + .dac_status_unf (dac_dunf), + .dac_clk_ratio (32'd2), + .up_dac_ce (), + .up_pps_rcounter(32'h0), + .up_pps_status(1'b0), + .up_pps_irq_mask(), + .up_drp_sel (), + .up_drp_wr (), + .up_drp_addr (), + .up_drp_wdata (), + .up_drp_rdata (32'd0), + .up_drp_ready (1'd0), + .up_drp_locked (1'd1), + .up_usr_chanmax (), + .dac_usr_chanmax (8'd3), + .up_dac_gpio_in (32'd0), + .up_dac_gpio_out (), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack_s[4]), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata_s[4]), + .up_rack (up_rack_s[4])); + + assign dac_single_lane = dac_num_lanes[0]; + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/library/axi_adrv9001/axi_adrv9001_tx_channel.v b/library/axi_adrv9001/axi_adrv9001_tx_channel.v new file mode 100644 index 000000000..141b16a3f --- /dev/null +++ b/library/axi_adrv9001/axi_adrv9001_tx_channel.v @@ -0,0 +1,251 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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_adrv9001_tx_channel #( + parameter COMMON_ID = 6'h11, + parameter CHANNEL_ID = 32'h0, + parameter Q_OR_I_N = 0, + parameter DISABLE = 0, + parameter DDS_DISABLE = 0, + parameter IQCORRECTION_DISABLE = 0, + parameter DAC_DDS_TYPE = 1, + parameter DAC_DDS_CORDIC_DW = 20, + parameter DAC_DDS_CORDIC_PHASE_DW = 18 +) ( + // dac interface + input dac_clk, + input dac_rst, + output dac_data_in_req, + input [15:0] dac_data_in, + input dac_data_out_req, + output [15:0] dac_data_out, + input [15:0] dac_data_iq_in, + output reg [15:0] dac_data_iq_out, + + // processor interface + output reg dac_enable = 1'b0, + input dac_data_sync, + input dac_dds_format, + + // bus interface + input up_rstn, + input up_clk, + input up_wreq, + input [13:0] up_waddr, + input [31:0] up_wdata, + output up_wack, + input up_rreq, + input [13:0] up_raddr, + output [31:0] up_rdata, + output up_rack +); + + // internal registers + + reg [15:0] dac_pat_data = 'd0; + reg [15:0] full_ramp_counter = 'd0; + + // internal signals + + wire [15:0] dac_dds_data_s; + wire [15:0] dac_dds_scale_1_s; + wire [15:0] dac_dds_init_1_s; + wire [15:0] dac_dds_incr_1_s; + wire [15:0] dac_dds_scale_2_s; + wire [15:0] dac_dds_init_2_s; + wire [15:0] dac_dds_incr_2_s; + wire [15:0] dac_pat_data_1_s; + wire [15:0] dac_pat_data_2_s; + wire [ 3:0] dac_data_sel_s; + wire dac_iqcor_enb_s; + wire [15:0] dac_iqcor_coeff_1_s; + wire [15:0] dac_iqcor_coeff_2_s; + wire [15:0] pn7_data; + wire [15:0] pn15_data; + // dac iq correction + + generate + if (DISABLE == 1 || IQCORRECTION_DISABLE == 1) begin + + assign dac_data_out = dac_data_iq_out; + assign dac_data_in_req = dac_data_out_req; + + end else begin + ad_iqcor #(.Q_OR_I_N (Q_OR_I_N)) i_ad_iqcor_0 ( + .clk (dac_clk), + .valid (dac_data_out_req), + .data_in (dac_data_iq_out[15:0]), + .data_iq (dac_data_iq_in[15:0]), + .valid_out (dac_data_in_req), + .data_out (dac_data_out[15:0]), + .iqcor_enable (dac_iqcor_enb_s), + .iqcor_coeff_1 (dac_iqcor_coeff_1_s), + .iqcor_coeff_2 (dac_iqcor_coeff_2_s)); + end + + if (DISABLE == 1) begin + assign up_wack = 1'b0; + assign up_rdata = 32'b0; + assign up_rack = 1'b0; + end else begin + + // PN7 x^7 + x^6 + 1 + ad_pngen #( + .POL_MASK ((1<<7) | (1<<6)), + .POL_W (7), + .DW (16) + ) PN7_gen ( + .clk (dac_clk), + .reset (dac_rst), + .clk_en (dac_data_in_req), + .pn_init (1'b0), + .pn_data_out (pn7_data) + ); + + // PN15 x^15 + x^14 + 1 + ad_pngen #( + .POL_MASK ((1<<15) | (1<<14)), + .POL_W (15), + .DW (16) + ) PN15_gen ( + .clk (dac_clk), + .reset (dac_rst), + .clk_en (dac_data_in_req), + .pn_init (1'b0), + .pn_data_out (pn15_data) + ); + + // full ramp generator + always @(posedge dac_clk) begin + if (dac_data_sync) begin + full_ramp_counter <= 'h0; + end else if (dac_data_in_req) begin + full_ramp_counter <= full_ramp_counter + 16'd1; + end + end + + // dac mux + + always @(posedge dac_clk) begin + dac_enable <= (dac_data_sel_s == 4'h2) ? 1'b1 : 1'b0; + case (dac_data_sel_s) + 4'hB: dac_data_iq_out <= full_ramp_counter; // full ramp + 4'hA: dac_data_iq_out <= {4{full_ramp_counter[3:0]}}; // nibble ramp + 4'h7: dac_data_iq_out <= pn15_data; + 4'h6: dac_data_iq_out <= pn7_data; + 4'h3: dac_data_iq_out <= 16'd0; + 4'h2: dac_data_iq_out <= dac_data_in; + 4'h1: dac_data_iq_out <= dac_pat_data_1_s; + default: dac_data_iq_out <= dac_dds_data_s; + endcase + end + + // dds + + ad_dds #( + .DISABLE (DDS_DISABLE), + .DDS_DW (16), + .PHASE_DW (16), + .DDS_TYPE (DAC_DDS_TYPE), + .CORDIC_DW (DAC_DDS_CORDIC_DW), + .CORDIC_PHASE_DW (DAC_DDS_CORDIC_PHASE_DW), + .CLK_RATIO (1)) + i_dds ( + .clk (dac_clk), + .dac_dds_format (dac_dds_format), + .dac_data_sync (dac_data_sync), + .dac_valid (dac_data_out_req), + .tone_1_scale (dac_dds_scale_1_s), + .tone_2_scale (dac_dds_scale_2_s), + .tone_1_init_offset (dac_dds_init_1_s), + .tone_2_init_offset (dac_dds_init_2_s), + .tone_1_freq_word (dac_dds_incr_1_s), + .tone_2_freq_word (dac_dds_incr_2_s), + .dac_dds_data (dac_dds_data_s)); + + // single channel processor + + up_dac_channel #( + .COMMON_ID(COMMON_ID), + .CHANNEL_ID (CHANNEL_ID), + .DDS_DISABLE(DDS_DISABLE), + .USERPORTS_DISABLE(1), + .IQCORRECTION_DISABLE(IQCORRECTION_DISABLE)) + i_up_dac_channel ( + .dac_clk (dac_clk), + .dac_rst (dac_rst), + .dac_dds_scale_1 (dac_dds_scale_1_s), + .dac_dds_init_1 (dac_dds_init_1_s), + .dac_dds_incr_1 (dac_dds_incr_1_s), + .dac_dds_scale_2 (dac_dds_scale_2_s), + .dac_dds_init_2 (dac_dds_init_2_s), + .dac_dds_incr_2 (dac_dds_incr_2_s), + .dac_pat_data_1 (dac_pat_data_1_s), + .dac_pat_data_2 (dac_pat_data_2_s), + .dac_data_sel (dac_data_sel_s), + .dac_iq_mode (), + .dac_iqcor_enb (dac_iqcor_enb_s), + .dac_iqcor_coeff_1 (dac_iqcor_coeff_1_s), + .dac_iqcor_coeff_2 (dac_iqcor_coeff_2_s), + .up_usr_datatype_be (), + .up_usr_datatype_signed (), + .up_usr_datatype_shift (), + .up_usr_datatype_total_bits (), + .up_usr_datatype_bits (), + .up_usr_interpolation_m (), + .up_usr_interpolation_n (), + .dac_usr_datatype_be (1'b0), + .dac_usr_datatype_signed (1'b1), + .dac_usr_datatype_shift (8'd0), + .dac_usr_datatype_total_bits (8'd16), + .dac_usr_datatype_bits (8'd16), + .dac_usr_interpolation_m (16'd1), + .dac_usr_interpolation_n (16'd1), + .up_rstn (up_rstn), + .up_clk (up_clk), + .up_wreq (up_wreq), + .up_waddr (up_waddr), + .up_wdata (up_wdata), + .up_wack (up_wack), + .up_rreq (up_rreq), + .up_raddr (up_raddr), + .up_rdata (up_rdata), + .up_rack (up_rack)); + end + endgenerate + +endmodule diff --git a/library/axi_adrv9001/intel/adrv9001_rx.v b/library/axi_adrv9001/intel/adrv9001_rx.v new file mode 100644 index 000000000..da507d828 --- /dev/null +++ b/library/axi_adrv9001/intel/adrv9001_rx.v @@ -0,0 +1,150 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_rx #( + parameter CMOS_LVDS_N = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter NUM_LANES = 3, + parameter DRP_WIDTH = 5, + parameter IODELAY_CTRL = 0, + parameter IO_DELAY_GROUP = "dev_if_delay_group" +) ( + // device interface + input rx_dclk_in_n_NC, + input rx_dclk_in_p_dclk_in, + input rx_idata_in_n_idata0, + input rx_idata_in_p_idata1, + input rx_qdata_in_n_qdata2, + input rx_qdata_in_p_qdata3, + input rx_strobe_in_n_NC, + input rx_strobe_in_p_strobe_in, + + // internal reset and clocks + input adc_rst, + output adc_clk, + output adc_clk_div, + output [7:0] adc_data_0, + output [7:0] adc_data_1, + output [7:0] adc_data_2, + output [7:0] adc_data_3, + output [7:0] adc_data_strobe, + output adc_valid, + + // delay interface (for IDELAY macros) + input up_clk, + input [NUM_LANES-1:0] up_adc_dld, + input [DRP_WIDTH*NUM_LANES-1:0] up_adc_dwdata, + output [DRP_WIDTH*NUM_LANES-1:0] up_adc_drdata, + input delay_clk, + input delay_rst, + output delay_locked, + + input mssi_sync, + output ssi_sync_out, + input ssi_sync_in, + output ssi_rst +); + + reg [3:0] valid_gen = 4'b0001; + + wire [4:0] gpio_in; + wire [39:0] deser_out; + + periphery_clk_buf rx_clk_buf( + .inclk (rx_dclk_in_p_dclk_in), + .outclk (rx_clk) + ); + + assign gpio_in = {rx_strobe_in_p_strobe_in, + rx_qdata_in_p_qdata3, + rx_qdata_in_n_qdata2, + rx_idata_in_p_idata1, + rx_idata_in_n_idata0}; + + assign {adc_data_strobe, + adc_data_3, + adc_data_2, + adc_data_1, + adc_data_0} = deser_out; + + genvar i; + generate + for (i = 0; i <= 4; i = i + 1) begin: g_ddr_i + + reg [7:0] shift_reg = 8'b0; + wire [1:0] gpio_out; + + // DDR input + adrv9001_gpio_in gpio_rx_in ( + .ck (rx_clk), + .dout (gpio_out), + .pad_in (gpio_in[i]) + ); + + // Temporal ordering: + // MSB - oldest received bit; + // LSB - newest received bit; + always @(posedge rx_clk) begin + shift_reg <= {shift_reg[5:0],gpio_out[0],gpio_out[1]}; + end + + assign deser_out[i*8+:8] = shift_reg; + + end + endgenerate + + always @(posedge rx_clk) begin + if (adc_rst) begin + valid_gen <= 4'b0001; + end else begin + valid_gen <= {valid_gen[2:0],valid_gen[3]}; + end + end + + assign adc_valid = valid_gen[3]; + // No clock divider, qualifier used instead + assign adc_clk_div = rx_clk; + assign adc_clk = rx_clk; + + // Drive unused signals + assign delay_locked = 'b0; + assign up_adc_drdata = 'b0; + + assign ssi_sync_out = 'b0; + assign ssi_rst = 'b0; + +endmodule diff --git a/library/axi_adrv9001/intel/adrv9001_tx.v b/library/axi_adrv9001/intel/adrv9001_tx.v new file mode 100644 index 000000000..4df9ddeee --- /dev/null +++ b/library/axi_adrv9001/intel/adrv9001_tx.v @@ -0,0 +1,135 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2020 (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 responsibilities 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 adrv9001_tx #( + parameter CMOS_LVDS_N = 0, + parameter NUM_LANES = 4, + parameter FPGA_TECHNOLOGY = 0, + parameter USE_RX_CLK_FOR_TX = 0 +) ( + input ref_clk, + input up_clk, + + input mssi_sync, + input tx_output_enable, + + // physical interface (transmit) + output tx_dclk_out_n_NC, + output tx_dclk_out_p_dclk_out, + input tx_dclk_in_n_NC, + input tx_dclk_in_p_dclk_in, + output tx_idata_out_n_idata0, + output tx_idata_out_p_idata1, + output tx_qdata_out_n_qdata2, + output tx_qdata_out_p_qdata3, + output tx_strobe_out_n_NC, + output tx_strobe_out_p_strobe_out, + + input rx_clk_div, + input rx_clk, + input rx_ssi_rst, + + // internal resets and clocks + + input dac_rst, + output dac_clk_div, + + input [7:0] dac_data_0, + input [7:0] dac_data_1, + input [7:0] dac_data_2, + input [7:0] dac_data_3, + input [7:0] dac_data_strb, + input [7:0] dac_data_clk, + input dac_data_valid +); + + wire [6*8-1:0] serdes_in; + wire [5:0] gpio_out; + + periphery_clk_buf tx_clk_buf( + .inclk (tx_dclk_in_p_dclk_in), + .outclk (tx_clk) + ); + + assign serdes_in = {dac_data_clk, + dac_data_strb, + dac_data_3, + dac_data_2, + dac_data_1, + dac_data_0}; + + assign {tx_dclk_out_p_dclk_out, + tx_strobe_out_p_strobe_out, + tx_qdata_out_p_qdata3, + tx_qdata_out_n_qdata2, + tx_idata_out_p_idata1, + tx_idata_out_n_idata0} = gpio_out; + + genvar i; + generate + for (i = 0; i <= 5; i = i + 1) begin: g_ddr_o + + reg [7:0] shift_reg = 8'b0; + wire [1:0] gpio_in; + + // DDR output + adrv9001_gpio_out gpio_tx_out ( + .ck(tx_clk), + .din(gpio_in), + .pad_out(gpio_out[i]) + ); + + always @(posedge tx_clk) begin + if (dac_data_valid) begin + shift_reg <= serdes_in[i*8+:8]; + end else begin + shift_reg <= {shift_reg[5:0],2'b0}; + end + end + // Order of transmission: + // gpio_in[0] - first + // gpio_in[1] - last + assign gpio_in = {shift_reg[6],shift_reg[7]}; + + end + endgenerate + + // No clock divider, qualifier used instead + assign dac_clk_div = tx_clk; + assign dac_clk = tx_clk; + +endmodule