From 8febfaf8ca82ff1523e881aa9c9d95dd0ff82901 Mon Sep 17 00:00:00 2001 From: caosjr Date: Wed, 4 Sep 2024 11:26:00 -0300 Subject: [PATCH] ADD: support to AD3541R, AD3542R, AD3551R, AD3552R It is supporting single SPI (Classic), dual SPI, and Quad SPI (according to the eval limitations) for the DACs AD3541R, AD3542R, AD3551R, AD3552R. Changed the regmap, the reg DAC_CUSTOM_CTRL needs to assert the MULTI_IO_MODE field to choose the SPI mode on the AXI controller. Signed-off-by: --- library/axi_ad3542r/Makefile | 35 ++ library/axi_ad3542r/axi_ad3542r.v | 236 ++++++++++ library/axi_ad3542r/axi_ad3542r_channel.v | 227 +++++++++ library/axi_ad3542r/axi_ad3542r_core.v | 263 +++++++++++ library/axi_ad3542r/axi_ad3542r_if.v | 362 +++++++++++++++ library/axi_ad3542r/axi_ad3542r_if_tb | 7 + library/axi_ad3542r/axi_ad3542r_if_tb.v | 265 +++++++++++ library/axi_ad3542r/axi_ad3542r_ip.tcl | 51 +++ library/axi_ad35xxr/Makefile | 35 ++ library/axi_ad35xxr/axi_ad35xxr.v | 238 ++++++++++ library/axi_ad35xxr/axi_ad35xxr_channel.v | 227 +++++++++ library/axi_ad35xxr/axi_ad35xxr_core.v | 263 +++++++++++ library/axi_ad35xxr/axi_ad35xxr_if.v | 430 ++++++++++++++++++ library/axi_ad35xxr/axi_ad35xxr_if_tb | 7 + library/axi_ad35xxr/axi_ad35xxr_if_tb.v | 413 +++++++++++++++++ library/axi_ad35xxr/axi_ad35xxr_ip.tcl | 59 +++ projects/ad3542r_evb/Makefile | 7 + projects/ad3542r_evb/Readme.md | 8 + .../ad3542r_evb/common/ad3542r_evb_bd.tcl | 61 +++ projects/ad3542r_evb/zed/Makefile | 25 + projects/ad3542r_evb/zed/system_bd.tcl | 17 + projects/ad3542r_evb/zed/system_constr.xdc | 21 + projects/ad3542r_evb/zed/system_project.tcl | 17 + projects/ad3542r_evb/zed/system_top.v | 242 ++++++++++ projects/ad35xxr_evb/Makefile | 7 + projects/ad35xxr_evb/Readme.md | 8 + .../ad35xxr_evb/common/ad35xxr_evb_bd.tcl | 65 +++ .../ad35xxr_evb/common/ad35xxr_evb_fmc.txt | 18 + projects/ad35xxr_evb/zed/Makefile | 25 + projects/ad35xxr_evb/zed/system_bd.tcl | 17 + projects/ad35xxr_evb/zed/system_constr.xdc | 24 + projects/ad35xxr_evb/zed/system_project.tcl | 17 + projects/ad35xxr_evb/zed/system_top.v | 244 ++++++++++ 33 files changed, 3941 insertions(+) create mode 100755 library/axi_ad3542r/Makefile create mode 100755 library/axi_ad3542r/axi_ad3542r.v create mode 100755 library/axi_ad3542r/axi_ad3542r_channel.v create mode 100755 library/axi_ad3542r/axi_ad3542r_core.v create mode 100755 library/axi_ad3542r/axi_ad3542r_if.v create mode 100755 library/axi_ad3542r/axi_ad3542r_if_tb create mode 100755 library/axi_ad3542r/axi_ad3542r_if_tb.v create mode 100755 library/axi_ad3542r/axi_ad3542r_ip.tcl create mode 100644 library/axi_ad35xxr/Makefile create mode 100644 library/axi_ad35xxr/axi_ad35xxr.v create mode 100644 library/axi_ad35xxr/axi_ad35xxr_channel.v create mode 100644 library/axi_ad35xxr/axi_ad35xxr_core.v create mode 100644 library/axi_ad35xxr/axi_ad35xxr_if.v create mode 100755 library/axi_ad35xxr/axi_ad35xxr_if_tb create mode 100644 library/axi_ad35xxr/axi_ad35xxr_if_tb.v create mode 100644 library/axi_ad35xxr/axi_ad35xxr_ip.tcl create mode 100755 projects/ad3542r_evb/Makefile create mode 100755 projects/ad3542r_evb/Readme.md create mode 100755 projects/ad3542r_evb/common/ad3542r_evb_bd.tcl create mode 100755 projects/ad3542r_evb/zed/Makefile create mode 100755 projects/ad3542r_evb/zed/system_bd.tcl create mode 100755 projects/ad3542r_evb/zed/system_constr.xdc create mode 100755 projects/ad3542r_evb/zed/system_project.tcl create mode 100755 projects/ad3542r_evb/zed/system_top.v create mode 100644 projects/ad35xxr_evb/Makefile create mode 100644 projects/ad35xxr_evb/Readme.md create mode 100644 projects/ad35xxr_evb/common/ad35xxr_evb_bd.tcl create mode 100644 projects/ad35xxr_evb/common/ad35xxr_evb_fmc.txt create mode 100644 projects/ad35xxr_evb/zed/Makefile create mode 100644 projects/ad35xxr_evb/zed/system_bd.tcl create mode 100644 projects/ad35xxr_evb/zed/system_constr.xdc create mode 100644 projects/ad35xxr_evb/zed/system_project.tcl create mode 100644 projects/ad35xxr_evb/zed/system_top.v diff --git a/library/axi_ad3542r/Makefile b/library/axi_ad3542r/Makefile new file mode 100755 index 0000000000..211512ce47 --- /dev/null +++ b/library/axi_ad3542r/Makefile @@ -0,0 +1,35 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_ad3542r + +GENERIC_DEPS += ../common/ad_addsub.v +GENERIC_DEPS += ../common/ad_dds.v +GENERIC_DEPS += ../common/ad_dds_1.v +GENERIC_DEPS += ../common/ad_dds_2.v +GENERIC_DEPS += ../common/ad_dds_cordic_pipe.v +GENERIC_DEPS += ../common/ad_dds_sine.v +GENERIC_DEPS += ../common/ad_dds_sine_cordic.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_ad3542r.v +GENERIC_DEPS += axi_ad3542r_channel.v +GENERIC_DEPS += axi_ad3542r_core.v +GENERIC_DEPS += axi_ad3542r_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_ad3542r_ip.tcl + +include ../scripts/library.mk diff --git a/library/axi_ad3542r/axi_ad3542r.v b/library/axi_ad3542r/axi_ad3542r.v new file mode 100755 index 0000000000..170dabcec4 --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r.v @@ -0,0 +1,236 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad3542r #( + + parameter ID = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter DDS_DISABLE = 0, + parameter DDS_TYPE = 1, + parameter DDS_CORDIC_DW = 16, + parameter DDS_CORDIC_PHASE_DW = 16 +) ( + + // DAC INTERFACE + + input dac_clk, + + input [31:0] dma_data, + input valid_in_dma, + input valid_in_dma_sec, + 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 [ 1:0] sdio_i, + output [ 1:0] sdio_o, + output sdio_t, + + // sync transfer between 2 DAC'S + + input external_sync, + output sync_ext_device, + + // 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 [ 1:0] multi_io_mode; + wire sdr_ddr_n; + wire symb_8_16b; + wire transfer_data; + wire stream; + wire [31:0] dac_data; + wire dac_valid; + wire if_busy; + wire dac_ext_sync_arm; + + // signal name changes + + assign up_clk = s_axi_aclk; + assign up_rstn = s_axi_aresetn; + + // device interface + axi_ad3542r_if axi_ad3542r_interface ( + .clk_in(dac_clk), + .reset_in(dac_rst_s), + .dac_data(dac_data), + .dac_data_valid(dac_valid), + .dac_data_valid_ext(valid_in_dma_sec), + .dac_data_ready(dac_data_ready), + .address(address), + .data_read(data_read), + .data_write(data_write), + .multi_io_mode(multi_io_mode), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(symb_8_16b), + .transfer_data(transfer_data), + .stream(stream), + .if_busy(if_busy), + .external_sync(external_sync), + .external_sync_arm(dac_ext_sync_arm), + .sync_ext_device(sync_ext_device), + .sclk(dac_sclk), + .csn(dac_csn), + .sdio_i(sdio_i), + .sdio_o(sdio_o), + .sdio_t(sdio_t)); + + // core + axi_ad3542r_core #( + .ID(ID), + .FPGA_TECHNOLOGY(FPGA_TECHNOLOGY), + .FPGA_FAMILY(FPGA_FAMILY), + .SPEED_GRADE(SPEED_GRADE), + .DEV_PACKAGE(DEV_PACKAGE), + .DDS_DISABLE(DDS_DISABLE), + .DDS_TYPE(DDS_TYPE), + .DDS_CORDIC_DW(DDS_CORDIC_DW), + .DDS_CORDIC_PHASE_DW(DDS_CORDIC_PHASE_DW) + ) axi_ad3542r_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), + .multi_io_mode(multi_io_mode), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(symb_8_16b), + .transfer_data(transfer_data), + .stream(stream), + .dac_ext_sync_arm(dac_ext_sync_arm), + .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_ad3542r/axi_ad3542r_channel.v b/library/axi_ad3542r/axi_ad3542r_channel.v new file mode 100755 index 0000000000..d5adfd951a --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r_channel.v @@ -0,0 +1,227 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad3542r_channel #( + + parameter CHANNEL_ID = 32'h0, + parameter DDS_DISABLE = 0, + parameter DDS_TYPE = 1, + parameter DDS_CORDIC_DW = 16, + parameter DDS_CORDIC_PHASE_DW = 16 +) ( + + // 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 [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; + + reg [15:0] ramp_pattern = 16'h0000; + reg ramp_valid = 1'b0; + reg [15:0] dac_data_int; + reg dac_data_valid_int; + + 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]; + + always @ (*) begin + case(dac_data_sel_s) + 4'h0 : + begin + dac_data_int = dac_dds_data_s; + dac_data_valid_int = 1'b1; + end + 4'h2 : + begin + dac_data_int = formatted_dma_data; + dac_data_valid_int = valid_in_dma; + end + 4'h3 : + begin + dac_data_int = 16'b0; + dac_data_valid_int = 1'b1; + end + 4'h8 : + begin + dac_data_int = formatted_adc_data; + dac_data_valid_int = valid_in_adc; + end + 4'hb : + begin + dac_data_int = ramp_pattern; + dac_data_valid_int = ramp_valid; + end + default : + begin + dac_data_int = 16'b0; + dac_data_valid_int = 1'b1; + end + endcase + end + + // ramp generator + + always @(posedge dac_clk) begin + ramp_valid <= 1'b1; + if(dac_data_ready == 1'b1) begin + ramp_pattern <= ramp_pattern + 1'b1; + end else begin + ramp_pattern <= ramp_pattern; + end + if(ramp_pattern == 16'hffff || dac_rst == 1'b1) begin + ramp_pattern <= 16'h0; + end + end + + ad_dds #( + .DISABLE (DDS_DISABLE), + .DDS_DW (16), + .PHASE_DW (16), + .DDS_TYPE (DDS_TYPE), + .CORDIC_DW (DDS_CORDIC_DW), + .CORDIC_PHASE_DW (DDS_CORDIC_PHASE_DW), + .CLK_RATIO (1) + ) i_dds ( + .clk (dac_clk), + .dac_dds_format (dac_dfmt_type), + .dac_data_sync (dac_data_sync), + .dac_valid (dac_data_ready), + .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 #( + .CHANNEL_ID(CHANNEL_ID), + .COMMON_ID(6'h01) + ) 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_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_ad3542r/axi_ad3542r_core.v b/library/axi_ad3542r/axi_ad3542r_core.v new file mode 100755 index 0000000000..de0481128d --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r_core.v @@ -0,0 +1,263 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad3542r_core #( + parameter ID = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter DDS_DISABLE = 0, + parameter DDS_TYPE = 1, + parameter DDS_CORDIC_DW = 16, + parameter DDS_CORDIC_PHASE_DW = 16 +) ( + + // 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 [ 1:0] multi_io_mode, + output sdr_ddr_n, + output symb_8_16b, + output transfer_data, + output stream, + output dac_ext_sync_arm, + + // 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 multi_io_mode = dac_control[3:2]; + 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_ad3542r_channel #( + .CHANNEL_ID(0), + .DDS_DISABLE(DDS_DISABLE), + .DDS_TYPE(DDS_TYPE), + .DDS_CORDIC_DW(DDS_CORDIC_DW), + .DDS_CORDIC_PHASE_DW(DDS_CORDIC_PHASE_DW) + ) axi_ad3542r_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_ad3542r_channel #( + .CHANNEL_ID(1), + .DDS_DISABLE(DDS_DISABLE), + .DDS_TYPE(DDS_TYPE), + .DDS_CORDIC_DW(DDS_CORDIC_DW), + .DDS_CORDIC_PHASE_DW(DDS_CORDIC_PHASE_DW) + ) axi_ad3542r_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), + .COMMON_ID(6'h00) + ) axi_ad3542r_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_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'd1), + .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_ad3542r/axi_ad3542r_if.v b/library/axi_ad3542r/axi_ad3542r_if.v new file mode 100755 index 0000000000..9fea486c1d --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r_if.v @@ -0,0 +1,362 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad3542r_if ( + + input clk_in, // 132MHz + input reset_in, + input [31:0] dac_data, + input dac_data_valid, + input dac_data_valid_ext, + output dac_data_ready, + + input [ 7:0] address, + input [23:0] data_write, + input [ 1:0] multi_io_mode, + input sdr_ddr_n, + input symb_8_16b, + input transfer_data, + input stream, + input external_sync, + input external_sync_arm, + + output if_busy, + output sync_ext_device, + output reg [23:0] data_read, + + // DAC control signals + + output sclk, + output reg csn, + input [ 1:0] sdio_i, + output [ 1:0] sdio_o, + output sdio_t +); + + wire transfer_data_s; + wire start_synced; + wire [31:0] dac_data_int; + wire dac_data_valid_synced; + wire external_sync_s; + + reg [55:0] transfer_reg = 56'h0; + reg [15:0] counter = 16'h0; + reg wa_cp = 1'b0; + reg [ 3:0] tf_cp = 4'h0; + reg [ 3:0] st_cp = 4'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; //why 4 registers? It is using up to the second + reg data_r_wn = 1'b0; + reg valid_captured = 1'b0; + reg start_transfer = 1'b0; + reg if_busy_reg = 1'b0; + reg dac_data_ready_s = 1'b0; + reg external_sync_arm_reg = 1'b0; + reg external_sync_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; + + // start the data stream transfer after valid has been captured + + assign start_synced = valid_captured_d[1] & start_transfer & stream; + assign sync_ext_device = start_synced; + + // use dac_data valid from an external source only if external_sync_arm_reg is 1 + + assign dac_data_valid_synced = (external_sync_arm_reg == 1'b1) ? (dac_data_valid & dac_data_valid_ext) : dac_data_valid ; + assign dac_data_ready = dac_data_ready_s & dac_data_valid_synced; + assign dac_data_int = dac_data; + + // sync the data only if the synchronizations has been armed in software + + assign external_sync_s = ~external_sync_arm_reg | external_sync_reg; + + 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(transfer_state == CS_HIGH || stream == 1'b0) begin + start_transfer <= 1'b0; + valid_captured <= 1'b0; + valid_captured_d <= 4'b0; + end + + // pulse to level conversion + + if(external_sync_arm == 1'b1) begin + external_sync_arm_reg <= 1'b1; + end + if(external_sync == 1'b1) begin + external_sync_reg <= 1'b1; + end + + if(transfer_state == CS_HIGH) begin + external_sync_arm_reg <= 1'b0; + external_sync_reg <= 1'b0; + 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 + + end + + 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 + // goes in to the next state only if the control is to transfer register or synced transfer(if it's armed in software) + transfer_state_next = ((transfer_data_s == 1'b1 && stream == 1'b0) || (start_synced == 1'b1 && external_sync_s)) ? 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 the rising edge of the clock (t2) + transfer_state_next = WRITE_ADDRESS; + csn = 1'b0; + transfer_step = 0; + cycle_done = 0; + end + WRITE_ADDRESS : begin + // writes the address + // 8-bit addressing requires 8 clock cycles because dual mode only support + // the address on a single lane + // step requires at least (t1)ns + cycle_done = wa_cp; //It is considering 8 bit address only + //cycle_done = (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. + transfer_step = (counter[0] == 1'h1); + end + TRANSFER_REGISTER : begin + // can be DDR or SDR + // counter is based on the "Clock Cycles Required to Transfer One Byte" table in the doc + // counter is twice the number because clk_in is twice the frequency + // cycle_done = (sdr_ddr_n | data_r_wn) ? (symb_8_16b ? (counter == 16'h8) : (counter == 16'h10)): + // (symb_8_16b ? (counter == 16'h4) : (counter == 16'h8)); + cycle_done = (sdr_ddr_n | data_r_wn) ? (symb_8_16b ? tf_cp[0] : tf_cp[1]): + (symb_8_16b ? tf_cp[2] : tf_cp[3]); + //DDR requires one more cycle to fulfill t3 + //DDR is only allowed in writte operations + //It is necessary to keep sclk low for the last bit + transfer_state_next = cycle_done ? CS_HIGH : TRANSFER_REGISTER; + csn = 1'b0; + // in DDR mode, change data on falledge + transfer_step = (sdr_ddr_n | data_r_wn) ? counter[0] : 1'b1; + 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 (t7 and t8) + // the last word in the stream needs one more clock cycle to guarantee t3 + // cycle_done = stream ? ((sdr_ddr_n | data_r_wn) ? (counter == 16'h1f) : (counter == 16'hf)): + // ((sdr_ddr_n | data_r_wn) ? (counter == 16'h20) : (counter == 16'h10)); + cycle_done = stream ? ((sdr_ddr_n | data_r_wn) ? st_cp[0] : st_cp[1]): + ((sdr_ddr_n | data_r_wn) ? st_cp[2] : st_cp[3]); + transfer_state_next = (stream && external_sync_s) ? STREAM: ((cycle_done || external_sync_s == 1'b0) ? CS_HIGH :STREAM); + csn = 1'b0; + transfer_step = (sdr_ddr_n | data_r_wn) ? 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 relies on a 132 Mhz clock or slower + // 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; + wa_cp <= 1'b0; + tf_cp[0] <= 1'b0; + tf_cp[1] <= 1'b0; + tf_cp[2] <= 1'b0; + tf_cp[3] <= 1'b0; + st_cp[0] <= 1'b0; + st_cp[1] <= 1'b0; + st_cp[2] <= 1'b0; + st_cp[3] <= 1'b0; + end else if (transfer_state == WRITE_ADDRESS | transfer_state == TRANSFER_REGISTER | transfer_state == STREAM) begin + if (cycle_done) begin + counter <= 0; + wa_cp <= 1'b0; + tf_cp[0] <= 1'b0; + tf_cp[1] <= 1'b0; + tf_cp[2] <= 1'b0; + tf_cp[3] <= 1'b0; + st_cp[0] <= 1'b0; + st_cp[1] <= 1'b0; + st_cp[2] <= 1'b0; + st_cp[3] <= 1'b0; + end else begin + counter <= counter + 1; + wa_cp <= (counter == 16'he); + //multi_io_mode == 0 is single SPI + tf_cp[0] <= (~(|multi_io_mode)) ? (counter == 16'hf) : (counter == 16'h7); + tf_cp[1] <= (~(|multi_io_mode)) ? (counter == 16'h1f): (counter == 16'hf); + tf_cp[2] <= (~(|multi_io_mode)) ? (counter == 16'h7) : (counter == 16'h3); + tf_cp[3] <= (~(|multi_io_mode)) ? (counter == 16'hf) : (counter == 16'h7); + st_cp[0] <= (counter == 16'h1e); + st_cp[1] <= (counter == 16'he); + st_cp[2] <= (counter == 16'h1f); + st_cp[3] <= (counter == 16'hf); + end + end + end + + always @(negedge clk_in) begin + if (transfer_state == STREAM | transfer_state == TRANSFER_REGISTER | transfer_state == WRITE_ADDRESS) begin + if (cycle_done) begin + sclk_ddr <= 0; + end else begin + sclk_ddr <= !sclk_ddr; + end + end else begin + sclk_ddr <= 0; + end + end + + // selection between 66 MHz clocks for the SCLK + // DDR mode requires a phase shift for the t7 and t8 + + assign sclk = (sdr_ddr_n | data_r_wn) ? counter[0] : sclk_ddr; + + 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 == STREAM) begin + if (cycle_done == 1'b1) begin + dac_data_ready_s <= stream; + end else begin + dac_data_ready_s <= 1'b0; + end + end else begin + dac_data_ready_s <= 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 && transfer_state != CS_HIGH) begin + transfer_reg <= (transfer_state == WRITE_ADDRESS || ~(|multi_io_mode)) ? {transfer_reg[54:0], sdio_i[0]} : {transfer_reg[53:0], sdio_i};//analisar hardware, provavelmente replicar dados + 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_state == WRITE_ADDRESS || ~(|multi_io_mode)) ? {1'b0, transfer_reg[55]} : transfer_reg[55:54]; //separar tristate + +endmodule diff --git a/library/axi_ad3542r/axi_ad3542r_if_tb b/library/axi_ad3542r/axi_ad3542r_if_tb new file mode 100755 index 0000000000..eaf1f723a9 --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r_if_tb @@ -0,0 +1,7 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" axi_ad3542r_if.v" + +cd `dirname $0` +source ../common/tb/run_tb.sh diff --git a/library/axi_ad3542r/axi_ad3542r_if_tb.v b/library/axi_ad3542r/axi_ad3542r_if_tb.v new file mode 100755 index 0000000000..bdff61218a --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r_if_tb.v @@ -0,0 +1,265 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad3542r_if_tb; + parameter VCD_FILE = "axi_ad3542r_if_tb.vcd"; + + `define TIMEOUT 9000 + `include "../common/tb/tb_base.v" + + wire [ 23:0] data_read; + wire dac_sclk; + wire dac_csn; + wire dac_data_ready; + wire [ 1:0] sdio_i; + wire [ 1:0] sdio_o; + wire sdio_t; + wire [31:0] dac_data_final; + wire [ 3:0] readback_data_shift; + wire [ 5: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 [ 1:0] multi_io_mode = 2'h1; + 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 [ 5:0] valid_counter = 6'b0; + reg [31:0] dac_data = 32'b0; + + always #3.8 dac_clk <= ~dac_clk; + + initial begin + + #100 reset_in = 1'b0; + + // Write 8 bit SDR + + wait (if_busy == 1'b0); + address_write = 8'h2c; + data_write = 24'hab0000; + multi_io_mode = 2'h0; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 8 bit SDR + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h1; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Write 16 bit SDR + + wait (if_busy == 1'b0); + address_write = 8'h2c; + data_write = 24'h123400; + multi_io_mode = 2'h1; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 16 bit SDR + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h0; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + #500; + + // Write 8 bit DDR + + wait (if_busy == 1'b0); + address_write = 8'h2c; + multi_io_mode = 2'h0; + data_write = 24'h120000; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 8 bit DDR + // it must ignore the sdr_ddr_n bit + // and work as SDR + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h1; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Write 16 bit DDR + + wait (if_busy == 1'b0); + address_write = 8'h2c; + data_write = 24'h123400; + multi_io_mode = 2'h0; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b0; + stream = 1'b0; + transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 16 bit DDR + // it must ignore the sdr_ddr_n bit + // and work as SDR + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h1; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + #500; + + // Stream SDR + + wait (if_busy == 1'b0); + address_write = 8'h2c; + multi_io_mode = 2'h1; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b1; + transfer_data = 1'b1; + #40 transfer_data = 1'b0; + #1000 stream = 1'b0; + + #500; + + // Stream DDR + + wait (if_busy == 1'b0); + address_write = 8'h2c; + multi_io_mode = 2'h1; + reg_8b_16bn = 1'b1; + sdr_ddr_n = 1'b0; + stream = 1'b1; + transfer_data = 1'b1; + #40 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 ) ? 6'd32: 6'd16; + + always @(posedge dac_clk) begin + if (valid_counter == data_increment_valid) begin + dac_data <= dac_data + 32'h00010002; + valid_counter <= 6'b0; + dac_data_valid <= 1'b1; + end else begin + dac_data <= dac_data; + valid_counter <= valid_counter + 6'b1; + dac_data_valid <= 1'b0; + end + end + + // data is circullary shifted at every sampling edge + + assign readback_data_shift = (sdr_ddr_n | address_write[7]) ? 4'h1 : 4'h0; + assign sdio_i = (sdio_t === 1'b1) ? transfer_reg[31:30] : 2'h0; + + always @(posedge dac_clk) begin + if (shift_count == readback_data_shift) begin + transfer_reg <= (~(|multi_io_mode)) ? {transfer_reg[30:0],transfer_reg[31]} : {transfer_reg[29:0],transfer_reg[31:30]}; + 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_ad3542r_if axi_ad3542r_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), + .multi_io_mode(multi_io_mode), + .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_ad3542r/axi_ad3542r_ip.tcl b/library/axi_ad3542r/axi_ad3542r_ip.tcl new file mode 100755 index 0000000000..5d3bfa6207 --- /dev/null +++ b/library/axi_ad3542r/axi_ad3542r_ip.tcl @@ -0,0 +1,51 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +source ../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl + +adi_ip_create axi_ad3542r +adi_ip_files axi_ad3542r [list \ + "$ad_hdl_dir/library/xilinx/common/ad_mul.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/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_2.v" \ + "$ad_hdl_dir/library/common/ad_dds_1.v" \ + "$ad_hdl_dir/library/common/ad_dds.v" \ + "$ad_hdl_dir/library/common/ad_addsub.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_ad3542r_channel.v" \ + "axi_ad3542r_core.v" \ + "axi_ad3542r_if.v" \ + "axi_ad3542r.v" ] + +adi_ip_properties axi_ad3542r +adi_init_bd_tcl +adi_ip_bd axi_ad3542r "bd/bd.tcl" + +set cc [ipx::current_core] + +set_property company_url {https://wiki.analog.com/resources/fpga/docs/axi_ad3542r} $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_ad35xxr/Makefile b/library/axi_ad35xxr/Makefile new file mode 100644 index 0000000000..36b5ff8ff1 --- /dev/null +++ b/library/axi_ad35xxr/Makefile @@ -0,0 +1,35 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := axi_ad35xxr + +GENERIC_DEPS += ../common/ad_addsub.v +GENERIC_DEPS += ../common/ad_dds.v +GENERIC_DEPS += ../common/ad_dds_1.v +GENERIC_DEPS += ../common/ad_dds_2.v +GENERIC_DEPS += ../common/ad_dds_cordic_pipe.v +GENERIC_DEPS += ../common/ad_dds_sine.v +GENERIC_DEPS += ../common/ad_dds_sine_cordic.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_ad35xxr.v +GENERIC_DEPS += axi_ad35xxr_channel.v +GENERIC_DEPS += axi_ad35xxr_core.v +GENERIC_DEPS += axi_ad35xxr_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_ad35xxr_ip.tcl + +include ../scripts/library.mk diff --git a/library/axi_ad35xxr/axi_ad35xxr.v b/library/axi_ad35xxr/axi_ad35xxr.v new file mode 100644 index 0000000000..8796ebdfd3 --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr.v @@ -0,0 +1,238 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad35xxr #( + + parameter ID = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter DDS_DISABLE = 0, + parameter DDS_TYPE = 1, + parameter DDS_CORDIC_DW = 16, + parameter DDS_CORDIC_PHASE_DW = 16 +) ( + + // DAC INTERFACE + + input dac_clk, + + input [31:0] dma_data, + input valid_in_dma, + input valid_in_dma_sec, + 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 [ 3:0] sdio_t, + output qspi_sel, + + // sync transfer between 2 DAC'S + + input external_sync, + output sync_ext_device, + + // 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 [ 1:0] multi_io_mode; + wire sdr_ddr_n; + wire symb_8_16b; + wire transfer_data; + wire stream; + wire [31:0] dac_data; + wire dac_valid; + wire if_busy; + wire dac_ext_sync_arm; + + // signal name changes + + assign up_clk = s_axi_aclk; + assign up_rstn = s_axi_aresetn; + assign qspi_sel = (multi_io_mode == 2'd2); //2'd2 is quad spi in multi_io_mode reg + + // device interface + axi_ad35xxr_if axi_ad35xxr_interface ( + .clk_in(dac_clk), + .reset_in(dac_rst_s), + .dac_data(dac_data), + .dac_data_valid(dac_valid), + .dac_data_valid_ext(valid_in_dma_sec), + .dac_data_ready(dac_data_ready), + .address(address), + .data_read(data_read), + .data_write(data_write), + .multi_io_mode(multi_io_mode), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(symb_8_16b), + .transfer_data(transfer_data), + .stream(stream), + .if_busy(if_busy), + .external_sync(external_sync), + .external_sync_arm(dac_ext_sync_arm), + .sync_ext_device(sync_ext_device), + .sclk(dac_sclk), + .csn(dac_csn), + .sdio_i(sdio_i), + .sdio_o(sdio_o), + .sdio_t(sdio_t)); + + // core + axi_ad35xxr_core #( + .ID(ID), + .FPGA_TECHNOLOGY(FPGA_TECHNOLOGY), + .FPGA_FAMILY(FPGA_FAMILY), + .SPEED_GRADE(SPEED_GRADE), + .DEV_PACKAGE(DEV_PACKAGE), + .DDS_DISABLE(DDS_DISABLE), + .DDS_TYPE(DDS_TYPE), + .DDS_CORDIC_DW(DDS_CORDIC_DW), + .DDS_CORDIC_PHASE_DW(DDS_CORDIC_PHASE_DW) + ) axi_ad35xxr_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), + .multi_io_mode(multi_io_mode), + .sdr_ddr_n(sdr_ddr_n), + .symb_8_16b(symb_8_16b), + .transfer_data(transfer_data), + .stream(stream), + .dac_ext_sync_arm(dac_ext_sync_arm), + .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_ad35xxr/axi_ad35xxr_channel.v b/library/axi_ad35xxr/axi_ad35xxr_channel.v new file mode 100644 index 0000000000..eaa7b8e9fe --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr_channel.v @@ -0,0 +1,227 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad35xxr_channel #( + + parameter CHANNEL_ID = 32'h0, + parameter DDS_DISABLE = 0, + parameter DDS_TYPE = 1, + parameter DDS_CORDIC_DW = 16, + parameter DDS_CORDIC_PHASE_DW = 16 +) ( + + // 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 [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; + + reg [15:0] ramp_pattern = 16'h0000; + reg ramp_valid = 1'b0; + reg [15:0] dac_data_int; + reg dac_data_valid_int; + + 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]; + + always @ (*) begin + case(dac_data_sel_s) + 4'h0 : + begin + dac_data_int = dac_dds_data_s; + dac_data_valid_int = 1'b1; + end + 4'h2 : + begin + dac_data_int = formatted_dma_data; + dac_data_valid_int = valid_in_dma; + end + 4'h3 : + begin + dac_data_int = 16'b0; + dac_data_valid_int = 1'b1; + end + 4'h8 : + begin + dac_data_int = formatted_adc_data; + dac_data_valid_int = valid_in_adc; + end + 4'hb : + begin + dac_data_int = ramp_pattern; + dac_data_valid_int = ramp_valid; + end + default : + begin + dac_data_int = 16'b0; + dac_data_valid_int = 1'b1; + end + endcase + end + + // ramp generator + + always @(posedge dac_clk) begin + ramp_valid <= 1'b1; + if(dac_data_ready == 1'b1) begin + ramp_pattern <= ramp_pattern + 1'b1; + end else begin + ramp_pattern <= ramp_pattern; + end + if(ramp_pattern == 16'hffff || dac_rst == 1'b1) begin + ramp_pattern <= 16'h0; + end + end + + ad_dds #( + .DISABLE (DDS_DISABLE), + .DDS_DW (16), + .PHASE_DW (16), + .DDS_TYPE (DDS_TYPE), + .CORDIC_DW (DDS_CORDIC_DW), + .CORDIC_PHASE_DW (DDS_CORDIC_PHASE_DW), + .CLK_RATIO (1) + ) i_dds ( + .clk (dac_clk), + .dac_dds_format (dac_dfmt_type), + .dac_data_sync (dac_data_sync), + .dac_valid (dac_data_ready), + .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 #( + .CHANNEL_ID(CHANNEL_ID), + .COMMON_ID(6'h01) + ) 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_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_ad35xxr/axi_ad35xxr_core.v b/library/axi_ad35xxr/axi_ad35xxr_core.v new file mode 100644 index 0000000000..3267cc7076 --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr_core.v @@ -0,0 +1,263 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad35xxr_core #( + parameter ID = 0, + parameter FPGA_TECHNOLOGY = 0, + parameter FPGA_FAMILY = 0, + parameter SPEED_GRADE = 0, + parameter DEV_PACKAGE = 0, + parameter DDS_DISABLE = 0, + parameter DDS_TYPE = 1, + parameter DDS_CORDIC_DW = 16, + parameter DDS_CORDIC_PHASE_DW = 16 +) ( + + // 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 [ 1:0] multi_io_mode, + output sdr_ddr_n, + output symb_8_16b, + output transfer_data, + output stream, + output dac_ext_sync_arm, + + // 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 multi_io_mode = dac_control[3:2]; + 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_ad35xxr_channel #( + .CHANNEL_ID(0), + .DDS_DISABLE(DDS_DISABLE), + .DDS_TYPE(DDS_TYPE), + .DDS_CORDIC_DW(DDS_CORDIC_DW), + .DDS_CORDIC_PHASE_DW(DDS_CORDIC_PHASE_DW) + ) axi_ad35xxr_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_ad35xxr_channel #( + .CHANNEL_ID(1), + .DDS_DISABLE(DDS_DISABLE), + .DDS_TYPE(DDS_TYPE), + .DDS_CORDIC_DW(DDS_CORDIC_DW), + .DDS_CORDIC_PHASE_DW(DDS_CORDIC_PHASE_DW) + ) axi_ad35xxr_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), + .COMMON_ID(6'h00) + ) axi_ad35xxr_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_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'd1), + .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_ad35xxr/axi_ad35xxr_if.v b/library/axi_ad35xxr/axi_ad35xxr_if.v new file mode 100644 index 0000000000..d1e24a37b9 --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr_if.v @@ -0,0 +1,430 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad35xxr_if ( + + input clk_in, // 132MHz + input reset_in, + input [31:0] dac_data, + input dac_data_valid, + input dac_data_valid_ext, + output dac_data_ready, + + input [ 7:0] address, + input [23:0] data_write, + input [ 1:0] multi_io_mode, + input sdr_ddr_n, + input symb_8_16b, + input transfer_data, + input stream, + input external_sync, + input external_sync_arm, + + output if_busy, + output sync_ext_device, + output reg [23:0] data_read, + + // DAC control signals + + output sclk, + output reg csn, + input [ 3:0] sdio_i, + output [ 3:0] sdio_o, + output [ 3:0] sdio_t +); + + wire transfer_data_s; + wire start_synced; + wire [31:0] dac_data_int; + wire dac_data_valid_synced; + wire external_sync_s; + + reg [55:0] transfer_reg_single = 0; + reg [55:0] transfer_reg_dual = 0; + reg [55:0] transfer_reg_quad = 0; + + reg [15:0] counter = 0; + reg wa_cp = 1'b0; + reg [ 3:0] tf_cp = 4'h0; + reg [ 3:0] st_cp = 4'h0; + reg [ 2:0] transfer_state = 0; + reg [ 2:0] transfer_state_next = 0; + reg [ 2:0] transfer_state_p = 0; + reg [ 2:0] transfer_state_prev = 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; //why 4 registers? It is using up to the second + reg data_r_wn = 1'b0; + reg valid_captured = 1'b0; + reg start_transfer = 1'b0; + reg if_busy_reg = 1'b0; + reg dac_data_ready_s = 1'b0; + reg external_sync_arm_reg = 1'b0; + reg external_sync_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; + + // start the data stream transfer after valid has been captured + + assign start_synced = valid_captured_d[1] & start_transfer & stream; + assign sync_ext_device = start_synced; + + // use dac_data valid from an external source only if external_sync_arm_reg is 1 + + assign dac_data_valid_synced = (external_sync_arm_reg == 1'b1) ? (dac_data_valid & dac_data_valid_ext) : dac_data_valid ; + assign dac_data_ready = dac_data_ready_s & dac_data_valid_synced; + assign dac_data_int = dac_data; + + // sync the data only if the synchronizations has been armed in software + + assign external_sync_s = ~external_sync_arm_reg | external_sync_reg; + + 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(transfer_state == CS_HIGH || stream == 1'b0) begin + start_transfer <= 1'b0; + valid_captured <= 1'b0; + valid_captured_d <= 4'b0; + end + + // pulse to level conversion + + if(external_sync_arm == 1'b1) begin + external_sync_arm_reg <= 1'b1; + end + if(external_sync == 1'b1) begin + external_sync_reg <= 1'b1; + end + + if(transfer_state == CS_HIGH) begin + external_sync_arm_reg <= 1'b0; + external_sync_reg <= 1'b0; + 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 + + end + + always @(posedge clk_in) begin + if (reset_in == 1'b1) begin + transfer_state <= IDLE; + end else begin + transfer_state <= transfer_state_next; + transfer_state_p <= transfer_state_prev; + end + end + + // FSM next state logic + + always @(*) begin + case (transfer_state) + IDLE : begin + // goes in to the next state only if the control is to transfer register or synced transfer(if it's armed in software) + transfer_state_next = ((transfer_data_s == 1'b1 && stream == 1'b0) || (start_synced == 1'b1 && external_sync_s)) ? CS_LOW : IDLE; + transfer_state_prev = 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 the rising edge of the clock (t2) + transfer_state_next = WRITE_ADDRESS; + transfer_state_prev = CS_LOW; + csn = 1'b0; + transfer_step = 0; + cycle_done = 0; + end + WRITE_ADDRESS : begin + // writes the address + // 8-bit addressing requires 8 clock cycles because dual mode only support + // the address on a single lane + // step requires at least (t1)ns + // it works either at full speed (66 MHz) when streaming or + // normal at speed (16.5 MHz) + // full speed - 2 clock cycles + // half speed 8 clock cycles + cycle_done = wa_cp; //It is considering 8 bit address only + transfer_state_next = cycle_done ? (stream ? STREAM : TRANSFER_REGISTER) : WRITE_ADDRESS; + transfer_state_prev = WRITE_ADDRESS; + csn = 1'b0; + // in streaming, change data on falledge. On regular transfer, change data on negedge. + transfer_step = full_speed ? counter[0] : ((counter[2:0] == 3'h5)); + end + TRANSFER_REGISTER : begin + // always works at 15 MHz due to the DAC limitation + // can be DDR or SDR + // counter is based on the "Clock Cycles Required to Transfer One Byte" table in the doc + cycle_done = (sdr_ddr_n | data_r_wn) ? (symb_8_16b ? tf_cp[0] : tf_cp[1]): + (symb_8_16b ? tf_cp[2] : tf_cp[3]); + //DDR requires one more cycle to fulfill t3 + //DDR is only allowed in writte operations + //It is necessary to keep sclk low for the last bit + transfer_state_next = cycle_done ? CS_HIGH : TRANSFER_REGISTER; + csn = 1'b0; + // in DDR mode, change data on falledge + transfer_step = (sdr_ddr_n | data_r_wn) ? (counter[2:0] == 3'h5) : ((counter[1:0] == 2'h0) && (transfer_state_p != WRITE_ADDRESS)); + transfer_state_prev = TRANSFER_REGISTER; + 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 (t7 and t8) + // the last word in the stream needs one more clock cycle to guarantee t3 + cycle_done = stream ? ((sdr_ddr_n | data_r_wn) ? st_cp[0] : st_cp[1]): + ((sdr_ddr_n | data_r_wn) ? st_cp[2] : st_cp[3]); + transfer_state_next = (stream && external_sync_s) ? STREAM: ((cycle_done || external_sync_s == 1'b0) ? CS_HIGH :STREAM); + transfer_state_prev = STREAM; + csn = 1'b0; + transfer_step = (sdr_ddr_n | data_r_wn) ? counter[0] : 1'b1; + end + CS_HIGH : begin + cycle_done = 1'b1; + transfer_state_next = cycle_done ? IDLE : CS_HIGH; + transfer_state_prev = CS_HIGH; + csn = 1'b1; + transfer_step = 0; + end + default : begin + cycle_done = 0; + transfer_state_next = IDLE; + transfer_state_prev = IDLE; + csn = 1'b1; + transfer_step = 0; + end + endcase + end + + // counter relies on a 132 Mhz clock or slower + // 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 <= 0; + wa_cp <= 1'b0; + tf_cp[0] <= 1'b0; + tf_cp[1] <= 1'b0; + tf_cp[2] <= 1'b0; + tf_cp[3] <= 1'b0; + st_cp[0] <= 1'b0; + st_cp[1] <= 1'b0; + st_cp[2] <= 1'b0; + st_cp[3] <= 1'b0; + end else if (transfer_state == WRITE_ADDRESS | transfer_state == TRANSFER_REGISTER | transfer_state == STREAM) begin + if (cycle_done) begin + counter <= 0; + wa_cp <= 1'b0; + tf_cp[0] <= 1'b0; + tf_cp[1] <= 1'b0; + tf_cp[2] <= 1'b0; + tf_cp[3] <= 1'b0; + st_cp[0] <= 1'b0; + st_cp[1] <= 1'b0; + st_cp[2] <= 1'b0; + st_cp[3] <= 1'b0; + end else begin + counter <= counter + 1; + if (multi_io_mode == 2'h1) begin //dual SPI + wa_cp <= full_speed ? (counter == 16'he) : (counter == 16'h3e); + tf_cp[0] <= (counter == 16'h1f); + tf_cp[1] <= (counter == 16'h3f); + tf_cp[2] <= (counter == 16'h10); + tf_cp[3] <= (counter == 16'h20); + st_cp[0] <= (counter == 16'h1e); + st_cp[1] <= (counter == 16'he); + st_cp[2] <= (counter == 16'h1f); + st_cp[3] <= (counter == 16'hf); + end else if (multi_io_mode == 2'h2) begin //Quad SPI + wa_cp <= full_speed ? (counter == 16'h2) : (counter == 16'he); + tf_cp[0] <= (counter == 16'he); + tf_cp[1] <= (counter == 16'h1f); + tf_cp[2] <= (counter == 16'h8); + tf_cp[3] <= (counter == 16'h10); + st_cp[0] <= (counter == 16'he); + st_cp[1] <= (counter == 16'h6); + st_cp[2] <= (counter == 16'hf); + st_cp[3] <= (counter == 16'h7); + end else begin //Any other case is classic SPI + wa_cp <= full_speed ? (counter == 16'he) : (counter == 16'h3e); + tf_cp[0] <= (counter == 16'h3f); + tf_cp[1] <= (counter == 16'h7f); + tf_cp[2] <= (counter == 16'h1f); + tf_cp[3] <= (counter == 16'h3f); + st_cp[0] <= (counter == 16'h3e); + st_cp[1] <= (counter == 16'h1e); + st_cp[2] <= (counter == 16'h3f); + st_cp[3] <= (counter == 16'h1f); + end + end + end + end + + always @(negedge clk_in) begin + if (transfer_state == STREAM | transfer_state == TRANSFER_REGISTER | transfer_state == WRITE_ADDRESS) begin + if (cycle_done) begin + sclk_ddr <= 0; + end else begin + sclk_ddr <= !sclk_ddr; + end + end else begin + sclk_ddr <= 0; + end + end + + // 66MHz for full speed + // 16.5 MHz for normal speed + // selection between 66 MHz and 16.5 MHz clocks for the SCLK + // DDR mode requires a phase shift for the t7 and t8 + assign sclk = full_speed ? ((sdr_ddr_n | data_r_wn) ? 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 == STREAM) begin + if (cycle_done == 1'b1) begin + dac_data_ready_s <= stream; + end else begin + dac_data_ready_s <= 1'b0; + end + end else begin + dac_data_ready_s <= 1'b0; + end + if (transfer_state == CS_LOW) begin + full_speed = stream; + if(stream) begin + transfer_reg_single <= {address,dac_data_int, {16{1'b0}}}; + transfer_reg_dual <= {address,dac_data_int, {16{1'b0}}}; + transfer_reg_quad <= {address,dac_data_int, {16{1'b0}}}; + end else begin + transfer_reg_single <= {address,data_write, {24{1'b0}}}; + transfer_reg_dual <= {address,data_write, {24{1'b0}}}; + transfer_reg_quad <= {address,data_write, {24{1'b0}}}; + end + end else if ((transfer_state == STREAM & cycle_done) || (transfer_state != STREAM && transfer_state_next == STREAM)) begin + transfer_reg_single <= {dac_data_int, {24{1'b0}}}; + transfer_reg_dual <= {dac_data_int, {24{1'b0}}}; + transfer_reg_quad <= {dac_data_int, {24{1'b0}}}; + end else if (transfer_step && transfer_state != CS_HIGH) begin + if (multi_io_mode == 2'h2) begin //Quad SPI + transfer_reg_quad <= {transfer_reg_quad[51:0], sdio_i}; + end else if ((multi_io_mode == 2'h0 || multi_io_mode == 2'h3)) begin + transfer_reg_single <= {transfer_reg_single[54:0], sdio_i[1]}; + end else begin //Dual SPI + if (transfer_state == WRITE_ADDRESS) begin + transfer_reg_dual <= {transfer_reg_dual[54:0], sdio_i[0]}; + end else begin + transfer_reg_dual <= {transfer_reg_dual[53:0], sdio_i[1:0]}; + end + end + end + + if (transfer_state == CS_HIGH) begin + if (symb_8_16b == 1'b0) begin + if (multi_io_mode == 2'h2) begin //Quad SPI + data_read <= {8'h0, transfer_reg_quad[15:0]}; + end else if((multi_io_mode == 2'h0 || multi_io_mode == 2'h3)) begin + data_read <= {8'h0, transfer_reg_single[15:0]}; + end else begin + data_read <= {8'h0, transfer_reg_dual[15:0]}; + end + end else begin + if (multi_io_mode == 2'h2) begin //Quad SPI + data_read <= {16'h0, transfer_reg_quad[7:0]}; + end else if((multi_io_mode == 2'h0 || multi_io_mode == 2'h3)) begin //Classic SPI + data_read <= {16'h0, transfer_reg_single[7:0]}; + end else begin //dual SPI + data_read <= {16'h0, transfer_reg_dual[7:0]}; + end + 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[0] = (~(|multi_io_mode)) ? 1'b0 : (data_r_wn && transfer_state == TRANSFER_REGISTER); //for the Single SPI case + assign sdio_t[3:1] = (~(|multi_io_mode)) ? 3'hf : {3{(data_r_wn && transfer_state == TRANSFER_REGISTER)}}; //high-impedance for the Single SPI case + + //multi_io_mode == 0xh3 is undefined, so the Classic SPI is chosen + assign sdio_o = (multi_io_mode == 2'h2) ? transfer_reg_quad[55:52] : + ((multi_io_mode == 2'h0 || multi_io_mode == 2'h3) ? {3'h0, transfer_reg_single[55]} : + ((transfer_state == WRITE_ADDRESS) ? {3'h0, transfer_reg_dual[55]} : + {2'h0, transfer_reg_dual[55:54]})); + +endmodule diff --git a/library/axi_ad35xxr/axi_ad35xxr_if_tb b/library/axi_ad35xxr/axi_ad35xxr_if_tb new file mode 100755 index 0000000000..d59bd3c09d --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr_if_tb @@ -0,0 +1,7 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" axi_ad35xxr_if.v" + +cd `dirname $0` +source ../common/tb/run_tb.sh diff --git a/library/axi_ad35xxr/axi_ad35xxr_if_tb.v b/library/axi_ad35xxr/axi_ad35xxr_if_tb.v new file mode 100644 index 0000000000..74a56f8186 --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr_if_tb.v @@ -0,0 +1,413 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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_ad35xxr_if_tb; + parameter VCD_FILE = "axi_ad35xxr_if_tb.vcd"; + + `define TIMEOUT 9000 + `include "../common/tb/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 [ 3:0] sdio_t; + wire [31:0] dac_data_final; + wire [ 3:0] readback_data_shift; + wire [ 5: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 [ 1:0] multi_io_mode = 2'h1; + 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 [ 5:0] valid_counter = 6'b0; + reg [31:0] dac_data = 32'b0; + + always #3.8 dac_clk <= ~dac_clk; + + initial begin + + #100 reset_in = 1'b0; + + // Write 8 bit SDR + // Classic SPI + + // wait (if_busy == 1'b0); + // address_write = 8'h2c; + // data_write = 24'hab0000; + // multi_io_mode = 2'h0; + // sdr_ddr_n = 1'b1; + // reg_8b_16bn = 1'b1; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Read 8 bit SDR + // Dual SPI + + // wait (if_busy == 1'b0); + // address_write = 8'hac; + // data_write = 24'h000000; + // multi_io_mode = 2'h1; + // sdr_ddr_n = 1'b1; + // reg_8b_16bn = 1'b1; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Write 8 bit SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'h2c; + data_write = 24'hab0000; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 8 bit SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Write 16 bit SDR + // Dual SPI + + // wait (if_busy == 1'b0); + // address_write = 8'h2c; + // data_write = 24'h123400; + // multi_io_mode = 2'h1; + // sdr_ddr_n = 1'b1; + // reg_8b_16bn = 1'b0; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Read 16 bit SDR + // Classic SPI + + // wait (if_busy == 1'b0); + // address_write = 8'hac; + // data_write = 24'h000000; + // multi_io_mode = 2'h0; + // sdr_ddr_n = 1'b1; + // reg_8b_16bn = 1'b0; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Write 16 bit SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'h2c; + data_write = 24'h123400; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 16 bit SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + #500; + + // Write 8 bit + // Classic SPI + + // wait (if_busy == 1'b0); + // address_write = 8'h2c; + // multi_io_mode = 2'h0; + // data_write = 24'h120000; + // sdr_ddr_n = 1'b0; + // reg_8b_16bn = 1'b1; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Read 8 bit DDR + // it must ignore the sdr_ddr_n bit + // and work as SDR + // Dual SPI + + // wait (if_busy == 1'b0); + // address_write = 8'hac; + // data_write = 24'h000000; + // multi_io_mode = 2'h1; + // sdr_ddr_n = 1'b0; + // reg_8b_16bn = 1'b1; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Write 8 bit DDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'h2c; + multi_io_mode = 2'h2; + data_write = 24'h120000; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 8 bit DDR + // it must ignore the sdr_ddr_n bit + // and work as SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b1; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Write 16 bit DDR + // Classic SPI + + // wait (if_busy == 1'b0); + // address_write = 8'h2c; + // data_write = 24'h123400; + // multi_io_mode = 2'h0; + // sdr_ddr_n = 1'b0; + // reg_8b_16bn = 1'b0; + // stream = 1'b0; + // transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Read 16 bit DDR + // it must ignore the sdr_ddr_n bit + // and work as SDR + // Dual SPI + + // wait (if_busy == 1'b0); + // address_write = 8'hac; + // data_write = 24'h000000; + // multi_io_mode = 2'h1; + // sdr_ddr_n = 1'b0; + // reg_8b_16bn = 1'b0; + // stream = 1'b0; + // #500 transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + + // Write 16 bit DDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'h2c; + data_write = 24'h123400; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b0; + stream = 1'b0; + transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + // Read 16 bit DDR + // it must ignore the sdr_ddr_n bit + // and work as SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'hac; + data_write = 24'h000000; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b0; + reg_8b_16bn = 1'b0; + stream = 1'b0; + #500 transfer_data = 1'b1; + #40 transfer_data = 1'b0; + + #500; + + // Stream SDR + // Dual SPI + + // wait (if_busy == 1'b0); + // address_write = 8'h2c; + // multi_io_mode = 2'h1; + // sdr_ddr_n = 1'b1; + // reg_8b_16bn = 1'b0; + // stream = 1'b1; + // transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + // #1000 stream = 1'b0; + + // #500; + + // Stream SDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'h2c; + multi_io_mode = 2'h2; + sdr_ddr_n = 1'b1; + reg_8b_16bn = 1'b0; + stream = 1'b1; + transfer_data = 1'b1; + #40 transfer_data = 1'b0; + #1000 stream = 1'b0; + + #500; + + // Stream DDR + // Dual SPI + + // wait (if_busy == 1'b0); + // address_write = 8'h2c; + // multi_io_mode = 2'h1; + // reg_8b_16bn = 1'b1; + // sdr_ddr_n = 1'b0; + // stream = 1'b1; + // transfer_data = 1'b1; + // #40 transfer_data = 1'b0; + // #1000 stream = 1'b0; + + // #500; + + // Stream DDR + // Quad SPI + + wait (if_busy == 1'b0); + address_write = 8'h2c; + multi_io_mode = 2'h2; + reg_8b_16bn = 1'b1; + sdr_ddr_n = 1'b0; + stream = 1'b1; + transfer_data = 1'b1; + #40 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 ) ? 6'd32: 6'd16; + + always @(posedge dac_clk) begin + if (valid_counter == data_increment_valid) begin + dac_data <= dac_data + 32'h00010002; + valid_counter <= 6'b0; + dac_data_valid <= 1'b1; + end else begin + dac_data <= dac_data; + valid_counter <= valid_counter + 6'b1; + dac_data_valid <= 1'b0; + end + end + + // data is circullary shifted at every sampling edge + + assign readback_data_shift = (sdr_ddr_n | address_write[7]) ? 4'h1 : 4'h0; + assign sdio_i = (sdio_t[1] === 1'b1) ? transfer_reg[31:28] : 2'h0;//transfer_reg[31:30] : 2'h0; + + always @(posedge dac_clk) begin + if (shift_count == readback_data_shift) begin + transfer_reg <= (~(|multi_io_mode)) ? {transfer_reg[30:0],transfer_reg[31]} : {transfer_reg[27:0],transfer_reg[31:28]};//{transfer_reg[29:0],transfer_reg[31:30]}; + end else if (sdio_t[1] === 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] === 1'b1) begin + shift_count <= shift_count + 3'b1; + end + end + + axi_ad35xxr_if axi_ad35xxr_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), + .multi_io_mode(multi_io_mode), + .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_ad35xxr/axi_ad35xxr_ip.tcl b/library/axi_ad35xxr/axi_ad35xxr_ip.tcl new file mode 100644 index 0000000000..0f09d053d0 --- /dev/null +++ b/library/axi_ad35xxr/axi_ad35xxr_ip.tcl @@ -0,0 +1,59 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +source ../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl + +adi_ip_create axi_ad35xxr +adi_ip_files axi_ad35xxr [list \ + "$ad_hdl_dir/library/xilinx/common/ad_mul.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/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_2.v" \ + "$ad_hdl_dir/library/common/ad_dds_1.v" \ + "$ad_hdl_dir/library/common/ad_dds.v" \ + "$ad_hdl_dir/library/common/ad_addsub.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_ad35xxr_channel.v" \ + "axi_ad35xxr_core.v" \ + "axi_ad35xxr_if.v" \ + "axi_ad35xxr.v" ] + +adi_ip_properties axi_ad35xxr +adi_init_bd_tcl +adi_ip_bd axi_ad35xxr "bd/bd.tcl" + +set cc [ipx::current_core] + +set_property company_url {https://wiki.analog.com/resources/fpga/docs/axi_ad35xxr} $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_bus "s_axis" "slave" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"dac_data_ready" "TREADY"} \ + {"valid_in_dma" "TVALID"} \ + {"dma_data" "TDATA"}] +adi_add_bus_clock "dac_clk" "s_axis" + +adi_add_auto_fpga_spec_params + +ipx::create_xgui_files $cc +ipx::save_core $cc diff --git a/projects/ad3542r_evb/Makefile b/projects/ad3542r_evb/Makefile new file mode 100755 index 0000000000..1402069e10 --- /dev/null +++ b/projects/ad3542r_evb/Makefile @@ -0,0 +1,7 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +include ../scripts/project-toplevel.mk diff --git a/projects/ad3542r_evb/Readme.md b/projects/ad3542r_evb/Readme.md new file mode 100755 index 0000000000..a3cd8b3a25 --- /dev/null +++ b/projects/ad3542r_evb/Readme.md @@ -0,0 +1,8 @@ +# AD3552R-EVB HDL Project + +Here are some pointers to help you: + * [Board Product Page](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/eval-ad3542r.html) + * Parts : [ AD3552R Dual Channel, 16-Bit, 33 MUPS, Multispan, Multi-IO SPI DAC ](https://www.analog.com/en/products/AD3542R.html) + * Project Doc: https://wiki.analog.com/resources/eval/user-guides/dac/eval-ad3542r + * HDL Doc: https://wiki.analog.com/resources/eval/user-guides/dac/eval-ad3542r + * Linux Drivers: NA \ No newline at end of file diff --git a/projects/ad3542r_evb/common/ad3542r_evb_bd.tcl b/projects/ad3542r_evb/common/ad3542r_evb_bd.tcl new file mode 100755 index 0000000000..b98e8f6f7c --- /dev/null +++ b/projects/ad3542r_evb/common/ad3542r_evb_bd.tcl @@ -0,0 +1,61 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +create_bd_port -dir O dac_sclk +create_bd_port -dir O dac_csn +create_bd_port -dir I -from 1 -to 0 dac_spi_sdi +create_bd_port -dir O -from 1 -to 0 dac_spi_sdo +create_bd_port -dir O dac_spi_sdo_t + +ad_ip_instance axi_dmac axi_dac_dma +ad_ip_parameter axi_dac_dma CONFIG.DMA_TYPE_SRC 0 +ad_ip_parameter axi_dac_dma CONFIG.DMA_TYPE_DEST 1 +ad_ip_parameter axi_dac_dma CONFIG.CYCLIC 1 +ad_ip_parameter axi_dac_dma CONFIG.SYNC_TRANSFER_START 0 +ad_ip_parameter axi_dac_dma CONFIG.AXI_SLICE_SRC 0 +ad_ip_parameter axi_dac_dma CONFIG.AXI_SLICE_DEST 0 +ad_ip_parameter axi_dac_dma CONFIG.DMA_2D_TRANSFER 0 +ad_ip_parameter axi_dac_dma CONFIG.DMA_DATA_WIDTH_SRC 32 +ad_ip_parameter axi_dac_dma CONFIG.DMA_DATA_WIDTH_DEST 32 + +ad_ip_instance axi_ad3542r axi_ad3542r_dac + +ad_connect axi_ad3542r_dac/dac_sclk dac_sclk +ad_connect axi_ad3542r_dac/dac_csn dac_csn +ad_connect axi_ad3542r_dac/sdio_i dac_spi_sdi +ad_connect axi_ad3542r_dac/sdio_o dac_spi_sdo +ad_connect axi_ad3542r_dac/sdio_t dac_spi_sdo_t +ad_connect axi_ad3542r_dac/dma_data axi_dac_dma/m_axis_data +ad_connect axi_ad3542r_dac/valid_in_dma axi_dac_dma/m_axis_valid +ad_connect axi_ad3542r_dac/dac_data_ready axi_dac_dma/m_axis_ready +ad_connect sys_rstgen/peripheral_aresetn axi_dac_dma/m_src_axi_aresetn + +# Tie unused inputs to GND + +ad_connect axi_ad3542r_dac/valid_in_dma_sec GND +ad_connect axi_ad3542r_dac/data_in_a GND +ad_connect axi_ad3542r_dac/data_in_b GND +ad_connect axi_ad3542r_dac/valid_in_a GND +ad_connect axi_ad3542r_dac/valid_in_b GND +ad_connect axi_ad3542r_dac/external_sync GND + +ad_ip_instance axi_clkgen axi_clkgen +ad_ip_parameter axi_clkgen CONFIG.ID 1 +ad_ip_parameter axi_clkgen CONFIG.CLKIN_PERIOD 10 +ad_ip_parameter axi_clkgen CONFIG.VCO_DIV 1 +ad_ip_parameter axi_clkgen CONFIG.VCO_MUL 8 +ad_ip_parameter axi_clkgen CONFIG.CLK0_DIV 6 + +ad_connect $sys_cpu_clk axi_clkgen/clk +ad_connect axi_clkgen/clk_0 axi_ad3542r_dac/dac_clk +ad_connect axi_clkgen/clk_0 axi_dac_dma/m_axis_aclk + +ad_cpu_interconnect 0x44a30000 axi_dac_dma +ad_cpu_interconnect 0x44a70000 axi_ad3542r_dac +ad_cpu_interconnect 0x44B00000 axi_clkgen + +ad_cpu_interrupt "ps-13" "mb-13" axi_dac_dma/irq + +ad_mem_hp0_interconnect sys_cpu_clk axi_dac_dma/m_src_axi diff --git a/projects/ad3542r_evb/zed/Makefile b/projects/ad3542r_evb/zed/Makefile new file mode 100755 index 0000000000..474af43475 --- /dev/null +++ b/projects/ad3542r_evb/zed/Makefile @@ -0,0 +1,25 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +PROJECT_NAME := ad3542r_evb_zed + +M_DEPS += ../common/ad3542r_evb_bd.tcl +M_DEPS += ../../scripts/adi_pd.tcl +M_DEPS += ../../common/zed/zed_system_constr.xdc +M_DEPS += ../../common/zed/zed_system_bd.tcl +M_DEPS += ../../../library/common/ad_iobuf.v + +LIB_DEPS += axi_ad3542r +LIB_DEPS += axi_clkgen +LIB_DEPS += axi_dmac +LIB_DEPS += axi_hdmi_tx +LIB_DEPS += axi_i2s_adi +LIB_DEPS += axi_spdif_tx +LIB_DEPS += axi_sysid +LIB_DEPS += sysid_rom +LIB_DEPS += util_i2c_mixer + +include ../../scripts/project-xilinx.mk diff --git a/projects/ad3542r_evb/zed/system_bd.tcl b/projects/ad3542r_evb/zed/system_bd.tcl new file mode 100755 index 0000000000..8920d60dc4 --- /dev/null +++ b/projects/ad3542r_evb/zed/system_bd.tcl @@ -0,0 +1,17 @@ +############################################################################### +## Copyright (C) 2022-2024 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +source $ad_hdl_dir/projects/common/zed/zed_system_bd.tcl +source $ad_hdl_dir/projects/scripts/adi_pd.tcl + +# block design +source ../common/ad3542r_evb_bd.tcl + +#system ID +ad_ip_parameter axi_sysid_0 CONFIG.ROM_ADDR_BITS 9 +ad_ip_parameter rom_sys_0 CONFIG.PATH_TO_FILE "$mem_init_sys_file_path/mem_init_sys.txt" +ad_ip_parameter rom_sys_0 CONFIG.ROM_ADDR_BITS 9 + +sysid_gen_sys_init_file diff --git a/projects/ad3542r_evb/zed/system_constr.xdc b/projects/ad3542r_evb/zed/system_constr.xdc new file mode 100755 index 0000000000..94107fc40e --- /dev/null +++ b/projects/ad3542r_evb/zed/system_constr.xdc @@ -0,0 +1,21 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +# ad3542r_fmc SPI interface + +set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS25} [get_ports {ad3542r_spi_sdio[0]}] ; # FMC_LA02_P IO_L20P_T3_34 +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS25} [get_ports {ad3542r_spi_sdio[1]}] ; # FMC_LA02_N IO_L20N_T3_34 + +set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS25 } [get_ports ad3542r_spi_sclk] ; # FMC_LA00_CC_P IO_L13P_T2_MRCC_34 +set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS25 } [get_ports ad3542r_spi_cs] ; # FMC_LA00_CC_N IO_L13N_T2_MRCC_34 + +set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS25} [get_ports ad3542r_ldacn] ; # FMC_LA05_P IO_L7P_T1_34 +set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS25} [get_ports ad3542r_resetn] ; # FMC_LA05_N IO_L7N_T1_34 +set_property -dict {PACKAGE_PIN M21 IOSTANDARD LVCMOS25} [get_ports ad3542r_alertn] ; # FMC_LA04_P IO_L15P_T2_DQS_34 + +set_property -dict {PACKAGE_PIN L21 IOSTANDARD LVCMOS25} [get_ports ad3542r_gpio_6] ; # FMC_LA06_P IO_L10P_T1_34 +set_property -dict {PACKAGE_PIN L22 IOSTANDARD LVCMOS25} [get_ports ad3542r_gpio_7] ; # FMC_LA06_N IO_L10N_T1_34 +set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS25} [get_ports ad3542r_gpio_8] ; # FMC_LA07_P IO_L21P_T3_DQS_34 +set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS25} [get_ports ad3542r_gpio_9] ; # FMC_LA07_N IO_L21N_T3_DQS_34 diff --git a/projects/ad3542r_evb/zed/system_project.tcl b/projects/ad3542r_evb/zed/system_project.tcl new file mode 100755 index 0000000000..6be62b17e6 --- /dev/null +++ b/projects/ad3542r_evb/zed/system_project.tcl @@ -0,0 +1,17 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +source ../../../scripts/adi_env.tcl +source $ad_hdl_dir/projects/scripts/adi_project_xilinx.tcl +source $ad_hdl_dir/projects/scripts/adi_board.tcl + +adi_project ad3542r_evb_zed +adi_project_files ad3542r_evb_zed [list \ + "system_top.v" \ + "system_constr.xdc" \ + "$ad_hdl_dir/projects/common/zed/zed_system_constr.xdc" \ + "$ad_hdl_dir/library/common/ad_iobuf.v" ] + +adi_project_run ad3542r_evb_zed diff --git a/projects/ad3542r_evb/zed/system_top.v b/projects/ad3542r_evb/zed/system_top.v new file mode 100755 index 0000000000..97d1e6b077 --- /dev/null +++ b/projects/ad3542r_evb/zed/system_top.v @@ -0,0 +1,242 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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 system_top ( + + inout [14:0] ddr_addr, + inout [ 2:0] ddr_ba, + inout ddr_cas_n, + inout ddr_ck_n, + inout ddr_ck_p, + inout ddr_cke, + inout ddr_cs_n, + inout [ 3:0] ddr_dm, + inout [31:0] ddr_dq, + inout [ 3:0] ddr_dqs_n, + inout [ 3:0] ddr_dqs_p, + inout ddr_odt, + inout ddr_ras_n, + inout ddr_reset_n, + inout ddr_we_n, + + inout fixed_io_ddr_vrn, + inout fixed_io_ddr_vrp, + inout [53:0] fixed_io_mio, + inout fixed_io_ps_clk, + inout fixed_io_ps_porb, + inout fixed_io_ps_srstb, + + inout [31:0] gpio_bd, + + output hdmi_out_clk, + output hdmi_vsync, + output hdmi_hsync, + output hdmi_data_e, + output [15:0] hdmi_data, + + output spdif, + + output i2s_mclk, + output i2s_bclk, + output i2s_lrclk, + output i2s_sdata_out, + input i2s_sdata_in, + + inout iic_scl, + inout iic_sda, + inout [ 1:0] iic_mux_scl, + inout [ 1:0] iic_mux_sda, + + input otg_vbusoc, + + // dac interface + + inout ad3542r_ldacn, + inout ad3542r_alertn, + inout ad3542r_gpio_6, + inout ad3542r_gpio_7, + inout ad3542r_gpio_8, + inout ad3542r_gpio_9, + inout [ 1:0] ad3542r_spi_sdio, + output ad3542r_resetn, + output ad3542r_spi_cs, + output ad3542r_spi_sclk +); + + // internal signals + + wire [63:0] gpio_i; + wire [63:0] gpio_o; + wire [63:0] gpio_t; + wire [ 1:0] iic_mux_scl_i_s; + wire [ 1:0] iic_mux_scl_o_s; + wire iic_mux_scl_t_s; + wire [ 1:0] iic_mux_sda_i_s; + wire [ 1:0] iic_mux_sda_o_s; + wire iic_mux_sda_t_s; + wire [ 1:0] ad3542r_spi_sdo; + wire [ 1:0] ad3542r_spi_sdi; + wire ad3542r_spi_t; + + assign gpio_i[63:39] = gpio_o[63:39]; + + assign ad3542r_resetn = gpio_o[38]; + + ad_iobuf #( + .DATA_WIDTH(2) + ) i_dac_0_spi_iobuf ( + .dio_t({2{ad3542r_spi_t}}), + .dio_i(ad3542r_spi_sdo), + .dio_o(ad3542r_spi_sdi), + .dio_p(ad3542r_spi_sdio)); + + ad_iobuf #( + .DATA_WIDTH(6) + ) i_ad3542r_iobuf ( + .dio_t(gpio_t[37:32]), + .dio_i(gpio_o[37:32]), + .dio_o(gpio_i[37:32]), + .dio_p({ad3542r_gpio_9, + ad3542r_gpio_8, + ad3542r_gpio_7, + ad3542r_gpio_6, + ad3542r_alertn, + ad3542r_ldacn})); + + ad_iobuf #( + .DATA_WIDTH (32) + ) i_iobuf ( + .dio_t (gpio_t[31:0]), + .dio_i (gpio_o[31:0]), + .dio_o (gpio_i[31:0]), + .dio_p (gpio_bd)); + + ad_iobuf #( + .DATA_WIDTH (2) + ) i_iic_mux_scl ( + .dio_t ({iic_mux_scl_t_s, iic_mux_scl_t_s}), + .dio_i (iic_mux_scl_o_s), + .dio_o (iic_mux_scl_i_s), + .dio_p (iic_mux_scl)); + + ad_iobuf #( + .DATA_WIDTH (2) + ) i_iic_mux_sda ( + .dio_t ({iic_mux_sda_t_s, iic_mux_sda_t_s}), + .dio_i (iic_mux_sda_o_s), + .dio_o (iic_mux_sda_i_s), + .dio_p (iic_mux_sda)); + + system_wrapper i_system_wrapper ( + .ddr_addr (ddr_addr), + .ddr_ba (ddr_ba), + .ddr_cas_n (ddr_cas_n), + .ddr_ck_n (ddr_ck_n), + .ddr_ck_p (ddr_ck_p), + .ddr_cke (ddr_cke), + .ddr_cs_n (ddr_cs_n), + .ddr_dm (ddr_dm), + .ddr_dq (ddr_dq), + .ddr_dqs_n (ddr_dqs_n), + .ddr_dqs_p (ddr_dqs_p), + .ddr_odt (ddr_odt), + .ddr_ras_n (ddr_ras_n), + .ddr_reset_n (ddr_reset_n), + .ddr_we_n (ddr_we_n), + + .fixed_io_ddr_vrn (fixed_io_ddr_vrn), + .fixed_io_ddr_vrp (fixed_io_ddr_vrp), + .fixed_io_mio (fixed_io_mio), + .fixed_io_ps_clk (fixed_io_ps_clk), + .fixed_io_ps_porb (fixed_io_ps_porb), + .fixed_io_ps_srstb (fixed_io_ps_srstb), + + .gpio_i (gpio_i), + .gpio_o (gpio_o), + .gpio_t (gpio_t), + + .hdmi_data (hdmi_data), + .hdmi_data_e (hdmi_data_e), + .hdmi_hsync (hdmi_hsync), + .hdmi_out_clk (hdmi_out_clk), + .hdmi_vsync (hdmi_vsync), + + .spdif (spdif), + + .i2s_bclk (i2s_bclk), + .i2s_lrclk (i2s_lrclk), + .i2s_mclk (i2s_mclk), + .i2s_sdata_in (i2s_sdata_in), + .i2s_sdata_out (i2s_sdata_out), + .iic_fmc_scl_io (iic_scl), + .iic_fmc_sda_io (iic_sda), + .iic_mux_scl_i (iic_mux_scl_i_s), + .iic_mux_scl_o (iic_mux_scl_o_s), + .iic_mux_scl_t (iic_mux_scl_t_s), + .iic_mux_sda_i (iic_mux_sda_i_s), + .iic_mux_sda_o (iic_mux_sda_o_s), + .iic_mux_sda_t (iic_mux_sda_t_s), + + .otg_vbusoc (otg_vbusoc), + + .spi0_clk_i (1'b0), + .spi0_clk_o (), + .spi0_csn_0_o (), + .spi0_csn_1_o (), + .spi0_csn_2_o (), + .spi0_csn_i (1'b1), + .spi0_sdi_i (1'b0), + .spi0_sdo_i (1'b0), + .spi0_sdo_o (), + .spi1_clk_i (1'b0), + .spi1_clk_o (), + .spi1_csn_0_o (), + .spi1_csn_1_o (), + .spi1_csn_2_o (), + .spi1_csn_i (1'b1), + .spi1_sdi_i (1'b0), + .spi1_sdo_i (1'b0), + .spi1_sdo_o (), + + //dac interface + + .dac_sclk(ad3542r_spi_sclk), + .dac_csn(ad3542r_spi_cs), + .dac_spi_sdi(ad3542r_spi_sdi), + .dac_spi_sdo(ad3542r_spi_sdo), + .dac_spi_sdo_t(ad3542r_spi_t)); +endmodule diff --git a/projects/ad35xxr_evb/Makefile b/projects/ad35xxr_evb/Makefile new file mode 100644 index 0000000000..1402069e10 --- /dev/null +++ b/projects/ad35xxr_evb/Makefile @@ -0,0 +1,7 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +include ../scripts/project-toplevel.mk diff --git a/projects/ad35xxr_evb/Readme.md b/projects/ad35xxr_evb/Readme.md new file mode 100644 index 0000000000..4c92e827e6 --- /dev/null +++ b/projects/ad35xxr_evb/Readme.md @@ -0,0 +1,8 @@ +# AD3552R-EVB HDL Project + +Here are some pointers to help you: + * [Board Product Page](https://www.analog.com/eval-ad3552r) + * Parts : [ AD3552R Dual Channel, 16-Bit, 33 MUPS, Multispan, Multi-IO SPI DAC ](https://www.analog.com/en/products/ad3552r.html) + * Project Doc: https://wiki.analog.com/resources/eval/user-guides/dac/ad3552r_eval_zed + * HDL Doc: https://wiki.analog.com/resources/eval/user-guides/dac/ad3552r_eval_zed + * Linux Drivers: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-dac/axi-ad3552r \ No newline at end of file diff --git a/projects/ad35xxr_evb/common/ad35xxr_evb_bd.tcl b/projects/ad35xxr_evb/common/ad35xxr_evb_bd.tcl new file mode 100644 index 0000000000..dfb3801633 --- /dev/null +++ b/projects/ad35xxr_evb/common/ad35xxr_evb_bd.tcl @@ -0,0 +1,65 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +create_bd_port -dir O dac_sclk +create_bd_port -dir O dac_csn +create_bd_port -dir I -from 3 -to 0 dac_spi_sdi +create_bd_port -dir O -from 3 -to 0 dac_spi_sdo +create_bd_port -dir O -from 3 -to 0 dac_spi_sdo_t +create_bd_port -dir O dac_qspi_sel + +ad_ip_instance axi_dmac axi_dac_dma +ad_ip_parameter axi_dac_dma CONFIG.DMA_TYPE_SRC 0 +ad_ip_parameter axi_dac_dma CONFIG.DMA_TYPE_DEST 1 +ad_ip_parameter axi_dac_dma CONFIG.CYCLIC 1 +ad_ip_parameter axi_dac_dma CONFIG.SYNC_TRANSFER_START 0 +ad_ip_parameter axi_dac_dma CONFIG.AXI_SLICE_SRC 0 +ad_ip_parameter axi_dac_dma CONFIG.AXI_SLICE_DEST 0 +ad_ip_parameter axi_dac_dma CONFIG.DMA_2D_TRANSFER 0 +ad_ip_parameter axi_dac_dma CONFIG.DMA_DATA_WIDTH_SRC 32 +ad_ip_parameter axi_dac_dma CONFIG.DMA_DATA_WIDTH_DEST 32 + +ad_ip_instance axi_ad35xxr axi_ad35xxr_dac + +ad_connect axi_ad35xxr_dac/dac_sclk dac_sclk +ad_connect axi_ad35xxr_dac/dac_csn dac_csn +ad_connect axi_ad35xxr_dac/sdio_i dac_spi_sdi +ad_connect axi_ad35xxr_dac/sdio_o dac_spi_sdo +ad_connect axi_ad35xxr_dac/sdio_t dac_spi_sdo_t +ad_connect axi_ad35xxr_dac/qspi_sel dac_qspi_sel + +ad_connect axi_ad35xxr_dac/s_axis axi_dac_dma/m_axis +#ad_connect axi_ad35xxr_dac/dma_data axi_dac_dma/m_axis_data +#ad_connect axi_ad35xxr_dac/valid_in_dma axi_dac_dma/m_axis_valid +#ad_connect axi_ad35xxr_dac/dac_data_ready axi_dac_dma/m_axis_ready +ad_connect sys_rstgen/peripheral_aresetn axi_dac_dma/m_src_axi_aresetn + +# Tie unused inputs to GND + +ad_connect axi_ad35xxr_dac/valid_in_dma_sec GND +ad_connect axi_ad35xxr_dac/data_in_a GND +ad_connect axi_ad35xxr_dac/data_in_b GND +ad_connect axi_ad35xxr_dac/valid_in_a GND +ad_connect axi_ad35xxr_dac/valid_in_b GND +ad_connect axi_ad35xxr_dac/external_sync GND + +ad_ip_instance axi_clkgen axi_clkgen +ad_ip_parameter axi_clkgen CONFIG.ID 1 +ad_ip_parameter axi_clkgen CONFIG.CLKIN_PERIOD 10 +ad_ip_parameter axi_clkgen CONFIG.VCO_DIV 1 +ad_ip_parameter axi_clkgen CONFIG.VCO_MUL 8 +ad_ip_parameter axi_clkgen CONFIG.CLK0_DIV 6 + +ad_connect $sys_cpu_clk axi_clkgen/clk +ad_connect axi_clkgen/clk_0 axi_ad35xxr_dac/dac_clk +ad_connect axi_clkgen/clk_0 axi_dac_dma/m_axis_aclk + +ad_cpu_interconnect 0x44a30000 axi_dac_dma +ad_cpu_interconnect 0x44a70000 axi_ad35xxr_dac +ad_cpu_interconnect 0x44B00000 axi_clkgen + +ad_cpu_interrupt "ps-13" "mb-13" axi_dac_dma/irq + +ad_mem_hp0_interconnect sys_cpu_clk axi_dac_dma/m_src_axi diff --git a/projects/ad35xxr_evb/common/ad35xxr_evb_fmc.txt b/projects/ad35xxr_evb/common/ad35xxr_evb_fmc.txt new file mode 100644 index 0000000000..19e400bd2d --- /dev/null +++ b/projects/ad35xxr_evb/common/ad35xxr_evb_fmc.txt @@ -0,0 +1,18 @@ +# ad35xxr + +FMC_pin FMC_port Schematic_name System_top_name IOSTANDARD Termination + + D12 FMC_LA05_N /RESET ad35xxr_resetn LVCMOS25 #N/A + G6 FMC_LA00_CC_P SPI_SCLK ad35xxr_spi_sclk LVCMOS25 #N/A + G7 FMC_LA00_CC_N SPI_/CS ad35xxr_spi_cs LVCMOS25 #N/A + H7 FMC_LA02_P SPI_SDIO0 ad35xxr_spi_sdio[0] LVCMOS25 #N/A + H8 FMC_LA02_N SPI_SDIO1 ad35xxr_spi_sdio[1] LVCMOS25 #N/A + G9 FMC_LA03_P SPI_SDIO2 ad35xxr_spi_sdio[2] LVCMOS25 #N/A + G10 FMC_LA03_N SPI_SDIO3 ad35xxr_spi_sdio[3] LVCMOS25 #N/A + D11 FMC_LA05_P /LDAC ad35xxr_ldacn LVCMOS25 #N/A + H10 FMC_LA04_P /ALERT ad35xxr_alertn LVCMOS25 #N/A + H11 FMC_LA04_N SPI_QPI ad35xxr_qspi_sel LVCMOS25 #N/A + C10 FMC_LA06_P GPIO_6 ad35xxr_gpio_6 LVCMOS25 #N/A + C11 FMC_LA06_N GPIO_7 ad35xxr_gpio_7 LVCMOS25 #N/A + H13 FMC_LA07_P GPIO_8 ad35xxr_gpio_8 LVCMOS25 #N/A + H14 FMC_LA07_N GPIO_9 ad35xxr_gpio_9 LVCMOS25 #N/A \ No newline at end of file diff --git a/projects/ad35xxr_evb/zed/Makefile b/projects/ad35xxr_evb/zed/Makefile new file mode 100644 index 0000000000..1bd62e8318 --- /dev/null +++ b/projects/ad35xxr_evb/zed/Makefile @@ -0,0 +1,25 @@ +#################################################################################### +## Copyright (c) 2018 - 2023 Analog Devices, Inc. +### SPDX short identifier: BSD-1-Clause +## Auto-generated, do not modify! +#################################################################################### + +PROJECT_NAME := ad35xxr_evb_zed + +M_DEPS += ../common/ad35xxr_evb_bd.tcl +M_DEPS += ../../scripts/adi_pd.tcl +M_DEPS += ../../common/zed/zed_system_constr.xdc +M_DEPS += ../../common/zed/zed_system_bd.tcl +M_DEPS += ../../../library/common/ad_iobuf.v + +LIB_DEPS += axi_ad35xxr +LIB_DEPS += axi_clkgen +LIB_DEPS += axi_dmac +LIB_DEPS += axi_hdmi_tx +LIB_DEPS += axi_i2s_adi +LIB_DEPS += axi_spdif_tx +LIB_DEPS += axi_sysid +LIB_DEPS += sysid_rom +LIB_DEPS += util_i2c_mixer + +include ../../scripts/project-xilinx.mk diff --git a/projects/ad35xxr_evb/zed/system_bd.tcl b/projects/ad35xxr_evb/zed/system_bd.tcl new file mode 100644 index 0000000000..bc6334b409 --- /dev/null +++ b/projects/ad35xxr_evb/zed/system_bd.tcl @@ -0,0 +1,17 @@ +############################################################################### +## Copyright (C) 2022-2024 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +source $ad_hdl_dir/projects/common/zed/zed_system_bd.tcl +source $ad_hdl_dir/projects/scripts/adi_pd.tcl + +# block design +source ../common/ad35xxr_evb_bd.tcl + +#system ID +ad_ip_parameter axi_sysid_0 CONFIG.ROM_ADDR_BITS 9 +ad_ip_parameter rom_sys_0 CONFIG.PATH_TO_FILE "$mem_init_sys_file_path/mem_init_sys.txt" +ad_ip_parameter rom_sys_0 CONFIG.ROM_ADDR_BITS 9 + +sysid_gen_sys_init_file diff --git a/projects/ad35xxr_evb/zed/system_constr.xdc b/projects/ad35xxr_evb/zed/system_constr.xdc new file mode 100644 index 0000000000..aaaff891f0 --- /dev/null +++ b/projects/ad35xxr_evb/zed/system_constr.xdc @@ -0,0 +1,24 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +# ad35xxr_fmc SPI interface + +set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS25} [get_ports {ad35xxr_spi_sdio[0]}] ; # FMC_LA02_P IO_L20P_T3_34 +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS25} [get_ports {ad35xxr_spi_sdio[1]}] ; # FMC_LA02_N IO_L20N_T3_34 +set_property -dict {PACKAGE_PIN N22 IOSTANDARD LVCMOS25} [get_ports {ad35xxr_spi_sdio[2]}] ; # FMC_LA03_P IO_L16P_T2_34 +set_property -dict {PACKAGE_PIN P22 IOSTANDARD LVCMOS25} [get_ports {ad35xxr_spi_sdio[3]}] ; # FMC_LA03_N IO_L16N_T2_34 + +set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS25 } [get_ports ad35xxr_spi_sclk] ; # FMC_LA00_CC_P IO_L13P_T2_MRCC_34 +set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS25 } [get_ports ad35xxr_spi_cs] ; # FMC_LA00_CC_N IO_L13N_T2_MRCC_34 + +set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS25} [get_ports ad35xxr_ldacn] ; # FMC_LA05_P IO_L7P_T1_34 +set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS25} [get_ports ad35xxr_resetn] ; # FMC_LA05_N IO_L7N_T1_34 +set_property -dict {PACKAGE_PIN M21 IOSTANDARD LVCMOS25} [get_ports ad35xxr_alertn] ; # FMC_LA04_P IO_L15P_T2_DQS_34 +set_property -dict {PACKAGE_PIN M22 IOSTANDARD LVCMOS25} [get_ports ad35xxr_qspi_sel] ; # FMC_LA04_N IO_L15N_T2_DQS_34 + +set_property -dict {PACKAGE_PIN L21 IOSTANDARD LVCMOS25} [get_ports ad35xxr_gpio_6] ; # FMC_LA06_P IO_L10P_T1_34 +set_property -dict {PACKAGE_PIN L22 IOSTANDARD LVCMOS25} [get_ports ad35xxr_gpio_7] ; # FMC_LA06_N IO_L10N_T1_34 +set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS25} [get_ports ad35xxr_gpio_8] ; # FMC_LA07_P IO_L21P_T3_DQS_34 +set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS25} [get_ports ad35xxr_gpio_9] ; # FMC_LA07_N IO_L21N_T3_DQS_34 diff --git a/projects/ad35xxr_evb/zed/system_project.tcl b/projects/ad35xxr_evb/zed/system_project.tcl new file mode 100644 index 0000000000..7c8e87d3ef --- /dev/null +++ b/projects/ad35xxr_evb/zed/system_project.tcl @@ -0,0 +1,17 @@ +############################################################################### +## Copyright (C) 2022-2023 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### + +source ../../../scripts/adi_env.tcl +source $ad_hdl_dir/projects/scripts/adi_project_xilinx.tcl +source $ad_hdl_dir/projects/scripts/adi_board.tcl + +adi_project ad35xxr_evb_zed +adi_project_files ad35xxr_evb_zed [list \ + "system_top.v" \ + "system_constr.xdc" \ + "$ad_hdl_dir/projects/common/zed/zed_system_constr.xdc" \ + "$ad_hdl_dir/library/common/ad_iobuf.v" ] + +adi_project_run ad35xxr_evb_zed diff --git a/projects/ad35xxr_evb/zed/system_top.v b/projects/ad35xxr_evb/zed/system_top.v new file mode 100644 index 0000000000..bbaf29d0c8 --- /dev/null +++ b/projects/ad35xxr_evb/zed/system_top.v @@ -0,0 +1,244 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2022-2023 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/main/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 system_top ( + + inout [14:0] ddr_addr, + inout [ 2:0] ddr_ba, + inout ddr_cas_n, + inout ddr_ck_n, + inout ddr_ck_p, + inout ddr_cke, + inout ddr_cs_n, + inout [ 3:0] ddr_dm, + inout [31:0] ddr_dq, + inout [ 3:0] ddr_dqs_n, + inout [ 3:0] ddr_dqs_p, + inout ddr_odt, + inout ddr_ras_n, + inout ddr_reset_n, + inout ddr_we_n, + + inout fixed_io_ddr_vrn, + inout fixed_io_ddr_vrp, + inout [53:0] fixed_io_mio, + inout fixed_io_ps_clk, + inout fixed_io_ps_porb, + inout fixed_io_ps_srstb, + + inout [31:0] gpio_bd, + + output hdmi_out_clk, + output hdmi_vsync, + output hdmi_hsync, + output hdmi_data_e, + output [15:0] hdmi_data, + + output spdif, + + output i2s_mclk, + output i2s_bclk, + output i2s_lrclk, + output i2s_sdata_out, + input i2s_sdata_in, + + inout iic_scl, + inout iic_sda, + inout [ 1:0] iic_mux_scl, + inout [ 1:0] iic_mux_sda, + + input otg_vbusoc, + + // dac interface + + inout ad35xxr_ldacn, + inout ad35xxr_alertn, + inout ad35xxr_gpio_6, + inout ad35xxr_gpio_7, + inout ad35xxr_gpio_8, + inout ad35xxr_gpio_9, + inout [ 3:0] ad35xxr_spi_sdio, + output ad35xxr_resetn, + output ad35xxr_qspi_sel, + output ad35xxr_spi_cs, + output ad35xxr_spi_sclk +); + + // internal signals + + wire [63:0] gpio_i; + wire [63:0] gpio_o; + wire [63:0] gpio_t; + wire [ 1:0] iic_mux_scl_i_s; + wire [ 1:0] iic_mux_scl_o_s; + wire iic_mux_scl_t_s; + wire [ 1:0] iic_mux_sda_i_s; + wire [ 1:0] iic_mux_sda_o_s; + wire iic_mux_sda_t_s; + wire [ 3:0] ad35xxr_spi_sdo; + wire [ 3:0] ad35xxr_spi_sdi; + wire [ 3:0] ad35xxr_spi_t; + + assign gpio_i[63:39] = gpio_o[63:39]; + + assign ad35xxr_resetn = gpio_o[38]; + + ad_iobuf #( + .DATA_WIDTH(4) + ) i_dac_0_spi_iobuf ( + .dio_t({ad35xxr_spi_t}), + .dio_i(ad35xxr_spi_sdo), + .dio_o(ad35xxr_spi_sdi), + .dio_p(ad35xxr_spi_sdio)); + + ad_iobuf #( + .DATA_WIDTH(6) + ) i_ad35xxr_iobuf ( + .dio_t(gpio_t[37:32]), + .dio_i(gpio_o[37:32]), + .dio_o(gpio_i[37:32]), + .dio_p({ad35xxr_gpio_9, + ad35xxr_gpio_8, + ad35xxr_gpio_7, + ad35xxr_gpio_6, + ad35xxr_alertn, + ad35xxr_ldacn})); + + ad_iobuf #( + .DATA_WIDTH (32) + ) i_iobuf ( + .dio_t (gpio_t[31:0]), + .dio_i (gpio_o[31:0]), + .dio_o (gpio_i[31:0]), + .dio_p (gpio_bd)); + + ad_iobuf #( + .DATA_WIDTH (2) + ) i_iic_mux_scl ( + .dio_t ({iic_mux_scl_t_s, iic_mux_scl_t_s}), + .dio_i (iic_mux_scl_o_s), + .dio_o (iic_mux_scl_i_s), + .dio_p (iic_mux_scl)); + + ad_iobuf #( + .DATA_WIDTH (2) + ) i_iic_mux_sda ( + .dio_t ({iic_mux_sda_t_s, iic_mux_sda_t_s}), + .dio_i (iic_mux_sda_o_s), + .dio_o (iic_mux_sda_i_s), + .dio_p (iic_mux_sda)); + + system_wrapper i_system_wrapper ( + .ddr_addr (ddr_addr), + .ddr_ba (ddr_ba), + .ddr_cas_n (ddr_cas_n), + .ddr_ck_n (ddr_ck_n), + .ddr_ck_p (ddr_ck_p), + .ddr_cke (ddr_cke), + .ddr_cs_n (ddr_cs_n), + .ddr_dm (ddr_dm), + .ddr_dq (ddr_dq), + .ddr_dqs_n (ddr_dqs_n), + .ddr_dqs_p (ddr_dqs_p), + .ddr_odt (ddr_odt), + .ddr_ras_n (ddr_ras_n), + .ddr_reset_n (ddr_reset_n), + .ddr_we_n (ddr_we_n), + + .fixed_io_ddr_vrn (fixed_io_ddr_vrn), + .fixed_io_ddr_vrp (fixed_io_ddr_vrp), + .fixed_io_mio (fixed_io_mio), + .fixed_io_ps_clk (fixed_io_ps_clk), + .fixed_io_ps_porb (fixed_io_ps_porb), + .fixed_io_ps_srstb (fixed_io_ps_srstb), + + .gpio_i (gpio_i), + .gpio_o (gpio_o), + .gpio_t (gpio_t), + + .hdmi_data (hdmi_data), + .hdmi_data_e (hdmi_data_e), + .hdmi_hsync (hdmi_hsync), + .hdmi_out_clk (hdmi_out_clk), + .hdmi_vsync (hdmi_vsync), + + .spdif (spdif), + + .i2s_bclk (i2s_bclk), + .i2s_lrclk (i2s_lrclk), + .i2s_mclk (i2s_mclk), + .i2s_sdata_in (i2s_sdata_in), + .i2s_sdata_out (i2s_sdata_out), + .iic_fmc_scl_io (iic_scl), + .iic_fmc_sda_io (iic_sda), + .iic_mux_scl_i (iic_mux_scl_i_s), + .iic_mux_scl_o (iic_mux_scl_o_s), + .iic_mux_scl_t (iic_mux_scl_t_s), + .iic_mux_sda_i (iic_mux_sda_i_s), + .iic_mux_sda_o (iic_mux_sda_o_s), + .iic_mux_sda_t (iic_mux_sda_t_s), + + .otg_vbusoc (otg_vbusoc), + + .spi0_clk_i (1'b0), + .spi0_clk_o (), + .spi0_csn_0_o (), + .spi0_csn_1_o (), + .spi0_csn_2_o (), + .spi0_csn_i (1'b1), + .spi0_sdi_i (1'b0), + .spi0_sdo_i (1'b0), + .spi0_sdo_o (), + .spi1_clk_i (1'b0), + .spi1_clk_o (), + .spi1_csn_0_o (), + .spi1_csn_1_o (), + .spi1_csn_2_o (), + .spi1_csn_i (1'b1), + .spi1_sdi_i (1'b0), + .spi1_sdo_i (1'b0), + .spi1_sdo_o (), + + //dac interface + + .dac_sclk(ad35xxr_spi_sclk), + .dac_csn(ad35xxr_spi_cs), + .dac_spi_sdi(ad35xxr_spi_sdi), + .dac_spi_sdo(ad35xxr_spi_sdo), + .dac_spi_sdo_t(ad35xxr_spi_t), + .dac_qspi_sel(ad35xxr_qspi_sel)); +endmodule