• 0

Eclypse Z7 and ZMOD-ADC1410 connection


Question

I'm trying to get the ADC1410 to work in the Eclypse Z7 FPGA board with a verilog-pure program, making use of the IP Core provided by Digilent (ZmodADC1410_Controller_0).
Up to now, I'am reading trash data from the IP output, so I suppose I've made a mistake in the connections or in the data acquisition or something else.
I've not seen any example of a verilog instantiation of the IP, so please let me know if there's any out there.

For making the connections, I've followed the schematic in the reference manual.

I'm posting my top level design and I'm also attaching the constraint I've used:

`timescale 1ns / 1ps

module top
(
    input   i_reset,            /* onboard button   */
    input   i_clock,            /* 125 MHz onboard  */
    
    output  o_tx,               /* uart output      */
    
    output  syzygy_d_n_0,       /* sc1_ac_l         */
    output  syzygy_d_p_0,       /* sc1_ac_h         */
    output  syzygy_d_n_1,       /* sc2_ac_l         */
    output  syzygy_d_p_1,       /* sc2_ac_h         */
    output  syzygy_d_n_2,       /* sclk_sc          */
    inout   syzygy_d_p_2,       /* sdio_sc          */
    output  syzygy_d_n_3,       /* sc2_gain_l       */
    output  syzygy_d_p_3,       /* sc2_gain_h       */
    input   syzygy_d_n_4,       /* data 2           */
    input   syzygy_d_p_4,       /* data 9           */
    output  syzygy_d_n_5,       /* sc1_gain_l       */
    output  syzygy_d_p_5,       /* sc1_gain_h       */
    input   syzygy_d_n_6,       /* data 4           */
    input   syzygy_d_p_6,       /* data 3           */
    output  syzygy_d_n_7,       /* com_sc_l         */
    output  syzygy_d_p_7,       /* com_sc_h         */
    input   syzygy_s_16,        /* data 5           */
    input   syzygy_s_17,        /* data 8           */
    input   syzygy_s_18,        /* data 6           */
    input   syzygy_s_19,        /* data 10          */
    input   syzygy_s_20,        /* data 7           */
    input   syzygy_s_21,        /* data 11          */
    input   syzygy_s_22,        /* data 1           */
    input   syzygy_s_23,        /* data 12          */
    input   syzygy_s_24,        /* data 0           */
    input   syzygy_s_25,        /* data 13          */
    output  syzygy_s_26,        /* cs_sc1n          */
    output  syzygy_s_27,        /* sync_adc         */
    output  syzygy_c2p_clk_n,   /* adc clock in n   */
    output  syzygy_c2p_clk_p,   /* adc clock in p   */
    input   syzygy_p2c_clk_p,   /* clkout adc       */
    output  syzygy_p2c_clk_n    /* GND              */
);      
    
    /* System */
    wire            clock;
    wire            locked;
        
    /* ADC */
    localparam  ADC_DATA_OUT_SIZE   =   16;
    localparam  ADC_DATA_IN_SIZE    =   14;
    wire                                    adc_init_done;
    wire                                    adc_clock;
    wire    [ ADC_DATA_OUT_SIZE - 1 : 0 ]   adc_data_out_ch1;
    wire    [ ADC_DATA_OUT_SIZE - 1 : 0 ]   adc_data_out_ch2;
    wire    [ ADC_DATA_IN_SIZE  - 1 : 0 ]   adc_data_in;
    wire                                    adc_test_mode;
    wire                                    adc_fifo_empty_ch1;
    wire                                    adc_fifo_empty_ch2;
    integer                                 adc_data_count;
    
    /* Serial */
    localparam  SERIAL_DATA_SIZE    =   8;
    localparam  SERIAL_CLK_COUNT    =   31000000;   
    reg                                     serial_send;
    wire                                    serial_ready;
    reg     [ SERIAL_DATA_SIZE - 1 : 0 ]    serial_data_l;
    reg     [ SERIAL_DATA_SIZE - 1 : 0 ]    serial_data_h;
    integer                                 clk_counter;
    
    /* UART: send one convertion each SERIAL_CLK_COUNT cycles */
    [email protected]( posedge clock ) begin
        if( ~locked ) begin
            clk_counter <= 0;
        end
        else begin
            clk_counter <= clk_counter + 1;
        
            if( clk_counter == SERIAL_CLK_COUNT ) begin
                clk_counter <= 0;
                if( serial_ready )
                    serial_send <= 1'b1;
            end
            else begin
                serial_send <= 1'b0;
            end
            
        end
    end
    
    /* Serial data setting */
    [email protected]( adc_data_out_ch1 ) begin
        serial_data_l = adc_data_out_ch1[7:0 ];
        serial_data_h = adc_data_out_ch1[15:8];    
    end
    
    assign  syzygy_p2c_clk_n    =   1'b0;
    assign  adc_test_mode       =   1'b0;
    assign  adc_data_in[ 0  ]   =   syzygy_s_24;
    assign  adc_data_in[ 1  ]   =   syzygy_s_22;
    assign  adc_data_in[ 2  ]   =   syzygy_d_n_4;
    assign  adc_data_in[ 3  ]   =   syzygy_d_p_6;
    assign  adc_data_in[ 4  ]   =   syzygy_d_n_6;
    assign  adc_data_in[ 5  ]   =   syzygy_s_16;
    assign  adc_data_in[ 6  ]   =   syzygy_s_18;
    assign  adc_data_in[ 7  ]   =   syzygy_s_20;
    assign  adc_data_in[ 8  ]   =   syzygy_s_17;
    assign  adc_data_in[ 9  ]   =   syzygy_d_p_4;
    assign  adc_data_in[ 10 ]   =   syzygy_s_19;
    assign  adc_data_in[ 11 ]   =   syzygy_s_21;
    assign  adc_data_in[ 12 ]   =   syzygy_s_23;
    assign  adc_data_in[ 13 ]   =   syzygy_s_25;
    
    /* ###################################### */
    clk_wiz_0
    u_clk_wiz_0
    (
        .clk_in1                (i_clock),
        .reset                  (i_reset),
        .clk_out1               (clock),            /* sys clock: 100MHz    */
        .clk_out2               (adc_clock),        /* adc clock: 400MHz    */
        .locked                 (locked)
    );
    /* ###################################### */
    serial #
    (
        .SERIAL_DATA_SIZE       (SERIAL_DATA_SIZE)
    )
    u_serial
    (
        .i_clock                (clock),
        .i_reset                (~locked),
        .i_send                 (serial_send),
        .i_data_h               (serial_data_h),
        .i_data_l               (serial_data_l),
        .o_ready                (serial_ready),
        .o_tx                   (o_tx)
    );
    /* ###################################### */
    ZmodADC1410_Controller_0
    u_ZmodADC1410_Controller_0
    (
        .SysClk             (clock),                //  IN STD_LOGIC;
        .ADC_InClk          (adc_clock),            //  IN STD_LOGIC;
        .sRst_n             (locked),               //  IN STD_LOGIC;
        .sInitDone_n        (adc_init_done),        //  OUT STD_LOGIC;
        .FIFO_EMPTY_CHA     (adc_fifo_empty_ch1),   //  OUT STD_LOGIC;
        .FIFO_EMPTY_CHB     (adc_fifo_empty_ch2),   //  OUT STD_LOGIC;
        .sCh1Out            (adc_data_out_ch1),     //  OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
        .sCh2Out            (adc_data_out_ch2),     //  OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
        .sTestMode          (adc_test_mode),        //  IN STD_LOGIC;
        .adcClkIn_p         (syzygy_c2p_clk_p),     //  OUT STD_LOGIC;
        .adcClkIn_n         (syzygy_c2p_clk_n),     //  OUT STD_LOGIC;
        .adcSync            (syzygy_s_27),          //  OUT STD_LOGIC;
        .DcoClk             (syzygy_p2c_clk_p),     //  IN STD_LOGIC;
        .dADC_Data          (adc_data_in),          //  IN STD_LOGIC_VECTOR(13 DOWNTO 0);
        .sADC_SDIO          (syzygy_d_p_2),         //  INOUT STD_LOGIC;
        .sADC_CS            (syzygy_s_26),          //  OUT STD_LOGIC;
        .sADC_Sclk          (syzygy_d_n_2),         //  OUT STD_LOGIC;
        .sCh1CouplingH      (syzygy_d_p_0),         //  OUT STD_LOGIC;
        .sCh1CouplingL      (syzygy_d_n_0),         //  OUT STD_LOGIC;
        .sCh2CouplingH      (syzygy_d_p_1),         //  OUT STD_LOGIC;
        .sCh2CouplingL      (syzygy_d_n_1),         //  OUT STD_LOGIC;
        .sCh1GainH          (syzygy_d_p_5),         //  OUT STD_LOGIC;
        .sCh1GainL          (syzygy_d_n_5),         //  OUT STD_LOGIC;
        .sCh2GainH          (syzygy_d_p_3),         //  OUT STD_LOGIC;
        .sCh2GainL          (syzygy_d_n_3),         //  OUT STD_LOGIC;
        .sRelayComH         (syzygy_d_p_7),         //  OUT STD_LOGIC;
        .sRelayComL         (syzygy_d_n_7)          //  OUT STD_LOGIC
    );
    /* ###################################### */

endmodule

The "trash data" that I'm getting comes from adc_data_out_ch1 (I'm not using CH2), and by "trash data" I mean nonsense values, for example, very unstable output values when I have a constant analog input (even with 0V). 

Eclypse-Z7-Constraint.xdc

Link to post
Share on other sites

3 answers to this question

Recommended Posts

  • 0

I appreciate that throwing code over the wall and hoping that someone spots the (hopefully) one or two defects that will fix the problem is an easy and quick solution... it's a common approach around this forum.

Perhaps there is a more productive way.

First, since you want to do an all HDL design your sources are missing at least one key element... a Verilog testbench. Part of the design process is verification, and at a minimum behavioral simulation is one part of verification. Simulation will help figure out what's going on with your design. To my way of thinking, if someone claims to have a design and there are no testbenches among the sources, then my first thought is to suggest that they still have some work to do before trying to implement an unfinished design in hardware.

If someone came to me in person with such a question as yours the first question, even before "where's the testbench?", would be "start by providing a brief description of how your design is supposed to work". Perhaps, you could start with that. I can't tell you how many times just asking that question has produced answers to questions; as having to put into words a representation of an amalgam of concepts often reveals bad assumptions and missing elements. Having someone stop, mid sentence as the lightbulb turns on, is most satisfying for everyone.

Link to post
Share on other sites
  • 0

Hello @zygot, thank you for your reply.

I got your point about "posting the code and hoping someone to fix it", but I did it because I may have some bad connections and this is one way of show you how the connections are made (maybe a diagram would be better?).

The purpose of the design is quite simple: digitalize some AC signals and then process them.

I didn't think about the testbench thing before now... but, ¿how could I simulate the IP behaviour without synthetizing and using the "real" ADC? 
I should simulate all the internal signals and responses? That sounds pretty complex...

Link to post
Share on other sites
  • 0
Posted (edited)
17 hours ago, Tomas Sarquis said:

The purpose of the design is quite simple: digitalize some AC signals and then process them.

Perhaps that's the purpose but it isn't a description of how the design is supposed to work. No one can help you debug your purpose but perhaps they might have some insight into how you can debug the design. So... again, how's the design supposed to work as you envision it?

 

17 hours ago, Tomas Sarquis said:

how could I simulate the IP behaviour without synthetizing and using the "real" ADC? 
I should simulate all the internal signals and responses? That sounds pretty complex...

There are a lot of ways to replace the ADC devices in your simulation testbench. The easiest would be to have a process that spits out incrementing data. You don't have to worry about output code formats... just refer to the ADC datasheet and make sure that the data is transferred accordingly. One of the nice things about Verilog for simulation is that you can use parts of Verilog that aren't supported by synthesis. You can read a file with ADC sample words and feed that into your testbench. Trying to see "actual real-world ADC sample data" in a simulation probably not a good choice for a number of reasons.

Really, the more important thing about the simulation is getting confirmation that, on a behavioral or RTL level at least, the whole design is doing what you think that it's doing. Simulating ADC formats isn't necessarily the first thing that you want to do.

I realize that there isn't a lot of texts available on good simulation techniques but you need to develop your verification chops in step with your design flow skills.

One problem with designing testbench code is that you are adding another thing to debug. It's analogous to unit testing software modules. The point is that, as your designs get more complex and hard to follow, your verification skills need to get more sophisticated and crafty as well. Your problem isn't that your design isn't working.. it's that your debugging skills aren't up to the task of figuring out how to find the cause of it's not working.

 

Edited by zygot
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now