Strobed buffered input

All technical discussions and projects around startKIT
Post Reply
atixmos
New User
Posts: 2
Joined: Mon Jun 06, 2016 6:02 pm

Strobed buffered input

Post by atixmos »

Hi!

I'm struggled with the behavior of an strobed buffered input. I would like to use an external parallel AD converter with enable/disable read signal. I have the following code:

Code: Select all

void InitHW(clock clk_adc,
            clock clk_trig,
            out port adc_clk_out,
            in buffered port:16  adc_in,
            in port adc_input_en_in,
            out port adc_input_en_out,
            out buffered port:1 ext_trig)
{
        configure_clock_rate (clk_adc , 100 , DIVIDER);                     // setting of the clock block of the ADC port
        configure_clock_rate (clk_trig , 100 , 1);                          // setting of the clock block for the trigger signal port

        configure_port_clock_output (adc_clk_out , clk_adc);                // clock output
       //configure_in_port(adc_in, clk_adc);                                // buffered input port
        configure_in_port_strobed_slave(adc_in, adc_input_en_in, clk_adc);  // buffered !strobbed! input

        configure_out_port(ext_trig, clk_trig, 0 );                         // ext trig is sync to the adc clock
        configure_out_port( adc_input_en_out, clk_trig,0);

        set_port_sample_delay(adc_in);                                      // ADC parallel input read is synced to the falling edge of the clock

        start_clock(clk_adc);
        start_clock(clk_trig);
}
... and the task:

Code: Select all

void AD92xxControlTask( in buffered port:16 adc_in, client interface AD92xx_DataIF_type adc_if)
{
    unsigned int AdcDataBuffer[ COLLECTION_LENGTH ];
    unsigned int* ptr =  &AdcDataBuffer[0];
    unsigned int index = 0;

    printstrln("before the while");
    while(1)
    {
        select{
            case adc_in :> AdcDataBuffer[index] :
                index++;
                if( index == COLLECTION_LENGTH ){
                        printstrln("adc COLLECTION_LENGTH");

                        index = 0;
                        adc_if.PassPtr(ptr);
                    }
            break;
        }
    }
}
..and the task, which enables the adc_in port. The "adc_input_en_in" and the "adc_input_en_out" is connected together on the board by.

Code: Select all

void task1( out buffered port:1 ext_trig,
            out port adc_input_en_out,
            server interface AD92xx_DataIF_type adc_if )
{

    unsigned int adc_buff = 0;
    unsigned int i=0;

    adc_input_en_out <: 1;           // enable adc

    while(1)
    {
        select{

            case adc_if.PassPtr( unsigned int* ptr) :
            {
                adc_input_en_out <: 0;
                for(i=0;i<COLLECTION_LENGTH;i++){  adc_buff = *(ptr++); };

                break;
            }

        }

    }
}
According to my understanding, the processsor is waiting until the strobe signal isn't high, but the reality is that the "case adc_in :> AdcDataBuffer[index] :" runs anytime independently from the state of the strobe signal. So, how this strobing should work? I'm the one, who don't get the meaning?


peter
XCore Addict
Posts: 230
Joined: Wed Mar 10, 2010 12:46 pm

Post by peter »

Hi atixmos,

You have correctly understood the function of the strobed ports. Let me just take you through the steps that I used to try to determine what is going wrong. Firstly, I created a test app with your setup code to do a sanity check:

Code: Select all

#include <platform.h>
#include <xs1.h>
#include <print.h>

clock c1 = XS1_CLKBLK_1;
clock c2 = XS1_CLKBLK_2;
out port p_clock_out = XS1_PORT_1A;
in buffered port:16 p_data = XS1_PORT_16A;
in port p_adc_en_in = XS1_PORT_1C;
out port p_adc_en_out = XS1_PORT_1D;
out buffered port:1 p_trigger = XS1_PORT_1E;

// Loopbacks
out port p_drive_adc_en_in = XS1_PORT_1F;
out port p_drive_data = XS1_PORT_16B;
clock clk_drive = XS1_CLKBLK_3;

#define DIVIDER 200 // 250kHz clock

void InitHW(...)
... // Copied from your code
}

void input(in buffered port:16 adc_in)
{
  for (int i = 0; i < 10; i++) {
    int data;
    adc_in :> data;
    printintln(data);
  }
}

