Quantcast
Channel: EngineerZone: Message List
Viewing all articles
Browse latest Browse all 28044

Re: AD9361 AC701 no-os customized for CMOS mode

$
0
0

Istvan,

 

I appreciate your help.  I have replaced the differential buffers with single ended as you described.  The part that I am worried about is in the main axi_ad9361_dev_if component. My goal is to use the CMOS timing as shown in pg. 15 of the AD9361 interface specification : 2R2T, DDR, FDD, Dual port, 0x10=0xC8, 0x11=0x00, 0x12=0x02.  I have added extra output buffers (not shown below) in order to send test versions of the tx_clk, tx_frame, and tx_data to fpga test io to see how the tx data path looks on a scope (from the FPGA to the AD9361).  Observing the scope,  I notice that the tx_frame signal is always being asserted.  I then assigned the data valid signal, from within the axi_ad9361_dev_if module, to one of my test outputs to see its behavior on the scope. ...which led me to notice that the data_valid signal is also always asserted. I traced this signal back further to discover that it comes from the axi_ad9361_tx module and is asserted based on some dac data rate parameter.  Two questions: 1. how can I go about making sure that the data_valid is being driven properly so that tx_frame is driven properly? And 2. if you have spare time: what else is going wrong in my code below to cause the digital tuning to fail?


Thanks,

Nick

 

