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
@Cris72: I wasn't actually using my ethernet for those tests. I was merely writing the samples to on board memory and then printf 'd those values afterwards so I could view them. I wanted to isolate the IORD in that way.
The FIFO is definately something I could go for. However, I havn't found example code yet where FIFO's or ring buffers are used with the TSE... Or examples with a DMA. The triple speed ethernet design I extended already uses a SGDMA rx and a tx connected to the TSE megacore function. Can I use these in any way? Or must I add a DMA/SGDMA for my special purpose? - Altera_Forum
Honored Contributor
You probably want to put a buffer inside your ADC avalon slave. That way the ADC gets guaranteed write access times (M9K buffers are dual ported).
You then need to add logic to your slave interface to access that memory block. It might be possible to leave space before the area where the ADC writes for an ethernet+IP+UDP header - and then transmit directly from that buffer! That would be a 1k+ UDP packet containing 512 16bit samples. Double buffer and a nios could schedule the transmits. Of course if you are using a network stack it all gets harder :-) - Altera_Forum
Honored Contributor
@dsl
--- Quote Start --- An embedded ethernet/TCP stack shouldn't necessarily require interrupts --- Quote End --- Sorry, you are right. I actually meant Nichestack uses two high priority TASKS not interrupts. This is valid in the standard way of operation based on Micrium RTOS, unless you use superloop mode. Anyway what I said still applies: the OS scheduler interrupt periodically takes control over your polling loop and delays your samples by a possibly indeterminate amount of time. Cris - Altera_Forum
Honored Contributor
@dsl: My ADC avalon slave is a PIO component. The PIO source code is generated, so I don't want to hack around in that. Is there a better component I can use for the ADC samples comming in?
I would really like to keep this simple, creating my own ethernet pakets is a bit to deep for me... Don't know if you're familiar with SGDMA. I've thought of using the SGDMA's in my system. But if I want to construct a descriptor with the API functions I can only read from a memory. The "Stream-To-Memory" configuration needs an Avalon-ST source - argh! Why is this so hard finding components for this purpose!? Maybe Nios is not normaly used for ADC-Systems... but I've seen many poeple use the PIO for thier ADC's. - Altera_Forum
Honored Contributor
If you don't want to create a custom component neither modifying standard source code, the easiest way to accomplish your task is to use a lpm_fifo in dual port mode.
Connect the write port to your ad9254 component output, connecting wrreq port to a signal which allows you to push into the fifo data at the required sample rate (maybe the valid or output enable signals are already good for this). Then you connect the read side of the fifo to the sopc component; make sure to generate the component with the 'empty' port, in order to know when adc data is available. Then you can use the pio or a tristate bus to extract data from the fifo. You only need to generate the rdreq signal to pop data out. Read the fifo megafunction user guide for detailed information. Choose the optimal fifo depth based on the needed sample rate and on your poll cycle latency. Cris - Altera_Forum
Honored Contributor
That sounds like a really good and simple idea! I know this might be a dumb question (I don't have that much experience on FIFO's):
If I connected the read side of the FIFO to - let's say, the PIO component, wouldn't that still not solve the problem of my poll cycle speed? Because when the FIFO is full, I would have to read faster than the values beeing written into the FIFO. Or am I missing the point? Or should I just take a really large FIFO? I think I would understand it if you explained the last sentence a bit more. Thanks a lot already for all your help! - Altera_Forum
Honored Contributor
Sure, you must in every case read the fifo faster then the values being written into. More exactly, you must be faster on a average. The fifo serves only as a buffer which avoids losing data samples.
The advantage is that you must not continuosly poll the PIO to get data samples synchromously to your adc source, but you can allow data to accumulate into the fifo; then you can read bursts of n values, which is usually a faster process than reading a single data n times. You can conveniently generate the fifo component with the used word port feature and then periodically launch a dma to read the exact number of stored samples. - Altera_Forum
Honored Contributor
Ok, the LPM-FIFO is no problem. If I connected my PIO to the ouput of the FIFO, I don't see how this could interface with a SGDMA. Because the SGDMA can read a whole block of memory (which is actually what I want), but the PIO only has a max. 32-Bit data register. I could just tell the SGDAM to read 4Bytes at a time using the API functions (mem-to-stream). The TSE has an internal transmit FIFO which is an Avalon-ST sink to the outside avalon bus. Would that be a solution? (LMP-FIFO -> PIO -> tx SGDMA -> TSE)
There is also an "On-Chip-FIFO" as an SOPC component and it could interface with the rx SGDMA. But I'd have trouble on the input side of that FIFO which is an Avalon-MM Slave. I would probably have to connect the PIO to there, but the PIO itself is only a MM-Slave. Even another option could be that I write the ADC data into the DDR2 SDRAM. The DDR2 SDRAM-Controller looks pretty complex. I havn't figured out how I can write the ADC data on there. Because my SGDMA's are already connected to the RAM-Controller it would possible to read memory blocks from there. - Altera_Forum
Honored Contributor
In order to read PIO data, with or without DMA, you need a single address, namely your PIO base address. The fifo will automatically pop a single data word on every access.
Using DMA you'll setup the read from this constant address (i.e. RCON bit for DMA controller core, not SGDMA) and the write (with WCON=0) to the buffer you choose, SRAM, DDR2, onchip RAM or whatever. For SGDMA core you have the increment field in dma descriptor insted of RCON/WCON control bits. I think it is possible to dma directly from PIO to TSE but this strongly depends on the ethernet protocol you need to use. - Altera_Forum
Honored Contributor
You should modify your ADC controller so that it writes into a circular buffer. For the circular buffer you could use a piece of on chip memory dedicated to this purpose. You could then have your ethernet controller hooked to that memory and dump large segments of your circular buffer at a time to the PC. You just need to be able to dump the data from the buffer to the PC faster than the ADC controller can fill it up or you will get a buffer overrun. You would be able to achieve the 62Mhz sample rate this way.
Having nios poll an IO block to get samples off of an ADC is not very efficient but it is pretty creative.