Forum Discussion
IORD_ALTERA_AVALON_PIO_DATA to slow?
Hi,
I'm trying to capture samples from an A/D Converter and streaming them onto a PC via an ethernet connection. I've extended the triple speed ethernet design example from the Nios II v9.1 installation directory. I'm using a PIO component in my SOPC System where the ADC data is written on the data register of the component. From there I'm reading it in a while loop in my Nios software using: while(tx_wr_pos < &tx_buf[SSS_TX_BUF_SIZE-8]) { tx_wr_pos += sprintf(tx_wr_pos,"%d\n\r", IORD_ALTERA_AVALON_PIO_DATA(AD_DATA_BASE)); } send(conn.fd, tx_buf, tx_wr_pos - tx_buf, 0); However, there seems to be aliasing occuring whenever the ADC signal gets faster then a few 100Hz. How many clock cycles does the IORD function need? My Nios II system is set to the maximum 100 ticks/s. Is my software to slow for just reading the PIO in a while loop?27 Replies
- Altera_Forum
Honored Contributor
How does ADC put data on PIO inputs? Is there a clock, latch or strobe signal or this is completely asynchronous to Nios clock?
If data changes asynchronously, it is possible your PIO samples some bits of the previous data word and some bits of the next one, leading to incorrect values. You can't control this because every PIO input can have a slightly different delay and rising/falling time. You may try multiple sampling, until you get twice the same data. - Altera_Forum
Honored Contributor
I would be more worried about the execution time of the sprintf();
Try using a 'quick and dirty' conversion into (say) base 16 (eg fixed width and consequetive character values). - Altera_Forum
Honored Contributor
@Cris72: I've written a VHDL module (ad9254.vhd) that writes the data stream value on to the PIO port with every clock cycle of the ADC data clock (ada_dco). This clock has the same speed as the clock of the PIO component. (62,5MHz)
I've attatched the Top-Level Schematics of my System (tserd_3c120). Hope that doesn't confuse. @dsl: Yes, of course the sprintf() could take up time. I only use that to display the samples. Would it make a big enough difference if I wrote the samples into an array and then printed the content of that array? I'm still new to this whole Nios programming. Would it be realistic to consider alternatives to the PIO such as a DMA or SGDMA? Or could it just be solved with a kind of a FIFO in hardware OR software?! - Altera_Forum
Honored Contributor
If you are trying to check your ADC I'd definitely read a block to an array, then copy that out somehow.
The sprintf() is probably several 100 clocks - if not several 1000, especially if you haven't ensured that everything is compiled with -O2 or -O3. The IORW() itself is probably 2 (depends on the number of wait states in your ADC slave) . - Altera_Forum
Honored Contributor
Thanks! That's good to know. Now I write the samples into an array. But my results are still confusing me. I've attatched captures of 2 different signal frequencies (10kHz, 1MHz). Does that not show, that my polling loop is too slow for high frequencies?
(The X-Aches is the number of samples, Y-Aches the amplitude) - Altera_Forum
Honored Contributor
Count the number of samples you collected for 1 phase of the 10kHz signal - that will give you the speed your poll loops runs at.
Your code loop will need (at least) the following instructions (and if you write the appropriate C the compiler can be persuaded to generate them): - load from the AD - store to memory - register increment for memory address - compare and branch (memory address against array end) Allowing for the extra clock for the 'predicted taken' branch, and provided the instructions are ordered properly (you need 2 clocks between the load and store), the minimum loop cost is 5 clocks + the ADC read/cycle time. There will be at least 1 clock extra delay in the read of the Avalon slave for the ADC. - Altera_Forum
Honored Contributor
--- Quote Start --- Does that not show, that my polling loop is too slow for high frequencies? --- Quote End --- Yes, I made a rough calculation with your graphs and it results to me that sometimes you have polling delay up to 2 or 3 us; this may be irrelevant for a 1kHz wave but it makes a mess when f>100kHz. This small delay is pretty normal since is the time required for isr periodically interrupting your polling loop. You mentioned in the original post that you are using tse for ethernet connection. Do you use a tcp stack, too? Things can get even worse when you transfer a lot of data on the ethernet because a lot of isr will need to be serviced. - Altera_Forum
Honored Contributor
The amplitude range of the 10kHz is also a different one to the 1MHz signal. Maybe this is something the ADC does?
@Cris72: You are right about the fruequencies. It's always messed up when the signal is over 100kHz. Yes, I use a TCP Stack (Nios II Niche Stack), but to me that seemed to be working fast enough using 1000Mbit/s-Ethernet connection. So, how could I optimize the design? Is it more a matter of hardware components or my Nios II software? Would writing the loop in assembler make it fast enough? In the end I want to capture a base band RF signal, don't know to which frequency that will be going... - Altera_Forum
Honored Contributor
I use Nichestack, too. It uses two high priority interrupts to manage ethernet rx and protocol: this is leading to the delay you are experiencing.
Nichestack also includes some critical pieces of code where isr are temporarily disabled, so you can't attain such a precise timing as you require, even if your sampling is made through a highest priority timer interrupt. the only way to perform precise sampling at f>100kHz is to make it with hardware, dma or similar. - Altera_Forum
Honored Contributor
Hmmm..... An embedded ethernet/TCP stack shouldn't necessarily require interrupts - it just needs to be called often enough to process the receive data stream. The ethernet chips receive descriptor ring can be used to hold the rx buffers with data (waiting to be processed) and the free buffers!
If you are trying to capture RF baseband you almost certainly need to get the ADC to save its data in a FIFO or ring buffer from where the Nios can save or process it. At least that will guarantee you get a block of consequetive samples for later processing.