// ***************************************************************************
// ***************************************************************************
// Copyright 2011(c) Analog Devices, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//    - Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    - Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in
//      the documentation and/or other materials provided with the
//      distribution.
//    - Neither the name of Analog Devices, Inc. nor the names of its
//      contributors may be used to endorse or promote products derived
//      from this software without specific prior written permission.
//    - The use of this software may or may not infringe the patent rights
//      of one or more patent holders.  This license does not release you
//      from the requirement that you obtain separate licenses from these
//      patent holders to use this software.
//    - Use of the software either in source or binary form, must be run
//      on or directly connected to an Analog Devices Inc. component.
//   
// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.
//
// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// This interface includes both the transmit and receive components -
// They both uses the same clock (sourced from the receiving side).
`timescale 1ns/100ps
module axi_ad9361_dev_if_cmos (       // physical interface (receive)       rx_clk_in,    rx_frame_in,    rx_data_in,       // physical interface (transmit)       tx_clk_out,    tx_frame_out,    tx_data_out,       // clock (common to both receive and transmit)       rst,    clk,    l_clk,       // receive data path interface       adc_valid,    adc_data,    adc_status,    adc_r1_mode,       // transmit data path interface       dac_valid,    dac_data,    dac_r1_mode,       // delay control signals       delay_clk,    delay_rst,    delay_sel,    delay_rwn,    delay_addr,    delay_wdata,    delay_rdata,    delay_ack_t,    delay_locked);       // this parameter controls the buffer type based on the target device.       parameter  PCORE_DEVICE_TYPE = 0;    parameter  PCORE_IODELAY_GROUP = "dev_if_delay_group";    localparam  PCORE_7SERIES = 0;    localparam  PCORE_VIRTEX6 = 1;       // physical interface (receive)       input          rx_clk_in;    input          rx_frame_in;    input  [11:0]  rx_data_in;       // physical interface (transmit)       output          tx_clk_out;    output          tx_frame_out;    output  [11:0]  tx_data_out;       // clock (common to both receive and transmit)       input          rst;    input          clk;    output          l_clk;       // receive data path interface       output          adc_valid;    output  [47:0]  adc_data;    output          adc_status;    input          adc_r1_mode;       // transmit data path interface       input          dac_valid;    input  [47:0]  dac_data;    input          dac_r1_mode;       // delay control signals       input          delay_clk;    input          delay_rst;    input          delay_sel;    input          delay_rwn;    input  [ 7:0]  delay_addr;    input  [ 4:0]  delay_wdata;    output  [ 4:0]  delay_rdata;    output          delay_ack_t;    output          delay_locked;            // internal registers       reg    [23:0]  rx_data = 'd0;    reg    [ 1:0]  rx_frame = 'd0;    reg            rx_error_r1 = 'd0;    reg            rx_valid_r1 = 'd0;    reg    [23:0]  rx_data_r1 = 'd0;    reg            rx_error_r2 = 'd0;    reg            rx_valid_r2 = 'd0;    reg    [47:0]  rx_data_r2 = 'd0;    reg            adc_p_valid = 'd0;    reg    [47:0]  adc_p_data = 'd0;    reg            adc_p_status = 'd0;    reg            adc_n_valid = 'd0;    reg    [47:0]  adc_n_data = 'd0;    reg            adc_n_status = 'd0;    reg            adc_valid_int = 'd0;    reg    [47:0]  adc_data_int = 'd0;    reg            adc_status_int = 'd0;    reg            adc_valid = 'd0;    reg    [47:0]  adc_data = 'd0;    reg            adc_status = 'd0;    reg    [1:0]  tx_data_cnt = 'd0;    reg    [47:0]  tx_data = 'd0;    reg            tx_frame = 'd0;    reg    [11:0]  tx_data_p = 'd0;    reg    [11:0]  tx_data_n = 'd0;    reg            tx_n_frame = 'd0;    reg    [11:0]  tx_n_data_p = 'd0;  // positive edge tx data, latched on falling edge    reg    [11:0]  tx_n_data_n = 'd0;  // negative edge tx data, latched on falling edge    reg            tx_p_frame = 'd0;    reg    [11:0]  tx_p_data_p = 'd0;  // positive edge tx data, latched on rising edge    reg    [11:0]  tx_p_data_n = 'd0;  // negative edge tx data, latched on rising edge    reg    [12:0]  delay_ld = 'd0;    reg    [ 4:0]  delay_rdata = 'd0;    reg            delay_ack_t = 'd0;       // internal signals       wire    [ 3:0]  tx_data_sel_s;    wire    [ 4:0]  delay_rdata_s[12:0];    wire    [11:0]  rx_data_p_s;    wire    [11:0]  rx_data_n_s;    wire            rx_frame_p_s;    wire            rx_frame_n_s;       genvar          l_inst;       // assign both data positive and negative edge data/frame to one signal    always @(posedge l_clk) begin       rx_data <= {rx_data_n_s, rx_data_p_s};    rx_frame <= {rx_frame_n_s, rx_frame_p_s};    end       // receive data rf 1 data  always @(posedge l_clk) begin  rx_error_r1 <= (rx_frame == 2'b10) ? 1'b0 : 1'b1;  rx_valid_r1 <= (rx_frame == 2'b10) ? 1'b1 : 1'b0;  if (rx_frame == 4'b10) begin    rx_data_r1 <= rx_data;  end  end         // receive data rf 2 data       always @(posedge l_clk) begin    rx_error_r2 <= ((rx_frame == 2'b11) || (rx_frame == 2'b00)) ? 1'b0 : 1'b1;    rx_valid_r2 <= (rx_frame == 2'b00) ? 1'b1 : 1'b0;    if (rx_frame == 2'b11) begin    rx_data_r2[23: 0] <= rx_data;    end    if (rx_frame == 2'b00) begin    rx_data_r2[47:24] <= rx_data;    end    end               // receive data path mux       always @(posedge l_clk) begin    if (adc_r1_mode == 1'b1) begin      adc_p_valid <= rx_valid_r1;      adc_p_data <= {24'd0, rx_data_r1};      adc_p_status <= ~rx_error_r1;    end else begin      adc_p_valid <= rx_valid_r2;      adc_p_data <= rx_data_r2;      adc_p_status <= ~rx_error_r2;    end    end       // transfer to a synchronous common clock       always @(negedge l_clk) begin    adc_n_valid <= adc_p_valid;    adc_n_data <= adc_p_data;    adc_n_status <= adc_p_status;    end       always @(posedge clk) begin    adc_valid_int <= adc_n_valid;    adc_data_int <= adc_n_data;    adc_status_int <= adc_n_status;    adc_valid <= adc_valid_int;    if (adc_valid_int == 1'b1) begin      adc_data <= adc_data_int;    end    adc_status <= adc_status_int;    end       // transmit data path mux (reverse of what receive does above)    // AD9361 Interface Specification pg. 15           always @(posedge clk) begin    if (dac_valid == 1'b1) begin      tx_data_cnt <= 2'b10;    end else if (tx_data_cnt[1] == 1'b1) begin      tx_data_cnt <= tx_data_cnt + 1'b1;    end    if (dac_valid == 1'b1) begin      tx_data <= dac_data;    end    case (tx_data_cnt)      2'b11: begin        tx_frame <= 1'b0;        tx_data_p <= tx_data[35:24];        tx_data_n <= tx_data[47:36];      end      2'b10: begin        tx_frame <= 1'b1;        tx_data_p <= tx_data[11:0];        tx_data_n <= tx_data[23:12];      end      default: begin        tx_frame <= 1'b0;        tx_data_p <= 12'd0;        tx_data_n <= 12'd0;      end    endcase    end       // transfer data from a synchronous clock (skew less than 2ns)       always @(negedge clk) begin    tx_n_frame <= tx_frame;    tx_n_data_p <= tx_data_p;    tx_n_data_n <= tx_data_n;    end       always @(posedge l_clk) begin    tx_p_frame <= tx_n_frame;    tx_p_data_p <= tx_n_data_p;    tx_p_data_n <= tx_n_data_n;    end       // delay write interface, each delay element can be individually    // addressed, and a delay value can be directly loaded (no inc/dec stuff)       always @(posedge delay_clk) begin    if ((delay_sel == 1'b1) && (delay_rwn == 1'b0)) begin      case (delay_addr)        8'h0c: delay_ld <= 13'h1000;        8'h0b: delay_ld <= 13'h0800;        8'h0a: delay_ld <= 13'h0400;        8'h09: delay_ld <= 13'h0200;        8'h08: delay_ld <= 13'h0100;        8'h07: delay_ld <= 13'h0080;        8'h06: delay_ld <= 13'h0040;        8'h05: delay_ld <= 13'h0020;        8'h04: delay_ld <= 13'h0010;        8'h03: delay_ld <= 13'h0008;        8'h02: delay_ld <= 13'h0004;        8'h01: delay_ld <= 13'h0002;        8'h00: delay_ld <= 13'h0001;        default: delay_ld <= 13'h0000;      endcase    end else begin      delay_ld <= 13'h000;    end    end       // delay read interface, a delay ack toggle is used to transfer data to the    // processor side- delay locked is independently transferred       always @(posedge delay_clk) begin    case (delay_addr)      8'h0c: delay_rdata <= delay_rdata_s[12];      8'h0b: delay_rdata <= delay_rdata_s[11];      8'h0a: delay_rdata <= delay_rdata_s[10];      8'h09: delay_rdata <= delay_rdata_s[9];      8'h08: delay_rdata <= delay_rdata_s[8];      8'h07: delay_rdata <= delay_rdata_s[7];      8'h06: delay_rdata <= delay_rdata_s[6];      8'h05: delay_rdata <= delay_rdata_s[5];      8'h04: delay_rdata <= delay_rdata_s[4];      8'h03: delay_rdata <= delay_rdata_s[3];      8'h02: delay_rdata <= delay_rdata_s[2];      8'h01: delay_rdata <= delay_rdata_s[1];      8'h00: delay_rdata <= delay_rdata_s[0];      default: delay_rdata <= 5'd0;    endcase    if (delay_sel == 1'b1) begin      delay_ack_t <= ~delay_ack_t;    end    end       // receive data interface, ibuf -> idelay -> iddr       generate    for (l_inst = 0; l_inst <= 11; l_inst = l_inst + 1) begin: g_rx_data    ad_lvds_in #(    .BUFTYPE (PCORE_DEVICE_TYPE),    .IODELAY_CTRL (0),    .IODELAY_GROUP (PCORE_IODELAY_GROUP))    i_rx_data (    .rx_clk (l_clk),    .rx_data_in (rx_data_in[l_inst]),    .rx_data_p (rx_data_p_s[l_inst]),    .rx_data_n (rx_data_n_s[l_inst]),    .delay_clk (delay_clk),    .delay_rst (delay_rst),    .delay_ld (delay_ld[l_inst]),    .delay_wdata (delay_wdata),    .delay_rdata (delay_rdata_s[l_inst]),    .delay_locked ());    end    endgenerate       // receive frame interface, ibuf -> idelay -> iddr       ad_lvds_in #(    .BUFTYPE (PCORE_DEVICE_TYPE),    .IODELAY_CTRL (1),    .IODELAY_GROUP (PCORE_IODELAY_GROUP))    i_rx_frame (    .rx_clk (l_clk),    .rx_data_in (rx_frame_in),    .rx_data_p (rx_frame_p_s), // ddr positive edge    .rx_data_n (rx_frame_n_s), // ddr negative edge    .delay_clk (delay_clk),    .delay_rst (delay_rst),    .delay_ld (delay_ld[12]),    .delay_wdata (delay_wdata),    .delay_rdata (delay_rdata_s[12]),    .delay_locked (delay_locked));       // transmit data interface, oddr -> obuf       generate    for (l_inst = 0; l_inst <= 11; l_inst = l_inst + 1) begin: g_tx_data    ad_lvds_out #(    .BUFTYPE (PCORE_DEVICE_TYPE))    i_tx_data (    .tx_clk (l_clk),    .tx_data_p (tx_p_data_p[l_inst]),    .tx_data_n (tx_p_data_n[l_inst]),    .tx_data_out (tx_data_out[l_inst]));    end    endgenerate       // transmit frame interface, oddr -> obuf       ad_lvds_out #(    .BUFTYPE (PCORE_DEVICE_TYPE))    i_tx_frame (    .tx_clk (l_clk),    .tx_data_p (tx_p_frame),    .tx_data_n (tx_p_frame),    .tx_data_out (tx_frame_out));       // transmit clock interface, oddr -> obuf       ad_lvds_out #(    .BUFTYPE (PCORE_DEVICE_TYPE))    i_tx_clk (    .tx_clk (l_clk),    .tx_data_p (1'b0),    .tx_data_n (1'b1),    .tx_data_out (tx_clk_out));       // turn differential receive clock into single ended clock    ad_lvds_clk #(    .BUFTYPE (PCORE_DEVICE_TYPE))    i_clk (    .clk_in (rx_clk_in),    .clk (l_clk));   
endmodule
// ***************************************************************************
// ***************************************************************************

Viewing all articles
Browse latest Browse all 28044

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>