LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Use of memory block in different clock domains (or some advice to use another approach)

Hi. It is my first post at the NI forums. I did some research about the following problem but I could not find a way to solve it.

 

I have a high speed scanning system, triggered to acquire shots of 200 k samples at a rate of 250 MHz. When the acquisition is done, a scanning motor moves the material to the next spot and triggers a new acquisition of 200 k samples. It works continuously: when the last spot is reached, the motors move back to the fist position and start over. This system should produce real-time tomographic images. After the acquisition, some data processing is necessary: filtering, normalization, FFT, down sampling and so on. Before start acquiring a new image, the system can have a little break to finish the processing and empty the queue, avoiding overflow.

 

At this time, the FPGA code simply acquire the data and send it to the Host VI through a ‘Target to Host-DMA’ FIFO. However, due to the low transfer rate to the host VI, the queue rapidly overflow and it is not enough to acquire 10% of the data necessary for one image. I created another loop that ‘hold’ the acquisition and re-enable it when the FIFO has reasonable space available. All the processing data routines are done at the host VI. 

 

However, I would like to implement the acquisition and all the data processing functions at the FPGA board. For the data acquisition, single-cycle timed loop (SCTL) is used – 250 MHz. Since only few functions work inside SCTL, another clock domain was created with a frequency of 80 MHz – higher loop frequencies generate compilation errors due to time violations.

The problem arises when I want to send data from one clock domain to another. A regular FIFO has size limitations and it still overflows when both loops are working. So, I need a bigger buffer to stack the data before it is processed. Block memory is more feasible for this purpose, but the latency time prevent its use inside a SCTL.

 

So, my question is how to have high speed data acquisition and data processing inside the FPGA. My idea is to use a producer-consumer framework. While the acquisition loop adds elements to the queue (ex. memory block), the consumer loop drops and process it according to its capability. The queue works as a buffer and should be big enough to avoid overflow.

 

My latest code use a SCTL to acquire and send data to a FIFO (please see the chart attached). The timed loop reads data from FIFO and sends it to the block memory (pre-processing). A third loop reads the pre-process memory, execute some functions and adds the processed data to a post-processing block memory. The fourth loop uses a second FIFO (target to host – DMA) to send the processed data to the Host VI. Instead of the original 200k points, only ~5k are send to the host. However, it still fails due to the use of read/write operations of the memory at different clock domains.

 

Is there any other way to implement this code. Or how could I configure the hardware to allow this use.

 

My hardware is:

Chassi PXIe-1082

Acquisition board: PXIe-7965R with an IO module NI 5761R

It also have a PXI-7851R which is used to drive the motors and for another triggering purporses.

 

I appreciate any help. Thanks.

 

 

 

Download All
0 Kudos
Message 1 of 13
(4,550 Views)

You'll want to stream your data through DRAM. Using the DRAM as a large buffer makes it easy to decouple the rate that data is acquired from the rate it is processed as long as your records are finite rather than continuous. If they're continuous then all using DRAM will do is delay the time to takes to overflow.

 

Anyway, if you are using LV 2014 or earlier you should have access to a DRAM FIFO in the form of a socketed CLIP. See the FlexRIO LV Help for more information on the socketed CLIP DRAM FIFO and the example finder Hardware Input and Output>>FlexRIO>>External Memory>>Simple Memory FIFO.

 

If you are using LV 2015 and you install FlexRIO 15.1 then you'll have acecss to a DRAM FIFO that is implemented using subVIs you can drop on the block diagram. See the example finder Hardware Input and Output>>FlexRIO>>External Memory>>Getting Started. Also the getting started example for Controller for FlexRIO demonstrates a slick template that uses the DRAM FIFO in a way that is easily repurposed for use in a PXI system with a 5761.

0 Kudos
Message 2 of 13
(4,522 Views)

You can define a target-scoped FIFO using "in-built" FIFO functionality using BRAM.  I use this in our current software to bridge different processing areas running at different speeds.  You need to make sure that you're using the built-in FIFO functionality that the FPGA card offers, then it works fine (we also use a 7965R).

 

