initial commit, add dds_par module
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
###############################################################################
|
||||
## Copyright (C) 2018-2023 Analog Devices, Inc.
|
||||
### SPDX short identifier: BSD-1-Clause
|
||||
## Auto-generated, do not modify!
|
||||
###############################################################################
|
||||
|
||||
LIBRARY_NAME := axi_ltc235x
|
||||
|
||||
GENERIC_DEPS += ../common/ad_rst.v
|
||||
GENERIC_DEPS += ../common/up_adc_channel.v
|
||||
GENERIC_DEPS += ../common/up_adc_common.v
|
||||
GENERIC_DEPS += ../common/up_axi.v
|
||||
GENERIC_DEPS += ../common/up_clock_mon.v
|
||||
GENERIC_DEPS += ../common/up_xfer_cntrl.v
|
||||
GENERIC_DEPS += ../common/up_xfer_status.v
|
||||
GENERIC_DEPS += axi_ltc235x.v
|
||||
GENERIC_DEPS += axi_ltc235x_cmos.v
|
||||
GENERIC_DEPS += axi_ltc235x_lvds.v
|
||||
|
||||
INTEL_DEPS += ../intel/common/up_clock_mon_constr.sdc
|
||||
INTEL_DEPS += ../intel/common/up_rst_constr.sdc
|
||||
INTEL_DEPS += ../intel/common/up_xfer_cntrl_constr.sdc
|
||||
INTEL_DEPS += ../intel/common/up_xfer_status_constr.sdc
|
||||
INTEL_DEPS += axi_ltc235x_hw.tcl
|
||||
|
||||
include ../scripts/library.mk
|
||||
@@ -0,0 +1,512 @@
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
// Copyright (C) 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:
|
||||
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
|
||||
//
|
||||
// OR
|
||||
//
|
||||
// 2. An ADI specific BSD license, which can be found in the top level directory
|
||||
// of this repository (LICENSE_ADIBSD), and also on-line at:
|
||||
// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD
|
||||
// This will allow to generate bit files and not release the source code,
|
||||
// as long as it attaches to an ADI device.
|
||||
//
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
module axi_ltc235x #(
|
||||
|
||||
parameter ID = 0,
|
||||
parameter XILINX_INTEL_N = 0,
|
||||
parameter FPGA_TECHNOLOGY = 0,
|
||||
parameter FPGA_FAMILY = 0,
|
||||
parameter SPEED_GRADE = 0,
|
||||
parameter DEV_PACKAGE = 0,
|
||||
parameter LVDS_CMOS_N = 0,
|
||||
parameter LANE_0_ENABLE = 1,
|
||||
parameter LANE_1_ENABLE = 1,
|
||||
parameter LANE_2_ENABLE = 1,
|
||||
parameter LANE_3_ENABLE = 1,
|
||||
parameter LANE_4_ENABLE = 1,
|
||||
parameter LANE_5_ENABLE = 1,
|
||||
parameter LANE_6_ENABLE = 1,
|
||||
parameter LANE_7_ENABLE = 1,
|
||||
parameter EXTERNAL_CLK = 0,
|
||||
parameter LTC235X_FAMILY = 0,
|
||||
parameter NUM_CHANNELS = 8,
|
||||
parameter DATA_WIDTH = 18
|
||||
) (
|
||||
|
||||
// physical data interface
|
||||
|
||||
input external_clk,
|
||||
|
||||
// common
|
||||
input busy,
|
||||
output lvds_cmos_n,
|
||||
|
||||
// cmos
|
||||
output sdi,
|
||||
output scki,
|
||||
input scko,
|
||||
input [ 7:0] sdo,
|
||||
|
||||
// lvds
|
||||
output sdi_p,
|
||||
output sdi_n,
|
||||
output scki_p,
|
||||
output scki_n,
|
||||
input scko_p,
|
||||
input scko_n,
|
||||
input sdo_p,
|
||||
input sdo_n,
|
||||
|
||||
// AXI Slave Memory Map
|
||||
|
||||
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,
|
||||
|
||||
// Write FIFO interface
|
||||
|
||||
input adc_dovf,
|
||||
output adc_valid_0,
|
||||
output adc_valid_1,
|
||||
output adc_valid_2,
|
||||
output adc_valid_3,
|
||||
output adc_valid_4,
|
||||
output adc_valid_5,
|
||||
output adc_valid_6,
|
||||
output adc_valid_7,
|
||||
output adc_enable_0,
|
||||
output adc_enable_1,
|
||||
output adc_enable_2,
|
||||
output adc_enable_3,
|
||||
output adc_enable_4,
|
||||
output adc_enable_5,
|
||||
output adc_enable_6,
|
||||
output adc_enable_7,
|
||||
output [31:0] adc_data_0,
|
||||
output [31:0] adc_data_1,
|
||||
output [31:0] adc_data_2,
|
||||
output [31:0] adc_data_3,
|
||||
output [31:0] adc_data_4,
|
||||
output [31:0] adc_data_5,
|
||||
output [31:0] adc_data_6,
|
||||
output [31:0] adc_data_7
|
||||
);
|
||||
|
||||
// localparam
|
||||
|
||||
localparam [ 7:0] ACTIVE_LANES = {
|
||||
LANE_7_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_6_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_5_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_4_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_3_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_2_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_1_ENABLE == 1 ? 1'b1 : 1'b0,
|
||||
LANE_0_ENABLE == 1 ? 1'b1 : 1'b0};
|
||||
localparam [ 0:0] RD_RAW_DATA = 1'b1;
|
||||
localparam [ 0:0] CMOS_OR_LVDS_N = ~LVDS_CMOS_N[0];
|
||||
localparam [31:0] CONFIG = {18'd0, RD_RAW_DATA, 5'b0, CMOS_OR_LVDS_N, 7'b0}; // truncated value with size 45 to match size of target (32)
|
||||
|
||||
// internal registers
|
||||
|
||||
reg up_wack = 1'b0;
|
||||
reg up_rack = 1'b0;
|
||||
reg [31:0] up_rdata = 32'b0;
|
||||
|
||||
// internal signals
|
||||
|
||||
wire [23:0] softspan_24;
|
||||
wire [ 2:0] softspan_3[0:7];
|
||||
|
||||
wire adc_valid;
|
||||
|
||||
wire up_clk;
|
||||
wire up_rstn;
|
||||
wire up_rreq_s;
|
||||
wire [13:0] up_raddr_s;
|
||||
wire up_wreq_s;
|
||||
wire [13:0] up_waddr_s;
|
||||
|
||||
wire adc_clk_s;
|
||||
|
||||
wire [13:0] up_addr_s;
|
||||
wire [31:0] up_wdata_s;
|
||||
wire [31:0] up_rdata_s[0:8];
|
||||
wire [ 8:0] up_rack_s;
|
||||
wire [ 8:0] up_wack_s;
|
||||
|
||||
// read raw, feature
|
||||
wire rd_req_s;
|
||||
wire wr_req_s;
|
||||
wire [15:0] wr_data_s;
|
||||
wire [15:0] rd_data_s;
|
||||
wire rd_valid_s;
|
||||
|
||||
wire adc_rst_s;
|
||||
|
||||
wire [ 7:0] adc_enable;
|
||||
wire [ 2:0] adc_status_header[0:7];
|
||||
wire [31:0] adc_data[0:7];
|
||||
|
||||
// defaults
|
||||
|
||||
assign up_clk = s_axi_aclk;
|
||||
assign up_rstn = s_axi_aresetn;
|
||||
|
||||
assign lvds_cmos_n = LVDS_CMOS_N[0];
|
||||
|
||||
assign adc_valid_0 = adc_valid;
|
||||
assign adc_valid_1 = adc_valid;
|
||||
assign adc_valid_2 = adc_valid;
|
||||
assign adc_valid_3 = adc_valid;
|
||||
assign adc_valid_4 = adc_valid;
|
||||
assign adc_valid_5 = adc_valid;
|
||||
assign adc_valid_6 = adc_valid;
|
||||
assign adc_valid_7 = adc_valid;
|
||||
|
||||
assign adc_enable_0 = adc_enable[0];
|
||||
assign adc_enable_1 = adc_enable[1];
|
||||
assign adc_enable_2 = adc_enable[2];
|
||||
assign adc_enable_3 = adc_enable[3];
|
||||
assign adc_enable_4 = adc_enable[4];
|
||||
assign adc_enable_5 = adc_enable[5];
|
||||
assign adc_enable_6 = adc_enable[6];
|
||||
assign adc_enable_7 = adc_enable[7];
|
||||
|
||||
assign adc_data_0 = adc_data[0];
|
||||
assign adc_data_1 = adc_data[1];
|
||||
assign adc_data_2 = adc_data[2];
|
||||
assign adc_data_3 = adc_data[3];
|
||||
assign adc_data_4 = adc_data[4];
|
||||
assign adc_data_5 = adc_data[5];
|
||||
assign adc_data_6 = adc_data[6];
|
||||
assign adc_data_7 = adc_data[7];
|
||||
|
||||
generate
|
||||
if (NUM_CHANNELS == 8) begin
|
||||
assign softspan_24 = {softspan_3[7], softspan_3[6], softspan_3[5], softspan_3[4], softspan_3[3], softspan_3[2], softspan_3[1], softspan_3[0]};
|
||||
end else if (NUM_CHANNELS == 4) begin
|
||||
assign softspan_24 = {softspan_3[3], softspan_3[2], softspan_3[1], softspan_3[0], 12'b0};
|
||||
end else begin
|
||||
assign softspan_24 = {softspan_3[1], softspan_3[0], 18'b0};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// processor read/write interface
|
||||
|
||||
always @(negedge up_rstn or posedge up_clk) begin
|
||||
if (up_rstn == 0) begin
|
||||
up_wack <= 'd0;
|
||||
up_rack <= 'd0;
|
||||
up_rdata <= 'd0;
|
||||
end else begin
|
||||
up_wack <= |up_wack_s;
|
||||
up_rack <= |up_rack_s;
|
||||
up_rdata <= up_rdata_s[0] |
|
||||
up_rdata_s[1] |
|
||||
up_rdata_s[2] |
|
||||
up_rdata_s[3] |
|
||||
up_rdata_s[4] |
|
||||
up_rdata_s[5] |
|
||||
up_rdata_s[6] |
|
||||
up_rdata_s[7] |
|
||||
up_rdata_s[8];
|
||||
end
|
||||
end
|
||||
|
||||
// CMOS/LVDS INTERFACE
|
||||
generate
|
||||
if (EXTERNAL_CLK == 1'b1) begin
|
||||
assign adc_clk_s = external_clk;
|
||||
end else begin
|
||||
assign adc_clk_s = up_clk;
|
||||
end
|
||||
|
||||
if (LVDS_CMOS_N == 1) begin
|
||||
axi_ltc235x_lvds #(
|
||||
.XILINX_INTEL_N (XILINX_INTEL_N),
|
||||
.LTC235X_FAMILY (LTC235X_FAMILY),
|
||||
.NUM_CHANNELS (NUM_CHANNELS),
|
||||
.DATA_WIDTH (DATA_WIDTH)
|
||||
) i_ltc235x_lvds (
|
||||
.rst (adc_rst_s),
|
||||
.clk (adc_clk_s),
|
||||
.adc_enable (adc_enable),
|
||||
.softspan_next (softspan_24),
|
||||
.scki_p (scki_p),
|
||||
.scki_n (scki_n),
|
||||
.sdi_p (sdi_p),
|
||||
.sdi_n (sdi_n),
|
||||
.scko_p (scko_p),
|
||||
.scko_n (scko_n),
|
||||
.sdo_p (sdo_p),
|
||||
.sdo_n (sdo_n),
|
||||
.busy (busy),
|
||||
.adc_ch0_id (adc_status_header[0]),
|
||||
.adc_ch1_id (adc_status_header[1]),
|
||||
.adc_ch2_id (adc_status_header[2]),
|
||||
.adc_ch3_id (adc_status_header[3]),
|
||||
.adc_ch4_id (adc_status_header[4]),
|
||||
.adc_ch5_id (adc_status_header[5]),
|
||||
.adc_ch6_id (adc_status_header[6]),
|
||||
.adc_ch7_id (adc_status_header[7]),
|
||||
.adc_data_0 (adc_data_0),
|
||||
.adc_data_1 (adc_data_1),
|
||||
.adc_data_2 (adc_data_2),
|
||||
.adc_data_3 (adc_data_3),
|
||||
.adc_data_4 (adc_data_4),
|
||||
.adc_data_5 (adc_data_5),
|
||||
.adc_data_6 (adc_data_6),
|
||||
.adc_data_7 (adc_data_7),
|
||||
.adc_softspan_0 (),
|
||||
.adc_softspan_1 (),
|
||||
.adc_softspan_2 (),
|
||||
.adc_softspan_3 (),
|
||||
.adc_softspan_4 (),
|
||||
.adc_softspan_5 (),
|
||||
.adc_softspan_6 (),
|
||||
.adc_softspan_7 (),
|
||||
.adc_valid (adc_valid));
|
||||
end else begin
|
||||
axi_ltc235x_cmos #(
|
||||
.LTC235X_FAMILY (LTC235X_FAMILY),
|
||||
.ACTIVE_LANES (ACTIVE_LANES),
|
||||
.NUM_CHANNELS (NUM_CHANNELS),
|
||||
.DATA_WIDTH (DATA_WIDTH)
|
||||
) i_ltc235x_cmos (
|
||||
.rst (adc_rst_s),
|
||||
.clk (adc_clk_s),
|
||||
.adc_enable (adc_enable),
|
||||
.softspan_next (softspan_24),
|
||||
.scki (scki),
|
||||
.sdi (sdi),
|
||||
.scko (scko),
|
||||
.sdo (sdo),
|
||||
.busy (busy),
|
||||
.adc_ch0_id (adc_status_header[0]),
|
||||
.adc_ch1_id (adc_status_header[1]),
|
||||
.adc_ch2_id (adc_status_header[2]),
|
||||
.adc_ch3_id (adc_status_header[3]),
|
||||
.adc_ch4_id (adc_status_header[4]),
|
||||
.adc_ch5_id (adc_status_header[5]),
|
||||
.adc_ch6_id (adc_status_header[6]),
|
||||
.adc_ch7_id (adc_status_header[7]),
|
||||
.adc_data_0 (adc_data_0),
|
||||
.adc_data_1 (adc_data_1),
|
||||
.adc_data_2 (adc_data_2),
|
||||
.adc_data_3 (adc_data_3),
|
||||
.adc_data_4 (adc_data_4),
|
||||
.adc_data_5 (adc_data_5),
|
||||
.adc_data_6 (adc_data_6),
|
||||
.adc_data_7 (adc_data_7),
|
||||
.adc_softspan_0 (),
|
||||
.adc_softspan_1 (),
|
||||
.adc_softspan_2 (),
|
||||
.adc_softspan_3 (),
|
||||
.adc_softspan_4 (),
|
||||
.adc_softspan_5 (),
|
||||
.adc_softspan_6 (),
|
||||
.adc_softspan_7 (),
|
||||
.adc_valid (adc_valid));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// regmap adc channels
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for (i = 0; i < NUM_CHANNELS; i=i+1) begin : regmap_channels
|
||||
up_adc_channel #(
|
||||
.CHANNEL_ID(i)
|
||||
) i_up_adc_channel (
|
||||
.adc_clk (adc_clk_s),
|
||||
.adc_rst (adc_rst_s),
|
||||
.adc_enable (adc_enable[i]),
|
||||
.adc_iqcor_enb (),
|
||||
.adc_dcfilt_enb (),
|
||||
.adc_dfmt_se (),
|
||||
.adc_dfmt_type (),
|
||||
.adc_dfmt_enable (),
|
||||
.adc_dcfilt_offset (),
|
||||
.adc_dcfilt_coeff (),
|
||||
.adc_iqcor_coeff_1 (),
|
||||
.adc_iqcor_coeff_2 (),
|
||||
.adc_pnseq_sel (),
|
||||
.adc_data_sel (),
|
||||
.adc_pn_err (1'b0),
|
||||
.adc_pn_oos (1'b0),
|
||||
.adc_or (1'b0),
|
||||
.adc_read_data (adc_data[i]),
|
||||
.adc_status_header({5'd0, adc_status_header[i]}),
|
||||
.adc_crc_err(1'b0),
|
||||
.adc_softspan (softspan_3[i]),
|
||||
.up_adc_crc_err (),
|
||||
.up_adc_pn_err (),
|
||||
.up_adc_pn_oos (),
|
||||
.up_adc_or (),
|
||||
.up_usr_datatype_be (),
|
||||
.up_usr_datatype_signed (),
|
||||
.up_usr_datatype_shift (),
|
||||
.up_usr_datatype_total_bits (),
|
||||
.up_usr_datatype_bits (),
|
||||
.up_usr_decimation_m (),
|
||||
.up_usr_decimation_n (),
|
||||
.adc_usr_datatype_be (1'b0),
|
||||
.adc_usr_datatype_signed (1'b1),
|
||||
.adc_usr_datatype_shift (8'd0),
|
||||
.adc_usr_datatype_total_bits (8'd32),
|
||||
.adc_usr_datatype_bits (8'd32),
|
||||
.adc_usr_decimation_m (16'd1),
|
||||
.adc_usr_decimation_n (16'd1),
|
||||
.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[i]),
|
||||
.up_rreq (up_rreq_s),
|
||||
.up_raddr (up_raddr_s),
|
||||
.up_rdata (up_rdata_s[i]),
|
||||
.up_rack (up_rack_s[i]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// up adc common
|
||||
|
||||
up_adc_common #(
|
||||
.ID(ID),
|
||||
.CONFIG(CONFIG)
|
||||
) i_up_adc_common (
|
||||
.mmcm_rst (),
|
||||
.adc_clk (adc_clk_s),
|
||||
.adc_rst (adc_rst_s),
|
||||
.adc_r1_mode (),
|
||||
.adc_ddr_edgesel (),
|
||||
.adc_pin_mode (),
|
||||
.adc_status ('h1),
|
||||
.adc_sync_status (1'b1),
|
||||
.adc_status_ovf (adc_dovf),
|
||||
.adc_clk_ratio (32'd1),
|
||||
.adc_start_code (),
|
||||
.adc_sref_sync (),
|
||||
.adc_sync (),
|
||||
.adc_ext_sync_arm(),
|
||||
.adc_ext_sync_disarm(),
|
||||
.adc_ext_sync_manual_req(),
|
||||
.adc_num_lanes(),
|
||||
.adc_custom_control(),
|
||||
.adc_crc_enable(),
|
||||
.adc_sdr_ddr_n(),
|
||||
.adc_symb_op(),
|
||||
.adc_symb_8_16b(),
|
||||
.up_pps_rcounter (32'b0),
|
||||
.up_pps_status (1'b0),
|
||||
.up_pps_irq_mask (),
|
||||
.up_adc_r1_mode(),
|
||||
.up_adc_ce (),
|
||||
.up_status_pn_err (1'b0),
|
||||
.up_status_pn_oos (1'b0),
|
||||
.up_status_or (1'b0),
|
||||
.up_drp_sel (),
|
||||
.up_drp_wr (),
|
||||
.up_drp_addr (),
|
||||
.up_drp_wdata (),
|
||||
.up_drp_rdata (32'd0),
|
||||
.up_drp_ready (1'd0),
|
||||
.up_drp_locked (1'd1),
|
||||
.adc_config_wr (),
|
||||
.adc_config_ctrl (),
|
||||
.adc_config_rd (32'd0),
|
||||
.adc_ctrl_status (1'd0),
|
||||
.up_usr_chanmax_out (),
|
||||
.up_usr_chanmax_in (8),
|
||||
.up_adc_gpio_in (32'b0),
|
||||
.up_adc_gpio_out (),
|
||||
.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[8]),
|
||||
.up_rreq (up_rreq_s),
|
||||
.up_raddr (up_raddr_s),
|
||||
.up_rdata (up_rdata_s[8]),
|
||||
.up_rack (up_rack_s[8]));
|
||||
|
||||
// up bus interface
|
||||
|
||||
up_axi #(
|
||||
.AXI_ADDRESS_WIDTH (16)
|
||||
) 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),
|
||||
.up_rreq (up_rreq_s),
|
||||
.up_raddr (up_raddr_s),
|
||||
.up_rdata (up_rdata),
|
||||
.up_rack (up_rack));
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,529 @@
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
// Copyright (C) 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:
|
||||
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
|
||||
//
|
||||
// OR
|
||||
//
|
||||
// 2. An ADI specific BSD license, which can be found in the top level directory
|
||||
// of this repository (LICENSE_ADIBSD), and also on-line at:
|
||||
// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD
|
||||
// This will allow to generate bit files and not release the source code,
|
||||
// as long as it attaches to an ADI device.
|
||||
//
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
module axi_ltc235x_cmos #(
|
||||
parameter ACTIVE_LANES = 8'b1111_1111,
|
||||
parameter LTC235X_FAMILY = 0,
|
||||
parameter NUM_CHANNELS = 8, // 8 for 2358, 4 for 2357, 2 for 2353
|
||||
parameter DATA_WIDTH = 18 // 18 or 16 based on -18/-16
|
||||
) (
|
||||
|
||||
input rst,
|
||||
input clk,
|
||||
input [ 7:0] adc_enable,
|
||||
input [23:0] softspan_next,
|
||||
|
||||
// physical interface
|
||||
|
||||
output scki,
|
||||
output sdi,
|
||||
input scko,
|
||||
input [ 7:0] sdo,
|
||||
input busy,
|
||||
|
||||
// FIFO interface
|
||||
|
||||
output [ 2:0] adc_ch0_id,
|
||||
output [ 2:0] adc_ch1_id,
|
||||
output [ 2:0] adc_ch2_id,
|
||||
output [ 2:0] adc_ch3_id,
|
||||
output [ 2:0] adc_ch4_id,
|
||||
output [ 2:0] adc_ch5_id,
|
||||
output [ 2:0] adc_ch6_id,
|
||||
output [ 2:0] adc_ch7_id,
|
||||
|
||||
output [31:0] adc_data_0,
|
||||
output [31:0] adc_data_1,
|
||||
output [31:0] adc_data_2,
|
||||
output [31:0] adc_data_3,
|
||||
output [31:0] adc_data_4,
|
||||
output [31:0] adc_data_5,
|
||||
output [31:0] adc_data_6,
|
||||
output [31:0] adc_data_7,
|
||||
|
||||
output [ 2:0] adc_softspan_0,
|
||||
output [ 2:0] adc_softspan_1,
|
||||
output [ 2:0] adc_softspan_2,
|
||||
output [ 2:0] adc_softspan_3,
|
||||
output [ 2:0] adc_softspan_4,
|
||||
output [ 2:0] adc_softspan_5,
|
||||
output [ 2:0] adc_softspan_6,
|
||||
output [ 2:0] adc_softspan_7,
|
||||
|
||||
output reg adc_valid
|
||||
);
|
||||
|
||||
localparam DW = 24; // packet size
|
||||
localparam BW = DW - 1;
|
||||
|
||||
// internal registers
|
||||
|
||||
reg busy_m1;
|
||||
reg busy_m2;
|
||||
reg busy_m3;
|
||||
|
||||
reg [ 4:0] scki_counter = 5'h0;
|
||||
reg [ 4:0] data_counter = 5'h0;
|
||||
|
||||
reg scki_i;
|
||||
reg scki_d;
|
||||
|
||||
reg [BW:0] adc_lane_0;
|
||||
reg [BW:0] adc_lane_1;
|
||||
reg [BW:0] adc_lane_2;
|
||||
reg [BW:0] adc_lane_3;
|
||||
reg [BW:0] adc_lane_4;
|
||||
reg [BW:0] adc_lane_5;
|
||||
reg [BW:0] adc_lane_6;
|
||||
reg [BW:0] adc_lane_7;
|
||||
|
||||
reg [BW:0] adc_data_init[7:0];
|
||||
reg [BW:0] adc_data_store[7:0];
|
||||
|
||||
reg [ 2:0] lane_0_ch = 3'd0;
|
||||
reg [ 2:0] lane_1_ch = 3'd0;
|
||||
reg [ 2:0] lane_2_ch = 3'd0;
|
||||
reg [ 2:0] lane_3_ch = 3'd0;
|
||||
reg [ 2:0] lane_4_ch = 3'd0;
|
||||
reg [ 2:0] lane_5_ch = 3'd0;
|
||||
reg [ 2:0] lane_6_ch = 3'd0;
|
||||
reg [ 2:0] lane_7_ch = 3'd0;
|
||||
|
||||
reg [ 3:0] adc_lane0_shift;
|
||||
reg [ 3:0] adc_lane1_shift;
|
||||
reg [ 3:0] adc_lane2_shift;
|
||||
reg [ 3:0] adc_lane3_shift;
|
||||
reg [ 3:0] adc_lane4_shift;
|
||||
reg [ 3:0] adc_lane5_shift;
|
||||
reg [ 3:0] adc_lane6_shift;
|
||||
reg [ 3:0] adc_lane7_shift;
|
||||
|
||||
reg [ 3:0] adc_lane0_shift_d;
|
||||
reg [ 3:0] adc_lane1_shift_d;
|
||||
reg [ 3:0] adc_lane2_shift_d;
|
||||
reg [ 3:0] adc_lane3_shift_d;
|
||||
reg [ 3:0] adc_lane4_shift_d;
|
||||
reg [ 3:0] adc_lane5_shift_d;
|
||||
reg [ 3:0] adc_lane6_shift_d;
|
||||
reg [ 3:0] adc_lane7_shift_d;
|
||||
|
||||
reg adc_valid_init;
|
||||
reg adc_valid_init_d;
|
||||
|
||||
reg [ 7:0] ch_data_lock = 8'hff;
|
||||
reg [ 7:0] ch_capture;
|
||||
reg [ 7:0] ch_captured;
|
||||
|
||||
reg scko_d;
|
||||
reg [ 7:0] sdo_d;
|
||||
|
||||
reg [ 4:0] sdi_index = 5'd23;
|
||||
|
||||
reg [23:0] softspan_next_int;
|
||||
|
||||
// internal wires
|
||||
|
||||
wire start_transfer_s;
|
||||
|
||||
wire scki_cnt_rst;
|
||||
|
||||
wire acquire_data;
|
||||
|
||||
wire [17:0] adc_data_raw_s [7:0];
|
||||
wire [31:0] adc_data_sign_s [7:0];
|
||||
wire [31:0] adc_data_zero_s [7:0];
|
||||
wire [31:0] adc_data_s [7:0];
|
||||
wire [ 2:0] adc_ch_id_s [7:0];
|
||||
wire [ 2:0] adc_softspan_s [7:0];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
busy_m1 <= 1'b0;
|
||||
busy_m2 <= 1'b0;
|
||||
end else begin
|
||||
busy_m1 <= busy;
|
||||
busy_m2 <= busy_m1;
|
||||
busy_m3 <= busy_m2;
|
||||
end
|
||||
end
|
||||
|
||||
assign start_transfer_s = busy_m3 & ~busy_m2;
|
||||
|
||||
// reading clock logic
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
scki_counter <= 5'h0;
|
||||
scki_i <= 1'b1;
|
||||
scki_d <= 1'b0;
|
||||
end else begin
|
||||
scki_d <= scki_i;
|
||||
if (acquire_data == 1'b0) begin
|
||||
scki_counter <= 5'h0;
|
||||
scki_i <= 1'b1;
|
||||
end else if (scki_cnt_rst & (scki_d & ~scki_i)) begin // end of a capture
|
||||
scki_counter <= 5'h1;
|
||||
scki_i <= 1'b1;
|
||||
end else if (scki_i == 1'b0) begin
|
||||
scki_counter <= scki_counter + 5'd1;
|
||||
scki_i <= 1'b1;
|
||||
end else begin
|
||||
scki_counter <= scki_counter;
|
||||
scki_i <= ~scki_i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign scki_cnt_rst = (scki_counter == DW);
|
||||
assign scki = scki_i | ~acquire_data;
|
||||
|
||||
/*
|
||||
The device sends each channel data on one of the 8 lines.
|
||||
Data is stored in the device in a ring buffer. After the first packet is read
|
||||
and no new conversion is requested if the reading process is restarted,
|
||||
the new data on the lines will be from the next index from the ring buffer.
|
||||
e.g For second read process without a conversion start
|
||||
line 0 = channel 1, line 1 = channel 2, line 2 = channel 3; so on and so forth.
|
||||
|
||||
The ring buffer contains the crc data on the 8(last position.)
|
||||
e.g for a 4'th reading cycle:
|
||||
line 0 = ch 3
|
||||
line 1 = ch 4
|
||||
line 2 = ch 5
|
||||
line 3 = ch 6
|
||||
line 4 = ch 7
|
||||
line 5 = crc
|
||||
line 6 = ch 0
|
||||
line 7 = ch 1
|
||||
|
||||
Because there is no rule for a specific number of lanes to be enabled at a given time
|
||||
the interface can handle every combination of enabled lanes with enabled channels.
|
||||
The valid signal will only be asserted after all enabled channels are stored.
|
||||
This means that the user must adjust the sampling frequency based on the
|
||||
interface clock frequency and the maximum position/index
|
||||
difference +1 of a channel data and the first enabled lane that will
|
||||
pass that channels data, maximum difference is 8(e.g line 0 to line 7).
|
||||
e.g. If only lanes 1 and 2(0 to 7) are enabled,
|
||||
1. The user wants to capture the 6'th(0 to 7) channel, 5 reading cycles are required.
|
||||
2. The user wants to capture channel 0, 8 reading cycles are required.
|
||||
*/
|
||||
|
||||
// capture data per lane in rx buffers adc_lane_X on every edge of scko
|
||||
// ignore when busy forced scko to 0
|
||||
always @(posedge clk) begin
|
||||
scko_d <= scko;
|
||||
sdo_d <= sdo;
|
||||
if (scko != scko_d && scki != scki_d) begin
|
||||
adc_lane_0 <= {adc_lane_0[BW-1:0], sdo_d[0]};
|
||||
adc_lane_1 <= {adc_lane_1[BW-1:0], sdo_d[1]};
|
||||
adc_lane_2 <= {adc_lane_2[BW-1:0], sdo_d[2]};
|
||||
adc_lane_3 <= {adc_lane_3[BW-1:0], sdo_d[3]};
|
||||
adc_lane_4 <= {adc_lane_4[BW-1:0], sdo_d[4]};
|
||||
adc_lane_5 <= {adc_lane_5[BW-1:0], sdo_d[5]};
|
||||
adc_lane_6 <= {adc_lane_6[BW-1:0], sdo_d[6]};
|
||||
adc_lane_7 <= {adc_lane_7[BW-1:0], sdo_d[7]};
|
||||
end
|
||||
end
|
||||
|
||||
// store the data from the rx buffers when all bits are received
|
||||
// when data transaction window is done
|
||||
// index is based by lane
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_data_init[0] <= 'h0;
|
||||
adc_data_init[1] <= 'h0;
|
||||
adc_data_init[2] <= 'h0;
|
||||
adc_data_init[3] <= 'h0;
|
||||
adc_data_init[4] <= 'h0;
|
||||
adc_data_init[5] <= 'h0;
|
||||
adc_data_init[6] <= 'h0;
|
||||
adc_data_init[7] <= 'h0;
|
||||
data_counter <= 5'h0;
|
||||
end else begin
|
||||
data_counter <= scki_counter;
|
||||
if (data_counter == DW) begin
|
||||
adc_data_init[0] <= adc_lane_0;
|
||||
adc_data_init[1] <= adc_lane_1;
|
||||
adc_data_init[2] <= adc_lane_2;
|
||||
adc_data_init[3] <= adc_lane_3;
|
||||
adc_data_init[4] <= adc_lane_4;
|
||||
adc_data_init[5] <= adc_lane_5;
|
||||
adc_data_init[6] <= adc_lane_6;
|
||||
adc_data_init[7] <= adc_lane_7;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// lane_x_ch - channel corresponds to which lane, e.g. lane_0_ch stores the current channel lane 0 has
|
||||
// ch_data_lock[i] - locks ch i, e.g. ch_data_lock[7] = 1 means data from channel 7 has already been sent to an active lane, channel 7 should now be locked
|
||||
// dont acquire data if all channels are all already locked
|
||||
always @(posedge clk) begin
|
||||
if (start_transfer_s) begin
|
||||
lane_0_ch <= 3'd0;
|
||||
lane_1_ch <= 3'd1;
|
||||
lane_2_ch <= 3'd2;
|
||||
lane_3_ch <= 3'd3;
|
||||
lane_4_ch <= 3'd4;
|
||||
lane_5_ch <= 3'd5;
|
||||
lane_6_ch <= 3'd6;
|
||||
lane_7_ch <= 3'd7;
|
||||
ch_data_lock <= 8'd0;
|
||||
end else if (acquire_data == 1'b1 && (scki_cnt_rst & (~scki_d & scki_i))) begin
|
||||
lane_0_ch <= lane_0_ch + 3'd1;
|
||||
lane_1_ch <= lane_1_ch + 3'd1;
|
||||
lane_2_ch <= lane_2_ch + 3'd1;
|
||||
lane_3_ch <= lane_3_ch + 3'd1;
|
||||
lane_4_ch <= lane_4_ch + 3'd1;
|
||||
lane_5_ch <= lane_5_ch + 3'd1;
|
||||
lane_6_ch <= lane_6_ch + 3'd1;
|
||||
lane_7_ch <= lane_7_ch + 3'd1;
|
||||
ch_data_lock[lane_0_ch] <= ACTIVE_LANES[0] ? 1'b1 : ch_data_lock[lane_0_ch];
|
||||
ch_data_lock[lane_1_ch] <= ACTIVE_LANES[1] ? 1'b1 : ch_data_lock[lane_1_ch];
|
||||
ch_data_lock[lane_2_ch] <= ACTIVE_LANES[2] ? 1'b1 : ch_data_lock[lane_2_ch];
|
||||
ch_data_lock[lane_3_ch] <= ACTIVE_LANES[3] ? 1'b1 : ch_data_lock[lane_3_ch];
|
||||
ch_data_lock[lane_4_ch] <= ACTIVE_LANES[4] ? 1'b1 : ch_data_lock[lane_4_ch];
|
||||
ch_data_lock[lane_5_ch] <= ACTIVE_LANES[5] ? 1'b1 : ch_data_lock[lane_5_ch];
|
||||
ch_data_lock[lane_6_ch] <= ACTIVE_LANES[6] ? 1'b1 : ch_data_lock[lane_6_ch];
|
||||
ch_data_lock[lane_7_ch] <= ACTIVE_LANES[7] ? 1'b1 : ch_data_lock[lane_7_ch];
|
||||
end
|
||||
end
|
||||
|
||||
assign acquire_data = ~((ch_data_lock[0] | ~adc_enable[0]) &
|
||||
(ch_data_lock[1] | ~adc_enable[1]) &
|
||||
(ch_data_lock[2] | ~adc_enable[2]) &
|
||||
(ch_data_lock[3] | ~adc_enable[3]) &
|
||||
(ch_data_lock[4] | ~adc_enable[4]) &
|
||||
(ch_data_lock[5] | ~adc_enable[5]) &
|
||||
(ch_data_lock[6] | ~adc_enable[6]) &
|
||||
(ch_data_lock[7] | ~adc_enable[7]));
|
||||
|
||||
// hold lane status and lane channel
|
||||
// for datasyncing with valid signal
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1 || adc_valid == 1'b1) begin
|
||||
adc_lane0_shift <= 4'd0;
|
||||
adc_lane1_shift <= 4'd0;
|
||||
adc_lane2_shift <= 4'd0;
|
||||
adc_lane3_shift <= 4'd0;
|
||||
adc_lane4_shift <= 4'd0;
|
||||
adc_lane5_shift <= 4'd0;
|
||||
adc_lane6_shift <= 4'd0;
|
||||
adc_lane7_shift <= 4'd0;
|
||||
adc_lane0_shift_d <= 4'd0;
|
||||
adc_lane1_shift_d <= 4'd0;
|
||||
adc_lane2_shift_d <= 4'd0;
|
||||
adc_lane3_shift_d <= 4'd0;
|
||||
adc_lane4_shift_d <= 4'd0;
|
||||
adc_lane5_shift_d <= 4'd0;
|
||||
adc_lane6_shift_d <= 4'd0;
|
||||
adc_lane7_shift_d <= 4'd0;
|
||||
end else begin
|
||||
adc_lane0_shift <= {ACTIVE_LANES[0], lane_0_ch};
|
||||
adc_lane1_shift <= {ACTIVE_LANES[1], lane_1_ch};
|
||||
adc_lane2_shift <= {ACTIVE_LANES[2], lane_2_ch};
|
||||
adc_lane3_shift <= {ACTIVE_LANES[3], lane_3_ch};
|
||||
adc_lane4_shift <= {ACTIVE_LANES[4], lane_4_ch};
|
||||
adc_lane5_shift <= {ACTIVE_LANES[5], lane_5_ch};
|
||||
adc_lane6_shift <= {ACTIVE_LANES[6], lane_6_ch};
|
||||
adc_lane7_shift <= {ACTIVE_LANES[7], lane_7_ch};
|
||||
adc_lane0_shift_d <= adc_lane0_shift;
|
||||
adc_lane1_shift_d <= adc_lane1_shift;
|
||||
adc_lane2_shift_d <= adc_lane2_shift;
|
||||
adc_lane3_shift_d <= adc_lane3_shift;
|
||||
adc_lane4_shift_d <= adc_lane4_shift;
|
||||
adc_lane5_shift_d <= adc_lane5_shift;
|
||||
adc_lane6_shift_d <= adc_lane6_shift;
|
||||
adc_lane7_shift_d <= adc_lane7_shift;
|
||||
end
|
||||
end
|
||||
|
||||
// stores the data from the rx buffer, but now based on ch
|
||||
// index is based on ch, not lane anymore
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_data_store[0] <= 'd0;
|
||||
adc_data_store[1] <= 'd0;
|
||||
adc_data_store[2] <= 'd0;
|
||||
adc_data_store[3] <= 'd0;
|
||||
adc_data_store[4] <= 'd0;
|
||||
adc_data_store[5] <= 'd0;
|
||||
adc_data_store[6] <= 'd0;
|
||||
adc_data_store[7] <= 'd0;
|
||||
end else begin
|
||||
if (!adc_valid_init_d & adc_valid_init) begin
|
||||
if (adc_lane0_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane0_shift_d[2:0]] <= adc_data_init[0];
|
||||
end
|
||||
if (adc_lane1_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane1_shift_d[2:0]] <= adc_data_init[1];
|
||||
end
|
||||
if (adc_lane2_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane2_shift_d[2:0]] <= adc_data_init[2];
|
||||
end
|
||||
if (adc_lane3_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane3_shift_d[2:0]] <= adc_data_init[3];
|
||||
end
|
||||
if (adc_lane4_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane4_shift_d[2:0]] <= adc_data_init[4];
|
||||
end
|
||||
if (adc_lane5_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane5_shift_d[2:0]] <= adc_data_init[5];
|
||||
end
|
||||
if (adc_lane6_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane6_shift_d[2:0]] <= adc_data_init[6];
|
||||
end
|
||||
if (adc_lane7_shift_d[3] == 1'b1) begin
|
||||
adc_data_store[adc_lane7_shift_d[2:0]] <= adc_data_init[7];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// extract info from the data bits
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < 8; i=i+1) begin: format
|
||||
assign adc_data_raw_s[i] = adc_data_store[i][BW:DW-DATA_WIDTH];
|
||||
assign adc_data_sign_s[i] = {{(32-DATA_WIDTH){adc_data_raw_s[i][DATA_WIDTH-1]}}, adc_data_raw_s[i]};
|
||||
assign adc_data_zero_s[i] = {{(32-DATA_WIDTH){1'b0}}, adc_data_raw_s[i]};
|
||||
assign adc_data_s[i] = (adc_softspan_s[i] == 3'b0)? 32'h0 :
|
||||
(adc_softspan_s[i][1])? adc_data_sign_s[i] :
|
||||
adc_data_zero_s[i] ;
|
||||
if (NUM_CHANNELS == 8) begin
|
||||
assign adc_ch_id_s[i] = adc_data_store[i][5:3];
|
||||
end else if (NUM_CHANNELS == 4) begin
|
||||
assign adc_ch_id_s[i] = {1'b0, adc_data_store[i][4:3]};
|
||||
end else begin
|
||||
assign adc_ch_id_s[i] = {2'b0, adc_data_store[i][3]};
|
||||
end
|
||||
assign adc_softspan_s[i] = adc_data_store[i][2:0];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// assign extracted adc data to corresponding outputs
|
||||
assign adc_data_0 = adc_data_s[0];
|
||||
assign adc_data_1 = adc_data_s[1];
|
||||
assign adc_data_2 = adc_data_s[2];
|
||||
assign adc_data_3 = adc_data_s[3];
|
||||
assign adc_data_4 = adc_data_s[4];
|
||||
assign adc_data_5 = adc_data_s[5];
|
||||
assign adc_data_6 = adc_data_s[6];
|
||||
assign adc_data_7 = adc_data_s[7];
|
||||
|
||||
// assign extracted adc channel id to corresponding outputs
|
||||
assign adc_ch0_id = adc_ch_id_s[0];
|
||||
assign adc_ch1_id = adc_ch_id_s[1];
|
||||
assign adc_ch2_id = adc_ch_id_s[2];
|
||||
assign adc_ch3_id = adc_ch_id_s[3];
|
||||
assign adc_ch4_id = adc_ch_id_s[4];
|
||||
assign adc_ch5_id = adc_ch_id_s[5];
|
||||
assign adc_ch6_id = adc_ch_id_s[6];
|
||||
assign adc_ch7_id = adc_ch_id_s[7];
|
||||
|
||||
// assign extracted adc channel id to corresponding outputs
|
||||
assign adc_softspan_0 = adc_softspan_s[0];
|
||||
assign adc_softspan_1 = adc_softspan_s[1];
|
||||
assign adc_softspan_2 = adc_softspan_s[2];
|
||||
assign adc_softspan_3 = adc_softspan_s[3];
|
||||
assign adc_softspan_4 = adc_softspan_s[4];
|
||||
assign adc_softspan_5 = adc_softspan_s[5];
|
||||
assign adc_softspan_6 = adc_softspan_s[6];
|
||||
assign adc_softspan_7 = adc_softspan_s[7];
|
||||
|
||||
// initial valid signal
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_valid_init <= 1'b0;
|
||||
end else begin
|
||||
if (data_counter == DW && adc_valid_init == 1'b0) begin
|
||||
adc_valid_init <= 1'b1;
|
||||
end else begin
|
||||
adc_valid_init <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// delayed both valid signal and data_lock signal
|
||||
// for datasyncing with valid signal
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1 || adc_valid == 1'b1) begin
|
||||
adc_valid <= 1'b0;
|
||||
adc_valid_init_d <= 1'b0;
|
||||
ch_capture <= 8'd0;
|
||||
ch_captured <= 8'd0;
|
||||
end else begin
|
||||
ch_capture <= ch_data_lock;
|
||||
ch_captured <= ch_capture;
|
||||
adc_valid_init_d <= adc_valid_init;
|
||||
adc_valid <= adc_valid_init_d &
|
||||
(ch_captured[0] | ~adc_enable[0]) &
|
||||
(ch_captured[1] | ~adc_enable[1]) &
|
||||
(ch_captured[2] | ~adc_enable[2]) &
|
||||
(ch_captured[3] | ~adc_enable[3]) &
|
||||
(ch_captured[4] | ~adc_enable[4]) &
|
||||
(ch_captured[5] | ~adc_enable[5]) &
|
||||
(ch_captured[6] | ~adc_enable[6]) &
|
||||
(ch_captured[7] | ~adc_enable[7]);
|
||||
end
|
||||
end
|
||||
|
||||
// every negedge of scki, update index of sdi
|
||||
always @(posedge clk) begin
|
||||
if (start_transfer_s || rst) begin
|
||||
sdi_index <= 5'd23;
|
||||
end else begin
|
||||
if (scki && !scki_d && sdi_index != 5'b11111) begin
|
||||
sdi_index <= sdi_index - 5'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// update next softspan configuration every after busy
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
softspan_next_int <= 24'hff_ffff;
|
||||
end else begin
|
||||
if (busy_m3 & ~busy_m2) begin
|
||||
softspan_next_int <= softspan_next;
|
||||
end else begin
|
||||
softspan_next_int <= softspan_next_int;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign sdi = (sdi_index != 5'b11111)? softspan_next_int[sdi_index] : 1'b0;
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,97 @@
|
||||
###############################################################################
|
||||
## Copyright (C) 2023 Analog Devices, Inc. All rights reserved.
|
||||
### SPDX short identifier: ADIBSD
|
||||
###############################################################################
|
||||
# ip
|
||||
|
||||
package require qsys 14.0
|
||||
package require quartus::device
|
||||
|
||||
source ../../scripts/adi_env.tcl
|
||||
source ../scripts/adi_ip_intel.tcl
|
||||
|
||||
ad_ip_create axi_ltc235x {AXI LTC235x Interface} axi_ltc235x_elab
|
||||
set_module_property AUTHOR {Geronimo, John Erasmus Mari F.}
|
||||
set_module_property VALIDATION_CALLBACK info_param_validate
|
||||
ad_ip_files axi_ltc235x [list \
|
||||
$ad_hdl_dir/library/common/up_axi.v \
|
||||
$ad_hdl_dir/library/common/up_adc_common.v \
|
||||
$ad_hdl_dir/library/common/ad_rst.v \
|
||||
$ad_hdl_dir/library/common/up_xfer_cntrl.v \
|
||||
$ad_hdl_dir/library/common/up_xfer_status.v \
|
||||
$ad_hdl_dir/library/common/up_clock_mon.v \
|
||||
$ad_hdl_dir/library/common/up_adc_channel.v \
|
||||
$ad_hdl_dir/library/intel/common/up_xfer_cntrl_constr.sdc \
|
||||
$ad_hdl_dir/library/intel/common/up_rst_constr.sdc \
|
||||
$ad_hdl_dir/library/intel/common/up_xfer_status_constr.sdc \
|
||||
$ad_hdl_dir/library/intel/common/up_clock_mon_constr.sdc \
|
||||
axi_ltc235x_cmos.v \
|
||||
axi_ltc235x_lvds.v \
|
||||
axi_ltc235x.v]
|
||||
add_documentation_link "AXI_LTC235x IP core" https://wiki.analog.com/resources/fpga/docs/axi_ltc235x
|
||||
|
||||
ad_ip_parameter ID INTEGER 0
|
||||
ad_ip_parameter XILINX_INTEL_N INTEGER 0
|
||||
ad_ip_parameter LVDS_CMOS_N INTEGER 0
|
||||
ad_ip_parameter LANE_0_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_1_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_2_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_3_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_4_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_5_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_6_ENABLE INTEGER 1
|
||||
ad_ip_parameter LANE_7_ENABLE INTEGER 1
|
||||
ad_ip_parameter EXTERNAL_CLK INTEGER 0
|
||||
ad_ip_parameter LTC235X_FAMILY INTEGER 0
|
||||
ad_ip_parameter NUM_CHANNELS INTEGER 8
|
||||
ad_ip_parameter DATA_WIDTH INTEGER 18
|
||||
|
||||
adi_add_auto_fpga_spec_params
|
||||
|
||||
proc axi_ltc235x_elab {} {
|
||||
# interfaces
|
||||
|
||||
# physical interface
|
||||
add_interface device_if conduit end
|
||||
# common
|
||||
add_interface_port device_if busy busy Input 1
|
||||
add_interface_port device_if lvds_cmos_n lvds_cmos_n Output 1
|
||||
|
||||
set interface [get_parameter_value LVDS_CMOS_N]
|
||||
switch $interface {
|
||||
"0" { ;# cmos
|
||||
add_interface_port device_if scki scki Output 1
|
||||
add_interface_port device_if scko scko Input 1
|
||||
add_interface_port device_if sdi sdi Output 1
|
||||
add_interface_port device_if sdo sdo Input 8}
|
||||
"1" { ;# lvds
|
||||
add_interface_port device_if scki_p scki_p Output 1
|
||||
add_interface_port device_if scki_n scki_n Output 1
|
||||
add_interface_port device_if scko_p scko_p Input 1
|
||||
add_interface_port device_if scko_n scko_n Input 1
|
||||
add_interface_port device_if sdi_p sdi_p Output 1
|
||||
add_interface_port device_if sdi_n sdi_n Output 1
|
||||
add_interface_port device_if sdo_p sdo_p Input 1
|
||||
add_interface_port device_if sdo_n sdo_n Input 1}
|
||||
}
|
||||
|
||||
# clock
|
||||
ad_interface clock external_clk input 1
|
||||
|
||||
# axi
|
||||
ad_ip_intf_s_axi s_axi_aclk s_axi_aresetn
|
||||
|
||||
# others
|
||||
ad_interface signal adc_dovf Input 1 ovf
|
||||
|
||||
set num_channels [get_parameter_value NUM_CHANNELS]
|
||||
for {set i 0} {$i < $num_channels} {incr i} {
|
||||
add_interface adc_ch_$i conduit end
|
||||
add_interface_port adc_ch_$i adc_enable_$i enable Output 1
|
||||
add_interface_port adc_ch_$i adc_valid_$i valid Output 1
|
||||
add_interface_port adc_ch_$i adc_data_$i data Output 32
|
||||
|
||||
set_interface_property adc_ch_$i associatedClock if_external_clk
|
||||
set_interface_property adc_ch_$i associatedReset ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
// Copyright (C) 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:
|
||||
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
|
||||
//
|
||||
// OR
|
||||
//
|
||||
// 2. An ADI specific BSD license, which can be found in the top level directory
|
||||
// of this repository (LICENSE_ADIBSD), and also on-line at:
|
||||
// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD
|
||||
// This will allow to generate bit files and not release the source code,
|
||||
// as long as it attaches to an ADI device.
|
||||
//
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
module axi_ltc235x_lvds #(
|
||||
parameter XILINX_INTEL_N = 0,
|
||||
parameter LTC235X_FAMILY = 0,
|
||||
parameter NUM_CHANNELS = 8, // 8 for 2358, 4 for 2357, 2 for 2353
|
||||
parameter DATA_WIDTH = 18 // 18 or 16 based on -18/-16
|
||||
) (
|
||||
|
||||
input rst,
|
||||
input clk,
|
||||
input [ 7:0] adc_enable,
|
||||
input [23:0] softspan_next,
|
||||
|
||||
// physical interface
|
||||
|
||||
output scki_p,
|
||||
output scki_n,
|
||||
output sdi_p,
|
||||
output sdi_n,
|
||||
input scko_p,
|
||||
input scko_n,
|
||||
input sdo_p,
|
||||
input sdo_n,
|
||||
input busy,
|
||||
|
||||
// FIFO interface
|
||||
|
||||
output [ 2:0] adc_ch0_id,
|
||||
output [ 2:0] adc_ch1_id,
|
||||
output [ 2:0] adc_ch2_id,
|
||||
output [ 2:0] adc_ch3_id,
|
||||
output [ 2:0] adc_ch4_id,
|
||||
output [ 2:0] adc_ch5_id,
|
||||
output [ 2:0] adc_ch6_id,
|
||||
output [ 2:0] adc_ch7_id,
|
||||
|
||||
output [31:0] adc_data_0,
|
||||
output [31:0] adc_data_1,
|
||||
output [31:0] adc_data_2,
|
||||
output [31:0] adc_data_3,
|
||||
output [31:0] adc_data_4,
|
||||
output [31:0] adc_data_5,
|
||||
output [31:0] adc_data_6,
|
||||
output [31:0] adc_data_7,
|
||||
|
||||
output [ 2:0] adc_softspan_0,
|
||||
output [ 2:0] adc_softspan_1,
|
||||
output [ 2:0] adc_softspan_2,
|
||||
output [ 2:0] adc_softspan_3,
|
||||
output [ 2:0] adc_softspan_4,
|
||||
output [ 2:0] adc_softspan_5,
|
||||
output [ 2:0] adc_softspan_6,
|
||||
output [ 2:0] adc_softspan_7,
|
||||
|
||||
output reg adc_valid
|
||||
);
|
||||
|
||||
// local parameters
|
||||
|
||||
localparam DW = 24; // packet size per channel
|
||||
localparam DW_8 = 24 * 8; // packet size for all 8 channels
|
||||
localparam BW = DW - 1;
|
||||
localparam BW_8 = DW_8 - 1;
|
||||
|
||||
// internal registers
|
||||
|
||||
reg busy_m1;
|
||||
reg busy_m2;
|
||||
reg busy_m3;
|
||||
|
||||
reg [ 8:0] scki_counter = 9'h0;
|
||||
reg [ 8:0] data_counter = 9'h0;
|
||||
|
||||
reg scki_i;
|
||||
reg scki_d;
|
||||
|
||||
reg [BW_8:0] adc_lane;
|
||||
reg [BW_8:0] adc_data_init;
|
||||
reg [ BW:0] adc_data_store[7:0];
|
||||
|
||||
reg adc_valid_init;
|
||||
reg adc_valid_init_d;
|
||||
|
||||
reg ch_data_lock = 1;
|
||||
reg ch_capture;
|
||||
reg ch_captured;
|
||||
|
||||
reg scko_d;
|
||||
reg sdo_d;
|
||||
|
||||
reg [ 4:0] sdi_index = 5'd23;
|
||||
|
||||
reg [23:0] softspan_next_int;
|
||||
|
||||
// internal wires
|
||||
|
||||
wire start_transfer_s;
|
||||
|
||||
wire scki_cnt_rst;
|
||||
|
||||
wire acquire_data;
|
||||
|
||||
wire [DATA_WIDTH-1:0] adc_data_raw_s [7:0];
|
||||
wire [31:0] adc_data_sign_s [7:0];
|
||||
wire [31:0] adc_data_zero_s [7:0];
|
||||
wire [31:0] adc_data_s [7:0];
|
||||
wire [ 2:0] adc_ch_id_s [7:0];
|
||||
wire [ 2:0] adc_softspan_s [7:0];
|
||||
|
||||
wire scki_s;
|
||||
wire sdi_s;
|
||||
wire scko_s;
|
||||
wire sdo_s;
|
||||
|
||||
generate
|
||||
if (XILINX_INTEL_N == 0) begin
|
||||
assign scki_p = scki_s;
|
||||
assign scki_n = 1'b0;
|
||||
assign sdi_p = sdi_s;
|
||||
assign sdi_n = 1'b0;
|
||||
assign scko_s = scko_p;
|
||||
assign sdo_s = sdo_p;
|
||||
end else begin
|
||||
OBUFDS obufds_scki (
|
||||
.O(scki_n),
|
||||
.OB(scki_p),
|
||||
.I(scki_s));
|
||||
|
||||
OBUFDS obufds_sdi (
|
||||
.O(sdi_n),
|
||||
.OB(sdi_p),
|
||||
.I(sdi_s));
|
||||
|
||||
IBUFDS #(
|
||||
.CCIO_EN_M("TRUE"),
|
||||
.CCIO_EN_S("TRUE")
|
||||
) ibufds_scko (
|
||||
.O(scko_s),
|
||||
.I(scko_p),
|
||||
.IB(scko_n));
|
||||
|
||||
IBUFDS #(
|
||||
.CCIO_EN_M("TRUE"),
|
||||
.CCIO_EN_S("TRUE")
|
||||
) ibufds_sdo (
|
||||
.O(sdo_s),
|
||||
.I(sdo_p),
|
||||
.IB(sdo_n));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
busy_m1 <= 1'b0;
|
||||
busy_m2 <= 1'b0;
|
||||
end else begin
|
||||
busy_m1 <= busy;
|
||||
busy_m2 <= busy_m1;
|
||||
busy_m3 <= busy_m2;
|
||||
end
|
||||
end
|
||||
|
||||
assign start_transfer_s = busy_m3 & ~busy_m2;
|
||||
|
||||
// reading clock logic
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
scki_counter <= 9'h0;
|
||||
scki_i <= 1'b0;
|
||||
scki_d <= 1'b0;
|
||||
end else begin
|
||||
scki_d <= scki_i;
|
||||
if (acquire_data == 1'b0) begin
|
||||
scki_counter <= 9'h0;
|
||||
scki_i <= 1'b0;
|
||||
end else if (scki_cnt_rst & (scki_d != scki_i)) begin // end of a capture
|
||||
scki_counter <= 9'h1;
|
||||
scki_i <= 1'b0;
|
||||
end else begin
|
||||
scki_counter <= scki_counter + 9'd1;
|
||||
scki_i <= ~scki_i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign scki_cnt_rst = (scki_counter == DW_8);
|
||||
assign scki_s = scki_i & acquire_data;
|
||||
|
||||
// capture data per lane in rx buffer on every edge of scko_s
|
||||
// ignore when busy forced scko_s to 0
|
||||
always @(posedge clk) begin
|
||||
scko_d <= scko_s;
|
||||
sdo_d <= sdo_s;
|
||||
if (scko_s != scko_d && scki_s != scki_d) begin
|
||||
adc_lane <= {adc_lane[BW_8-1:0], sdo_d};
|
||||
end
|
||||
end
|
||||
|
||||
// store the data from the rx buffers when all bits are received
|
||||
// when data transaction window is done
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_data_init <= 'h0;
|
||||
data_counter <= 9'h0;
|
||||
end else begin
|
||||
data_counter <= scki_counter;
|
||||
if (data_counter == DW_8) begin
|
||||
adc_data_init <= adc_lane;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ch_data_lock - locks all the channel, means dont acquire data if all ch's are lock while acquire_data = 0
|
||||
always @(posedge clk) begin
|
||||
if (start_transfer_s) begin
|
||||
ch_data_lock <= 1'd0;
|
||||
end else if (acquire_data == 1'b1 && (scki_cnt_rst & (scki_d != scki_i))) begin
|
||||
ch_data_lock <= 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
assign acquire_data = ~((ch_data_lock | ~adc_enable[0]) &
|
||||
(ch_data_lock | ~adc_enable[1]) &
|
||||
(ch_data_lock | ~adc_enable[2]) &
|
||||
(ch_data_lock | ~adc_enable[3]) &
|
||||
(ch_data_lock | ~adc_enable[4]) &
|
||||
(ch_data_lock | ~adc_enable[5]) &
|
||||
(ch_data_lock | ~adc_enable[6]) &
|
||||
(ch_data_lock | ~adc_enable[7]));
|
||||
|
||||
// stores the data from the rx buffer, but now based on ch
|
||||
// from the whole buffer into the per channel buffer
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_data_store[0] <= 'd0;
|
||||
adc_data_store[1] <= 'd0;
|
||||
adc_data_store[2] <= 'd0;
|
||||
adc_data_store[3] <= 'd0;
|
||||
adc_data_store[4] <= 'd0;
|
||||
adc_data_store[5] <= 'd0;
|
||||
adc_data_store[6] <= 'd0;
|
||||
adc_data_store[7] <= 'd0;
|
||||
end else begin
|
||||
if (!adc_valid_init_d & adc_valid_init) begin
|
||||
adc_data_store[0] <= adc_data_init[BW + DW * 7: DW * 7];
|
||||
adc_data_store[1] <= adc_data_init[BW + DW * 6: DW * 6];
|
||||
adc_data_store[2] <= adc_data_init[BW + DW * 5: DW * 5];
|
||||
adc_data_store[3] <= adc_data_init[BW + DW * 4: DW * 4];
|
||||
adc_data_store[4] <= adc_data_init[BW + DW * 3: DW * 3];
|
||||
adc_data_store[5] <= adc_data_init[BW + DW * 2: DW * 2];
|
||||
adc_data_store[6] <= adc_data_init[BW + DW * 1: DW * 1];
|
||||
adc_data_store[7] <= adc_data_init[BW + DW * 0: DW * 0];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// extract info from the data bits
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < 8; i=i+1) begin: format
|
||||
assign adc_data_raw_s[i] = adc_data_store[i][BW:DW-DATA_WIDTH];
|
||||
assign adc_data_sign_s[i] = {{(32-DATA_WIDTH){adc_data_raw_s[i][DATA_WIDTH-1]}}, adc_data_raw_s[i]};
|
||||
assign adc_data_zero_s[i] = {{(32-DATA_WIDTH){1'b0}}, adc_data_raw_s[i]};
|
||||
assign adc_data_s[i] = (adc_softspan_s[i] == 3'b0)? 32'h0 :
|
||||
(adc_softspan_s[i][1])? adc_data_sign_s[i] :
|
||||
adc_data_zero_s[i] ;
|
||||
if (NUM_CHANNELS == 8) begin
|
||||
assign adc_ch_id_s[i] = adc_data_store[i][5:3];
|
||||
end else if (NUM_CHANNELS == 4) begin
|
||||
assign adc_ch_id_s[i] = {1'b0, adc_data_store[i][4:3]};
|
||||
end else begin
|
||||
assign adc_ch_id_s[i] = {2'b0, adc_data_store[i][3]};
|
||||
end
|
||||
assign adc_softspan_s[i] = adc_data_store[i][2:0];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// assign extracted adc data to corresponding outputs
|
||||
assign adc_data_0 = adc_data_s[0];
|
||||
assign adc_data_1 = adc_data_s[1];
|
||||
assign adc_data_2 = adc_data_s[2];
|
||||
assign adc_data_3 = adc_data_s[3];
|
||||
assign adc_data_4 = adc_data_s[4];
|
||||
assign adc_data_5 = adc_data_s[5];
|
||||
assign adc_data_6 = adc_data_s[6];
|
||||
assign adc_data_7 = adc_data_s[7];
|
||||
|
||||
// assign extracted adc channel id to corresponding outputs
|
||||
assign adc_ch0_id = adc_ch_id_s[0];
|
||||
assign adc_ch1_id = adc_ch_id_s[1];
|
||||
assign adc_ch2_id = adc_ch_id_s[2];
|
||||
assign adc_ch3_id = adc_ch_id_s[3];
|
||||
assign adc_ch4_id = adc_ch_id_s[4];
|
||||
assign adc_ch5_id = adc_ch_id_s[5];
|
||||
assign adc_ch6_id = adc_ch_id_s[6];
|
||||
assign adc_ch7_id = adc_ch_id_s[7];
|
||||
|
||||
// assign extracted adc channel id to corresponding outputs
|
||||
assign adc_softspan_0 = adc_softspan_s[0];
|
||||
assign adc_softspan_1 = adc_softspan_s[1];
|
||||
assign adc_softspan_2 = adc_softspan_s[2];
|
||||
assign adc_softspan_3 = adc_softspan_s[3];
|
||||
assign adc_softspan_4 = adc_softspan_s[4];
|
||||
assign adc_softspan_5 = adc_softspan_s[5];
|
||||
assign adc_softspan_6 = adc_softspan_s[6];
|
||||
assign adc_softspan_7 = adc_softspan_s[7];
|
||||
|
||||
// initial valid signal
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_valid_init <= 1'b0;
|
||||
end else begin
|
||||
if (data_counter == DW_8 && adc_valid_init == 1'b0) begin
|
||||
adc_valid_init <= 1'b1;
|
||||
end else begin
|
||||
adc_valid_init <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// delayed both valid signal and data_lock signal
|
||||
// for datasyncing with valid signal
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1 || adc_valid == 1'b1) begin
|
||||
adc_valid <= 1'b0;
|
||||
adc_valid_init_d <= 1'b0;
|
||||
ch_capture <= 1'd0;
|
||||
ch_captured <= 1'd0;
|
||||
end else begin
|
||||
ch_capture <= ch_data_lock;
|
||||
ch_captured <= ch_capture;
|
||||
adc_valid_init_d <= adc_valid_init;
|
||||
adc_valid <= adc_valid_init_d &
|
||||
(ch_captured | ~adc_enable[0]) &
|
||||
(ch_captured | ~adc_enable[1]) &
|
||||
(ch_captured | ~adc_enable[2]) &
|
||||
(ch_captured | ~adc_enable[3]) &
|
||||
(ch_captured | ~adc_enable[4]) &
|
||||
(ch_captured | ~adc_enable[5]) &
|
||||
(ch_captured | ~adc_enable[6]) &
|
||||
(ch_captured | ~adc_enable[7]);
|
||||
end
|
||||
end
|
||||
|
||||
// every negedge of clk, update index of sdi_s
|
||||
always @(negedge clk) begin
|
||||
if (start_transfer_s || rst) begin
|
||||
sdi_index <= 5'd23;
|
||||
end else begin
|
||||
if (scki_s != scki_d && sdi_index != 5'b11111) begin
|
||||
sdi_index <= sdi_index - 5'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// update next softspan configuration every after busy
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
softspan_next_int <= 24'hff_ffff;
|
||||
end else begin
|
||||
if (busy_m3 & ~busy_m2) begin
|
||||
softspan_next_int <= softspan_next;
|
||||
end else begin
|
||||
softspan_next_int <= softspan_next_int;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign sdi_s = (sdi_index != 5'b11111)? softspan_next_int[sdi_index] : 1'b0;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user