void drive(out port en, out port data)
{
  en <: 0;
  for (int i = 0; i < 5; i++) {
    data <: i;
  }

  en <: 1;
  for (int i = 100; i < 105; i++) {
    data <: i;
  }

  en <: 0;
  for (int i = 200; i < 205; i++) {
    data <: i;
  }

  en <: 1;
  for (int i = 300; i < 305; i++) {
    data <: i;
  }
}

int main()
{
  par {
    {
      InitHW(c1, c2, p_clock_out, p_data, p_adc_en_in, p_adc_en_out, p_trigger);
      input(p_data);
    }
    {
      configure_clock_rate (clk_drive, 100, DIVIDER);
      configure_out_port(p_drive_data, clk_drive, 0);
      configure_out_port(p_drive_adc_en_in, clk_drive, 0);
      start_clock(clk_drive);
      drive(p_drive_adc_en_in, p_drive_data);
    }
  }
  return 0;
}
Then I compiled it and ran it on some hardware just to double-check everything was being setup correctly:

Code: Select all

$ xcc test.xc -target=XCORE-200-EXPLORER -o a.xe
$ xgdb a.xe
GNU gdb (XGDB) Community_14.2.0 (build 11257, May-12-2016)
...
(gdb) connect
0x00040000 in _start ()
(gdb) b input
Breakpoint 1 at 0x4030c
(gdb) r
Loading setup image to XCore 0
...
[Switching to tile[0] core[1]]
Breakpoint 1, 0x0004030c in input ()
(gdb) source ~/sandboxes/xgdb_scripts/tilestate 
(gdb) res_print_all
Tile 0:
--------
...
16-bit Port 0:
    input, inUse=1, ieMode=E, ieEnabled=0, cond=NONE, condData=0x0
    slave, buffered, strobed, data port, not inverted, no sample delay
    tWaiting=0, tNum=1
    clkSrc=0x00000106, rdySrc=0x00000000
    vector=0x00040000, ev=0x00000000
...
Clock Block 1:
    inUse=1, started=1, stopping=0, fallDelay=0, riseDelay=0
    tWaiting=0, tNum=1
    clkSrc=0x00000001, rdySrc=0x00010100
...
From this it confirmed that the port and clock block look correctly configured, so that is good. The gdb script I used for this is found on github and require the 14.2 tools to work. It gives the current status of all active resources.

So, I then ran the test on the simulator to confirm what was happening. I had written a simple driver app which controls the enable and data ports and using simulation we can see what happens under these conditions:

Code: Select all

$ xsim --plugin LoopbackPort.dll "-port tile[0] XS1_PORT_1C 1 0 -port tile[0] XS1_PORT_1F 1 0 -port tile[0] XS1_PORT_16A 16 0 -port tile[0] XS1_PORT_16B 16 0" --trace-to sim.log --vcd-tracing "-o trace.vcd -tile tile[0] -ports -ports-detailed -clock-blocks" a.xe
4
100
101
102
103
204
300
301
302
303
What this shows is that the data is not input when the enable pin is low and is when the enable pin is high. There is clearly a bit of synchronisation at the start of sequences where I haven't got my enable/data/clock aligned properly (the fact that 4 and 204 are seen).

If you load the VCD into xTIMEcomposer->Trace->VCD Trace view then you can see that data is not being made available during the time that the enable signal is held low.

So, I can only presume one of two things because of the issues I encountered writing my test app:
- The enable signal is not being correctly driven or,
- More likely is the clock is running at an incorrect rate. The port will sample data whenever the enable pin is high and there is a falling clock (you've setup sample_delay). So, if the clock rate is too high then you will sample the data multiple times when you were expecting only a single value.

Does that help?

Peter
atixmos
New User
Posts: 2
Joined: Mon Jun 06, 2016 6:02 pm

Post by atixmos »

First of all, thank you for your help.

At this moment, I don't have the ADC board, so I can't check whether the reading happing at the correct time point (it should happen at the falling edge of the outputed clock) or not. But I found the error. The driver signal of the enable pin were miswired...I connected to the wrong pin. I have changed it and then I got only 1 interface transfare, which is what I wanted to.
Concerning your reply. I don't get it all clearly for the first look, but I will look through it slowly later.
Post Reply