This is assuming that the BRAM implementation can keep up with your 250MHz rates, but at least the different clock rates of producer and consumer are no longer a problem.  I don't think the DRAM interface is going to cut the mustard since it's limited to 200MHz (Max) and is not really deterministic.

 

BRAM FIFO built-in.png

 

Having said that, depending on the width of the data you need to buffer, this might also not work since you only have 8MBit available.  If your data is less than 18bit, you may need to do some bit-packing to get your data to fit, if it can fit at all.  200k Samples divided over 8MBit only allows for (assuming 200k samples) maximum 40-bit values to be buffered but then you're using ALL of the block RAM on your device which will most likely also lead to timing errors as the routing will be horrendous, especially at 250MHz.

0 Kudos
Message 3 of 13
(4,491 Views)

Thanks for the answers. I will check these suggestions and let you know the results.

0 Kudos
Message 4 of 13
(4,461 Views)

I've been trying to use DRAM for the past weeks. To understand how it works, I created a small test project. The idea is to acquire the AN0 input inside a SCTL loop, queue to a 128 bits DRAM  FIFO and read it using a while loop (for further processing). I confess the implementation is not elegant, but it is not the issue here.

 

As you can see in the FPGA.png picture, the acquition part was put inside a case structure, controlled by a button. In theory, it should add elements to the FIFO, only if the button 'Acquire' is pressed. However, I'm continuously receiving data at the while loop (attested by the 'DRAM_Bank1\Data_Available' LED) even if this button is not pressed. My question is: where is this data coming from? I had the same behaviour on my first project. This is the reason I started over, step by step.

 

Thanks.

Download All
0 Kudos
Message 5 of 13
(4,316 Views)

CLIPs run asychronously to the rest of the code on the block diagram. So if you have some IO nodes from a CLIP inside of a case structure, they're still executing even if the case isn't selected. In your code, regardless of what case is selected, you're asking the FIFO if its full, its saying its not, and then stuffing more data into the fifo every single tick.

 

Either stop using a case structure to control the flow of data into a CLIP, or add some logic into the case struture that requires something from outside of the case structure to reach a value of true on the 'DRAM Bank 1/Write' input.

 

0 Kudos
Message 6 of 13
(4,292 Views)

Thanks David-A

 

I notice it when checking the 'Simple External Memory FIFO' example. Now I removed the case structure and conected the 'Acquire' button straight to the 'DRAM Write' input of the I/O node using AND logic with the 'DRAM Full' output. I guess it solves the problem.

0 Kudos
Message 7 of 13
(4,252 Views)

Hi,

 

I am still having some trouble to syncronize the DRAM writing process. It seems when a control is wired to the write note, it works as expected - like the structure implemented in the 'Simple External Memory FIFO.lvproj' - using a control to Enable FIFO Writes. 

 

When the control is replaced by a boolean, I am getting a continous writting, even when the state machine is not in the case that enables the DRAM FIFO write. As you mention before, CLIPS runs asychronously, but in which way could I wire it to work 'as expected'?

 

Please check the image attached. Thanks.

0 Kudos
Message 8 of 13
(4,168 Views)

From the looks of it you shouldn't be writing more than 1 out of every four cycles to the DRAM. How are you verifying that that the DRAM CLIP is commiting records more frequently than that? 

 

Have you set the sync registers to zero? The LV help mentions that the DRAM CLIP may do some funky things if you don't remove the sync registers. 

 

Also, what version of LabVIEW are you using? There may be some libraries I can point you to that assist with things like packing data. For example, the FlexRIO Instrument Development Library has a data manipulation library you may be interested in. 

 

Capture.PNG

0 Kudos
Message 9 of 13
(4,143 Views)

Hi,
I forgot to mention but we are using LabVIEW 2011. Unfortunately, it is the latest version we have licensed here.

 

Thanks.

0 Kudos
Message 10 of 13
(4,134 Views)