From 77067e8ad5a979670f947a1dc5368d06c4d4a15a Mon Sep 17 00:00:00 2001 From: PopPaul2021 Date: Thu, 16 Feb 2023 11:41:43 +0200 Subject: [PATCH] library/axi_ad3552r: Added interface IP for Xilinx projects. The custom interface IP for AD3552R DAC has more operation capabilities: - 8b register read/write SDR/DDR - 16b register read/write SDR/DDR - data stream SDR/DDR - selectable input source : DMA/ADC/TEST_RAMP - the reference clock for the IP (clk_in) has a 120MHz frequency - data out clock(SCLK) has 15MHz(clk_in/8) frequency when the converter is configured and 60MHz(clk_in/2) when the converter is in stream mode --- library/Makefile | 2 + library/axi_ad3552r/Makefile | 29 +++ library/axi_ad3552r/axi_ad3552r.v | 212 ++++++++++++++++ library/axi_ad3552r/axi_ad3552r_channel.v | 163 +++++++++++++ library/axi_ad3552r/axi_ad3552r_core.v | 247 +++++++++++++++++++ library/axi_ad3552r/axi_ad3552r_if.v | 285 ++++++++++++++++++++++ library/axi_ad3552r/axi_ad3552r_if_tb | 8 + library/axi_ad3552r/axi_ad3552r_if_tb.v | 244 ++++++++++++++++++ library/axi_ad3552r/axi_ad3552r_ip.tcl | 40 +++ library/axi_ad3552r/tb_base.v | 76 ++++++ 10 files changed, 1306 insertions(+) create mode 100755 library/axi_ad3552r/Makefile create mode 100755 library/axi_ad3552r/axi_ad3552r.v create mode 100755 library/axi_ad3552r/axi_ad3552r_channel.v create mode 100755 library/axi_ad3552r/axi_ad3552r_core.v create mode 100755 library/axi_ad3552r/axi_ad3552r_if.v create mode 100755 library/axi_ad3552r/axi_ad3552r_if_tb create mode 100755 library/axi_ad3552r/axi_ad3552r_if_tb.v create mode 100755 library/axi_ad3552r/axi_ad3552r_ip.tcl create mode 100755 library/axi_ad3552r/tb_base.v diff --git a/library/Makefile b/library/Makefile index d98dc2924c..65234a0d46 100644 --- a/library/Makefile +++ b/library/Makefile @@ -14,6 +14,7 @@ all: lib clean: $(MAKE) -C ad463x_data_capture clean + $(MAKE) -C axi_ad3552r clean $(MAKE) -C axi_ad5766 clean $(MAKE) -C axi_ad7606x clean $(MAKE) -C axi_ad7616 clean @@ -136,6 +137,7 @@ clean-all:clean lib: $(MAKE) -C ad463x_data_capture + $(MAKE) -C axi_ad3552r $(MAKE) -C axi_ad5766 $(MAKE) -C axi_ad7606x $(MAKE) -C axi_ad7616 diff --git a/library/axi_ad3552r/Makefile b/library/axi_ad3552r/Makefile new file mode 100755 index 0000000000..b9f6511858 --- /dev/null +++ b/library/axi_ad3552r/Makefile @@ -0,0 +1,29 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_ad3552r + +GENERIC_DEPS += ../common/ad_iobuf.v +GENERIC_DEPS += ../common/ad_rst.v +GENERIC_DEPS += ../common/up_axi.v +GENERIC_DEPS += ../common/up_clock_mon.v +GENERIC_DEPS += ../common/up_dac_channel.v +GENERIC_DEPS += ../common/up_dac_common.v +GENERIC_DEPS += ../common/up_xfer_cntrl.v +GENERIC_DEPS += ../common/up_xfer_status.v +GENERIC_DEPS += axi_ad3552r.v +GENERIC_DEPS += axi_ad3552r_channel.v +GENERIC_DEPS += axi_ad3552r_core.v +GENERIC_DEPS += axi_ad3552r_if.v + +XILINX_DEPS += ../xilinx/common/ad_mul.v +XILINX_DEPS += ../xilinx/common/ad_rst_constr.xdc +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_ad3552r_ip.tcl + +include ../scripts/library.mk diff --git a/library/axi_ad3552r/axi_ad3552r.v b/library/axi_ad3552r/axi_ad3552r.v new file mode 100755 index 0000000000..ebb2106e89 --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r.v @@ -0,0 +1,212 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2023 (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_ad3552r #( + + parameter ID = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0 +) ( + + // DAC INTERFACE + + input dac_clk, + + input [31:0] dma_data, + input valid_in_dma, + output dac_data_ready, + + input [15:0] data_in_a, + input [15:0] data_in_b, + input valid_in_a, + input valid_in_b, + + output dac_sclk, + output dac_csn, + input [ 3:0] sdio_i, + output [ 3:0] sdio_o, + output sdio_t, + + // axi interface + + input s_axi_aclk, + input s_axi_aresetn, + input s_axi_awvalid, + input [15:0] s_axi_awaddr, + input [ 2:0] s_axi_awprot, + output s_axi_awready, + input s_axi_wvalid, + input [31:0] s_axi_wdata, + input [ 3:0] s_axi_wstrb, + output s_axi_wready, + output s_axi_bvalid, + output [ 1:0] s_axi_bresp, + input s_axi_bready, + input s_axi_arvalid, + input [15:0] s_axi_araddr, + input [ 2:0] s_axi_arprot, + output s_axi_arready, + output s_axi_rvalid, + output [ 1:0] s_axi_rresp, + output [31:0] s_axi_rdata, + input s_axi_rready +); + + // internal clocks and resets + + wire dac_rst_s; + wire up_clk; + wire up_rstn; + + // internal signals + + wire up_wreq_s; + wire [13:0] up_waddr_s; + wire [31:0] up_wdata_s; + wire up_wack_s; + wire up_rreq_s; + wire [13:0] up_raddr_s; + wire [31:0] up_rdata_s; + wire up_rack_s; + + wire [ 7:0] address; + wire [23:0] data_read; + wire [23:0] data_write; + wire ddr_sdr_n; + wire symb_8_16b; + wire transfer_data; + wire stream; + wire [31:0] dac_data; + wire dac_valid; + wire if_busy; + // signal name changes + + assign up_clk = s_axi_aclk; + assign up_rstn = s_axi_aresetn; + + // device interface + axi_ad3552r_if axi_ad3552r_interface ( + .clk_in(dac_clk), + .reset_in(dac_rst_s), + .dac_data(dac_data), + .dac_data_valid(dac_valid), + .dac_data_ready(dac_data_ready), + .address(address), + .data_read(data_read), + .data_write(data_write), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(symb_8_16b), + .transfer_data(transfer_data), + .stream(stream), + .if_busy(if_busy), + .sclk(dac_sclk), + .csn(dac_csn), + .sdio_i(sdio_i), + .sdio_o(sdio_o), + .sdio_t(sdio_t)); + + // core + axi_ad3552r_core #( + .ID(ID), + .FPGA_TECHNOLOGY(FPGA_TECHNOLOGY), + .FPGA_FAMILY(FPGA_FAMILY), + .SPEED_GRADE(SPEED_GRADE), + .DEV_PACKAGE(DEV_PACKAGE) + ) axi_ad3552r_up_core ( + .dac_clk(dac_clk), + .dac_rst(dac_rst_s), + .adc_data_in_a(data_in_a), + .adc_data_in_b(data_in_b), + .dma_data(dma_data), + .adc_valid_in_a(valid_in_a), + .adc_valid_in_b(valid_in_b), + .valid_in_dma(valid_in_dma), + .dac_data_ready(dac_data_ready), + .dac_data(dac_data), + .dac_valid(dac_valid), + .address(address), + .data_read(data_read), + .data_write(data_write), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(symb_8_16b), + .transfer_data(transfer_data), + .stream(stream), + .if_busy(if_busy), + .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)); + + // up bus interface + + up_axi i_up_axi( + .up_rstn(up_rstn), + .up_clk(up_clk), + .up_axi_awvalid(s_axi_awvalid), + .up_axi_awaddr(s_axi_awaddr), + .up_axi_awready(s_axi_awready), + .up_axi_wvalid(s_axi_wvalid), + .up_axi_wdata(s_axi_wdata), + .up_axi_wstrb(s_axi_wstrb), + .up_axi_wready(s_axi_wready), + .up_axi_bvalid(s_axi_bvalid), + .up_axi_bresp(s_axi_bresp), + .up_axi_bready(s_axi_bready), + .up_axi_arvalid(s_axi_arvalid), + .up_axi_araddr(s_axi_araddr), + .up_axi_arready(s_axi_arready), + .up_axi_rvalid(s_axi_rvalid), + .up_axi_rresp(s_axi_rresp), + .up_axi_rdata(s_axi_rdata), + .up_axi_rready(s_axi_rready), + .up_wreq(up_wreq_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)); +endmodule diff --git a/library/axi_ad3552r/axi_ad3552r_channel.v b/library/axi_ad3552r/axi_ad3552r_channel.v new file mode 100755 index 0000000000..f80053ae79 --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r_channel.v @@ -0,0 +1,163 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2023 (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 modificat +// 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_ad3552r_channel #( + + parameter CHANNEL_ID = 32'h0, + parameter DATAPATH_DISABLE = 0 +) ( + + // dac interface + + input dac_clk, + input dac_rst, + output dac_data_valid, + output [15:0] dac_data, + + // input sources + + input [15:0] dma_data, + input [15:0] adc_data, + input valid_in_adc, + input valid_in_dma, + input dac_data_ready, + + // processor interface + + input dac_data_sync, + input dac_dfmt_type, + + // 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 signals + + wire [15:0] formatted_dma_data; + wire [15:0] formatted_adc_data; + wire [ 3:0] dac_data_sel_s; + wire dac_data_valid_int; + wire [15:0] dac_data_int; + + reg [15:0] ramp_pattern = 16'h0000; + reg ramp_valid = 1'b0; + + assign dac_data = dac_data_int; + assign dac_data_valid = dac_data_valid_int; + + assign formatted_dma_data [15] = dac_dfmt_type ^ dma_data[15]; + assign formatted_dma_data [14:0] = dma_data[14:0]; + assign formatted_adc_data [15] = dac_dfmt_type ^ adc_data[15]; + assign formatted_adc_data [14:0] = adc_data[14:0]; + + assign dac_data_int = (dac_data_sel_s == 4'hb) ? ramp_pattern : + ((dac_data_sel_s == 4'h3) ? 16'b0 : ((dac_data_sel_s == 4'h8) ? formatted_adc_data : formatted_dma_data)); + assign dac_data_valid_int = (dac_data_sel_s == 4'hb) ? ramp_valid : + ((dac_data_sel_s == 4'h3) ? 1'b1 : ((dac_data_sel_s == 4'h8) ? valid_in_adc : valid_in_dma)); + + // ramp generator + + always @(posedge dac_clk) begin + if(dac_data_ready == 1'b1) begin + ramp_pattern <= ramp_pattern + 1'b1; + ramp_valid <= 1'b1; + end else begin + ramp_pattern <= ramp_pattern; + ramp_valid <= 1'b0; + end + if(ramp_pattern == 16'hffff || dac_rst == 1'b1) begin + ramp_pattern <= 16'h0; + end + end + + // single channel processor + + up_dac_channel #( + .CHANNEL_ID(CHANNEL_ID) + ) dac_channel ( + .dac_clk(dac_clk), + .dac_rst(dac_rst), + .dac_dds_scale_1(), + .dac_dds_init_1(), + .dac_dds_incr_1(), + .dac_dds_scale_2(), + .dac_dds_init_2(), + .dac_dds_incr_2(), + .dac_pat_data_1(), + .dac_pat_data_2(), + .dac_data_sel(dac_data_sel_s), + .dac_mask_enable(), + .dac_iq_mode(), + .dac_iqcor_enb(), + .dac_iqcor_coeff_1(), + .dac_iqcor_coeff_2(), + .dac_src_chan_sel(), + .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'd0), + .dac_usr_datatype_signed(1'd1), + .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)); +endmodule diff --git a/library/axi_ad3552r/axi_ad3552r_core.v b/library/axi_ad3552r/axi_ad3552r_core.v new file mode 100755 index 0000000000..42d14c38ab --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r_core.v @@ -0,0 +1,247 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2023 (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_ad3552r_core #( + parameter ID = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0 +) ( + + // dac interface + + input dac_clk, + output dac_rst, + input [15:0] adc_data_in_a, + input [15:0] adc_data_in_b, + input [31:0] dma_data, + input adc_valid_in_a, + input adc_valid_in_b, + input valid_in_dma, + output [31:0] dac_data, + output dac_valid, + input dac_data_ready, + + // output + + output [ 7:0] address, + input if_busy, + input [23:0] data_read, + output [23:0] data_write, + output sdr_ddr_n, + output symb_8_16b, + output transfer_data, + output stream, + + // 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 [31:0] up_rdata_0_s; + wire up_rack_0_s; + wire up_wack_0_s; + wire [31:0] up_rdata_1_s; + wire up_rack_1_s; + wire up_wack_1_s; + wire [31:0] up_rdata_s; + wire up_rack_s; + wire up_wack_s; + + wire [15:0] dac_data_channel_0; + wire [15:0] dac_data_channel_1; + wire dac_valid_channel_0; + wire dac_valid_channel_1; + wire dac_rst_s; + + wire [31:0] dac_data_control; + wire [31:0] dac_control; + + wire dac_data_sync; + wire dac_dfmt_type; + + // defaults + + assign dac_rst = dac_rst_s; + assign dac_data = {dac_data_channel_1 ,dac_data_channel_0}; + assign dac_valid = dac_valid_channel_0 | dac_valid_channel_1; + + assign data_write = dac_data_control[23:0]; + assign transfer_data = dac_control[0]; + assign stream = dac_control[1]; + assign address = dac_control[31:24]; + + // 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 | up_rdata_0_s | up_rdata_1_s; + up_rack <= up_rack_s | up_rack_0_s | up_rack_1_s; + up_wack <= up_wack_s | up_wack_0_s | up_wack_1_s; + end + end + + // DAC CHANNEL 0 + + axi_ad3552r_channel #( + .CHANNEL_ID(0) + ) axi_ad3552r_channel_0 ( + .dac_clk(dac_clk), + .dac_rst(dac_rst_s), + .dac_data_valid(dac_valid_channel_0), + .dac_data(dac_data_channel_0), + .dma_data(dma_data[15:0]), + .dac_data_ready(dac_data_ready), + .adc_data(adc_data_in_a), + .valid_in_adc(adc_valid_in_a), + .valid_in_dma(valid_in_dma), + .dac_data_sync(dac_data_sync), + .dac_dfmt_type(dac_dfmt_type), + .up_rstn(up_rstn), + .up_clk(up_clk), + .up_wreq(up_wreq), + .up_waddr(up_waddr), + .up_wdata(up_wdata), + .up_wack(up_wack_0_s), + .up_rreq(up_rreq), + .up_raddr(up_raddr), + .up_rdata(up_rdata_0_s), + .up_rack(up_rack_0_s)); + + // DAC CHANNEL 1 + + axi_ad3552r_channel #( + .CHANNEL_ID(1) + ) axi_ad3552r_channel_1( + .dac_clk(dac_clk), + .dac_rst(dac_rst_s), + .dac_data_valid(dac_valid_channel_1), + .dac_data(dac_data_channel_1), + .dma_data(dma_data[31:16]), + .dac_data_ready(dac_data_ready), + .adc_data(adc_data_in_b), + .valid_in_adc(adc_valid_in_b), + .valid_in_dma(valid_in_dma), + .dac_data_sync(dac_data_sync), + .dac_dfmt_type(dac_dfmt_type), + .up_rstn(up_rstn), + .up_clk(up_clk), + .up_wreq(up_wreq), + .up_waddr(up_waddr), + .up_wdata(up_wdata), + .up_wack(up_wack_1_s), + .up_rreq(up_rreq), + .up_raddr(up_raddr), + .up_rdata(up_rdata_1_s), + .up_rack(up_rack_1_s)); + + // 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) + ) axi_ad3552r_common_core ( + .mmcm_rst(), + .dac_clk(dac_clk), + .dac_rst(dac_rst_s), + .dac_num_lanes(), + .dac_sdr_ddr_n(sdr_ddr_n), + .dac_symb_op(), + .dac_symb_8_16b(symb_8_16b), + .dac_sync(dac_data_sync), + .dac_ext_sync_arm(), + .dac_ext_sync_disarm(), + .dac_ext_sync_manual_req(), + .dac_frame(), + .dac_clksel(), + .dac_custom_wr(dac_data_control), + .dac_custom_rd({8'b0, data_read}), + .dac_custom_control(dac_control), + .dac_status_if_busy(if_busy), + .dac_par_type(), + .dac_par_enb(), + .dac_r1_mode(), + .dac_datafmt(dac_dfmt_type), + .dac_datarate(), + .dac_status(), + .dac_sync_in_status(), + .dac_status_unf(), + .dac_clk_ratio(32'd2), + .up_dac_ce(), + .up_pps_rcounter(32'd0), + .up_pps_status(1'd0), + .up_pps_irq_mask(), + .up_dac_r1_mode(), + .up_drp_sel(), + .up_drp_wr(), + .up_drp_addr(), + .up_drp_wdata() , + .up_drp_rdata(32'd0), + .up_drp_ready(1'd1), + .up_drp_locked(1'd1), + .up_usr_chanmax(), + .dac_usr_chanmax(8'd1), + .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), + .up_rreq(up_rreq), + .up_raddr(up_raddr), + .up_rdata(up_rdata_s), + .up_rack (up_rack_s)); +endmodule diff --git a/library/axi_ad3552r/axi_ad3552r_if.v b/library/axi_ad3552r/axi_ad3552r_if.v new file mode 100755 index 0000000000..77de0964cd --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r_if.v @@ -0,0 +1,285 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2022 - 2023 (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_ad3552r_if ( + + input clk_in, // 120MHz + input reset_in, + input [31:0] dac_data, + input dac_data_valid, + output reg dac_data_ready, + + input [ 7:0] address, + output reg [23:0] data_read, + input [23:0] data_write, + input sdr_ddr_n, + input symb_8_16b, + input transfer_data, + input stream, + + // DAC control signals + + output sclk, + output reg csn, + output if_busy, + + input [ 3:0] sdio_i, + output [ 3:0] sdio_o, + output sdio_t +); + + wire transfer_data_s; + wire start_synced; + wire [31:0] dac_data_int; + + reg [55:0] transfer_reg = 56'h0; + reg [15:0] counter = 16'h0; + reg [ 2:0] transfer_state = 0; + reg [ 2:0] transfer_state_next = 0; + reg cycle_done = 1'b0; + reg transfer_step = 1'b0; + reg sclk_ddr = 1'b0; + reg full_speed = 1'b0; + reg transfer_data_d = 1'b0; + reg transfer_data_dd = 1'b0; + reg [ 3:0] valid_captured_d = 4'b0; + reg data_r_wn = 1'b0; + reg valid_captured = 1'b0; + reg start_transfer = 1'b0; + reg if_busy_reg = 1'b0; + + localparam [ 2:0] IDLE = 3'h0, + CS_LOW = 3'h1, + WRITE_ADDRESS = 3'h2, + TRANSFER_REGISTER = 3'h3, + READ_REGISTER = 3'h4, + STREAM = 3'h5, + CS_HIGH = 3'h6; + + assign if_busy = if_busy_reg; + + // transform the transfer data rising edge into a pulse + + assign transfer_data_s = transfer_data_d & ~transfer_data_dd; + assign start_synced = valid_captured_d[1] & start_transfer & stream; + + always @(posedge clk_in) begin + if(reset_in == 1'b1) begin + transfer_data_d <= 'd0; + transfer_data_dd <= 'd0; + valid_captured_d <= 4'b0; + valid_captured <= 1'b0; + end else begin + transfer_data_d <= transfer_data; + transfer_data_dd <= transfer_data_d; + valid_captured_d <= {valid_captured_d[2:0], valid_captured}; + end + if(dac_data_valid == 1'b1 && start_transfer == 1'b1 ) begin + valid_captured <= 1'b1; + end + if( transfer_data == 1'b1) begin + start_transfer <= 1'b1; + end + + if(transfer_state == CS_HIGH || stream == 1'b0 ) begin + start_transfer <= 1'b0; + valid_captured <= 1'b0; + valid_captured_d <= 4'b0; + end + end + +// dac_data_int is a register allows capturing asinchronously with the +// transmission + + assign dac_data_int = dac_data; + + always @(posedge clk_in) begin + if (reset_in == 1'b1) begin + transfer_state <= IDLE; + end else begin + transfer_state <= transfer_state_next; + end + end + + // FSM next state logic + + always @(*) begin + case (transfer_state) + IDLE : begin + transfer_state_next = ((transfer_data_s == 1'b1 && stream == 1'b0) || start_synced == 1'b1) ? CS_LOW : IDLE; + csn = 1'b1; + transfer_step = 0; + cycle_done = 0; + end + CS_LOW : begin + // brings CS down + // loads all configuration + // puts data on the SDIO pins + // needs 5 ns before risedge of the clock + transfer_state_next = WRITE_ADDRESS; + csn = 1'b0; + transfer_step = 0; + cycle_done = 0; + end + WRITE_ADDRESS : begin + // writes the address + // it works either at full speed (60 MHz) when streaming or normal + // speed (15 MHz) + // full speed - 2 clock cycles + // half speed 8 clock cycles + cycle_done = full_speed ? (counter == 16'h3) : (counter == 16'hf); + transfer_state_next = cycle_done ? (stream ? STREAM : TRANSFER_REGISTER) : WRITE_ADDRESS ; + csn = 1'b0; + // in streaming, change data on falledge. On regular transfer, change data on negedge. + //A single step should be done for 8 bit addressing + transfer_step = full_speed ? (counter[0]== 1'h1) : ((counter[4:0] == 5'h5)); + end + TRANSFER_REGISTER : begin + // always works at 15 MHz + // can be DDR or SDR + cycle_done = sdr_ddr_n ? (symb_8_16b ? (counter == 16'h10) : (counter == 16'h20)) : + (symb_8_16b ? (counter == 16'h09) : (counter == 16'h11)); + transfer_state_next = cycle_done ? CS_HIGH : TRANSFER_REGISTER; + csn = 1'b0; + // in DDR mode, change data on falledge + transfer_step = sdr_ddr_n ? (counter[2:0] == 3'h0) : (counter[1:0] == 2'h0); + end + STREAM : begin + // can be DDR or SDR + // in DDR mode needs to be make sure the clock and data is shifted by 2 ns + cycle_done = stream ? (sdr_ddr_n ? (counter == 16'h0f ) : (counter == 16'h7)): + (sdr_ddr_n ? (counter == 16'h10 ) : (counter == 16'h7)); + transfer_state_next = stream ? STREAM: (cycle_done ? CS_HIGH :STREAM); + csn = 1'b0; + transfer_step = sdr_ddr_n ? counter[0] : 1'b1; + end + CS_HIGH : begin + cycle_done = 1'b1; + transfer_state_next = cycle_done ? IDLE : CS_HIGH; + csn = 1'b1; + transfer_step = 0; + end + default : begin + cycle_done = 0; + transfer_state_next = IDLE; + csn = 1'b1; + transfer_step = 0; + end + endcase + end + + // counter is used to time all states + // depends on number of clock cycles per phase + + always@(posedge clk_in) begin + if (transfer_state == IDLE | reset_in == 1'b1 ) begin + counter <= 'b0; + end else if (transfer_state == WRITE_ADDRESS | transfer_state == TRANSFER_REGISTER | transfer_state == STREAM) begin + if (cycle_done) begin + counter <= 0; + end else begin + counter <= counter + 1; + end + end + end + + always @(negedge clk_in) begin + if (transfer_state == STREAM | transfer_state == WRITE_ADDRESS ) begin + sclk_ddr <= !sclk_ddr; + end else begin + sclk_ddr <= 0; + end + end + + // selection between 60 MHz and 15 MHz + + assign sclk = full_speed ? (sdr_ddr_n ? counter[0] : sclk_ddr) : counter[2]; + + always@(posedge clk_in) begin + if (transfer_state == CS_LOW) begin + data_r_wn <= address[7]; + end else if (transfer_state == CS_HIGH) begin + data_r_wn <=1'b0; + end + if (transfer_state == CS_LOW & stream) begin + dac_data_ready <= 1'b1; + end else if (transfer_state == STREAM) begin + if (cycle_done == 1'b1) begin + dac_data_ready <= stream; + end else begin + dac_data_ready <= 1'b0; + end + end else begin + dac_data_ready <= 1'b0; + end + if (transfer_state == CS_LOW) begin + full_speed = stream; + if(stream) begin + transfer_reg <= {address,dac_data_int, 16'h0}; + end else begin + transfer_reg <= {address,data_write, 24'h0}; + end + end else if ((transfer_state == STREAM & cycle_done) || (transfer_state != STREAM && transfer_state_next == STREAM)) begin + transfer_reg <= {dac_data_int, 24'h0}; + end else if (transfer_step) begin + transfer_reg <= {transfer_reg[51:0], sdio_i}; + end + + if (transfer_state == CS_HIGH) begin + if (symb_8_16b == 1'b0 ) begin + data_read <= {8'h0,transfer_reg[15:0]}; + end else begin + data_read <= {16'h0,transfer_reg[7:0]}; + end + end else begin + data_read <= data_read; + end + if (transfer_state == CS_HIGH || transfer_state == IDLE) begin + if_busy_reg <= 1'b0; + end else begin + if_busy_reg <= 1'b1; + end + + end + + // address[7] is r_wn : depends also on the state machine, input only when + // in TRANSFER register mode + + assign sdio_t = (data_r_wn & transfer_state == TRANSFER_REGISTER); + assign sdio_o = transfer_reg[55:52]; + +endmodule diff --git a/library/axi_ad3552r/axi_ad3552r_if_tb b/library/axi_ad3552r/axi_ad3552r_if_tb new file mode 100755 index 0000000000..85331ea537 --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r_if_tb @@ -0,0 +1,8 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" ../common/ad_iobuf.v" +SOURCE+=" axi_ad3552r_if.v" + +cd `dirname $0` +source ../common/tb/run_tb.sh diff --git a/library/axi_ad3552r/axi_ad3552r_if_tb.v b/library/axi_ad3552r/axi_ad3552r_if_tb.v new file mode 100755 index 0000000000..20d0824ab1 --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r_if_tb.v @@ -0,0 +1,244 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2023 (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_ad3552r_if_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `define TIMEOUT 10000 + `include "tb_base.v" + + + wire [ 23:0] data_read; + wire dac_sclk; + wire dac_csn; + wire dac_data_ready; + wire [ 3:0] sdio_i; + wire [ 3:0] sdio_o; + wire sdio_t; + wire [31:0] dac_data_final; + wire [ 3:0] readback_data_shift; + wire [ 4:0] data_increment_valid; + wire if_busy; + + reg [ 7:0] address_write = 8'b0; + reg dac_clk = 1'b0; + reg reset_in = 1'b1; + reg transfer_data = 1'b0; + reg sdr_ddr_n = 1'b1; + reg reg_8b_16bn = 1'b0; + reg stream = 1'b0; + reg [23:0] data_write = 24'h0; + reg dac_data_valid = 1'b0; + reg [ 3:0] shift_count = 4'b0; + reg [31:0] transfer_reg = 32'h89abcdef; + reg [ 4:0] valid_counter = 5'b0; + reg [31:0] dac_data = 32'b0; + + always #4 dac_clk <= ~dac_clk; + + initial begin + + #100 reset_in = 1'b0; + + // Write 8 bit SDR + + address_write = 8'h2c; + data_write = 24'hab0000; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + + // Read 8 bit SDR + + address_write = 8'hac; + data_write = 24'h000000; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + // Write 16 bit SDR + + address_write = 8'h2c; + data_write = 24'h123400; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + // Read 16 bit SDR + + address_write = 8'hac; + data_write = 24'h000000; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + #500; + + // Write 8 bit DDR + + address_write = 8'h2c; + data_write = 24'h120000; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + + // Read 8 bit DDR + + address_write = 8'hac; + data_write = 24'h000000; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + + // Write 16 bit DDR + + address_write = 8'h2c; + data_write = 24'h123400; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b0; + stream = 1'b0; + transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + // Read 16 bit DDR + + address_write = 8'hac; + data_write = 24'h000000; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #100 transfer_data = 1'b0; + + #500; + + // Stream SDR + + address_write = 8'h2c; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b1; + transfer_data = 1'b1; + #100 transfer_data = 1'b0; + #1000 stream = 1'b0; + + #500; + + // Stream DDR + + address_write = 8'h2c; + reg_8b_16bn = 1'b1; + sdr_ddr_n = 1'b0; + stream = 1'b1; + transfer_data = 1'b1; + #100 transfer_data = 1'b0; + #1000 stream = 1'b0; + + end + + // data is incremented at each complete cycle + + assign dac_data_final = (stream == 1'b1) ? dac_data : data_write; + assign data_increment_valid = (sdr_ddr_n ) ? 5'd16: 5'h8; + + always @(posedge dac_clk) begin + if (valid_counter == data_increment_valid) begin + dac_data <= dac_data + 32'h00010002; + valid_counter <= 3'b0; + dac_data_valid <= 1'b1; + end else begin + dac_data <= dac_data; + valid_counter <= valid_counter + 3'b1; + dac_data_valid <= 1'b0; + end + end + + // data is circullary shifted at every sampling edge + + assign readback_data_shift = (sdr_ddr_n ) ? 4'h8 : 4'h4; + assign sdio_i = (sdio_t === 1'b1) ? transfer_reg[31:28] : 4'b0; + + always @(posedge dac_clk) begin + if( shift_count == readback_data_shift) begin + transfer_reg <= {transfer_reg[27:0],transfer_reg[31:28]}; + end else if (sdio_t === 1'b1) begin + transfer_reg <= transfer_reg; + end + + if( shift_count == readback_data_shift || dac_csn == 1'b1) begin + shift_count <= 3'b0; + end else if (sdio_t === 1'b1) begin + shift_count <= shift_count + 3'b1; + end + end + + axi_ad3552r_if axi_ad3552r_interface ( + .clk_in(dac_clk), + .reset_in(reset_in), + .dac_data(dac_data_final), + .dac_data_valid(dac_data_valid), + .address(address_write), + .data_read(data_read), + .data_write(data_write), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(reg_8b_16bn), + .transfer_data(transfer_data), + .stream(stream), + .dac_data_ready(dac_data_ready), + .if_busy(if_busy), + .sclk(dac_sclk), + .csn(dac_csn), + .sdio_i(sdio_i), + .sdio_o(sdio_o), + .sdio_t(sdio_t)); + +endmodule diff --git a/library/axi_ad3552r/axi_ad3552r_ip.tcl b/library/axi_ad3552r/axi_ad3552r_ip.tcl new file mode 100755 index 0000000000..6201feb48e --- /dev/null +++ b/library/axi_ad3552r/axi_ad3552r_ip.tcl @@ -0,0 +1,40 @@ +source ../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl + +adi_ip_create axi_ad3552r +adi_ip_files axi_ad3552r [list \ + "$ad_hdl_dir/library/xilinx/common/ad_mul.v" \ + "$ad_hdl_dir/library/common/ad_iobuf.v" \ + "$ad_hdl_dir/library/common/ad_rst.v" \ + "$ad_hdl_dir/library/common/up_axi.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_dac_common.v" \ + "$ad_hdl_dir/library/common/up_dac_channel.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" \ + "axi_ad3552r_channel.v" \ + "axi_ad3552r_core.v" \ + "axi_ad3552r_if.v" \ + "axi_ad3552r.v" ] + +adi_ip_properties axi_ad3552r +adi_init_bd_tcl +adi_ip_bd axi_ad3552r "bd/bd.tcl" + +set cc [ipx::current_core] + +set_property company_url {https://wiki.analog.com/resources/fpga/docs/axi_ad3552r} $cc + +set_property driver_value 0 [ipx::get_ports *dac* -of_objects $cc] +set_property driver_value 0 [ipx::get_ports *data* -of_objects $cc] +set_property driver_value 0 [ipx::get_ports *valid* -of_objects $cc] +ipx::infer_bus_interface dac_clk xilinx.com:signal:clock_rtl:1.0 $cc + +adi_add_auto_fpga_spec_params + +ipx::create_xgui_files $cc +ipx::save_core $cc diff --git a/library/axi_ad3552r/tb_base.v b/library/axi_ad3552r/tb_base.v new file mode 100755 index 0000000000..960e9232a1 --- /dev/null +++ b/library/axi_ad3552r/tb_base.v @@ -0,0 +1,76 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2023 (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. +// +// *************************************************************************** +// *************************************************************************** + + reg clk = 1'b0; + reg [3:0] reset_shift = 4'b1111; + reg trigger_reset = 1'b0; + wire reset; + wire resetn = ~reset; + + reg failed = 1'b0; + + initial + begin + $dumpfile (VCD_FILE); + $dumpvars; +`ifdef TIMEOUT + #`TIMEOUT +`else + #100000 +`endif + if (failed == 1'b0) + $display("SUCCESS"); + else + $display("FAILED"); + $finish; + end + + always @(*) #10 clk <= ~clk; + always @(posedge clk) begin + if (trigger_reset == 1'b1) begin + reset_shift <= 3'b111; + end else begin + reset_shift <= {reset_shift[2:0],1'b0}; + end + end + + assign reset = reset_shift[3]; + + task do_trigger_reset; + begin + @(posedge clk) trigger_reset <= 1'b1; + @(posedge clk) trigger_reset <= 1'b0; + end + endtask