LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Easier more elegant way to instantiating two CLIPs?

Solved!
Go to solution

I'm using NI FPGA to program a FlexRIO.  I've got a module that I've written in VHDL and imported as CLIP inside my project.  I can instantiate the CLIP interface and read/write to my VHDL code without problem.

 

What I'd ultimately like to do is instantiate multiple instances of the same CLIP module.  Same code, just replicated multiple times in my VI and all processing in parallel.  Unfortunately it doesn't seem like there's an easy way to do this besides declaring a second, third, fourth, etc. copy of my CLIP interface and also creating a whole new set of controls and indicators for each CLIP interface. 

 

It becomes very burdensome for me because I now have a project full of the exact same CLIP module, but have to manage each one individually if I make a change.  It's also a burden on the Host VI (or Software if I export this to the C API), because software has to manage an entire set of controls/indicators for each instantiation of the CLIP.

 

I'm looking for solutions that may make this more elegant.  Is there an easier way for me to instantiate multiple of the same CLIP instance and make it easy for software to manage the ins and outs of that CLIP? 

0 Kudos
Message 1 of 12
(3,713 Views)

Have you created a subVI that contains the CLIP? And did you configure this subVI to be reentrant preallocated clone?

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 2 of 12
(3,669 Views)

Well in NI FPGA all subVIs are reentrant by default .  I tried just now to add some VHDL code to my CLIP interface that takes an input u32 logic vector and just loops it back to an output u32 logic vector.  I imported that CLIP code and then I created a subVI with IO nodes that write a u32 value and read the u32 response, as well as set a boolean and loop a boolean back out.  I then dropped that submodule down 3 times inside a higher-level single cycle timed loop.  

 

The boolean control/indicator loopback works as you'd expect, but the problem there is that all of the FPGA IO nodes are referencing ports from the same CLIP module.  It's not replicating the CLIP interface every time I drop down the subVI.  So if I changed the u32 value on any of the inputs to any of the submodules, that value will be reflected on all 3 submodules' outputs.  

 

Is there a way to do reentrant implemenation of CLIP modules themselves?

 

By the way here's the block diagram with my submodule code copy/pasted in to it, and the result.  my CLIP interface is called "mux", it has input u32 ports "ip_reg", and mirrors the value of ip_reg onto an output u32 port called "op_reg".

my NI FPGA VI and a look into the submodule codemy NI FPGA VI and a look into the submodule coderesultsresults

 

0 Kudos
Message 3 of 12
(3,632 Views)

Since you have to error wire forcing execution order your op_reg can easily be read before ip_reg is written.

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 4 of 12
(3,625 Views)

Sorry, I'm not sure I understand what you're saying here.  Can you elaborate please?

 

EDIT: Oh, I think you're saying that since I don't have an error wire connected between the two FPGA I/O methods I could read the value of op_reg before ip_reg was written.  Can you elaborate on what that has to do with the question I posted?  My problem is that when I write a value into the input of any of these subVIs, all 3 subVI outputs change, not that I'm running into any race conditions between reading and writing registers. 

0 Kudos
Message 5 of 12
(3,620 Views)

Well if you work with IO nodes then the whole parallelization only makes sense if you use different IO names in the subVIs. Also IO nodes and constants and globals in LabVIEW work like that that they are read first if there is no data dependency that forces something else! Then the IO is written to the IO nodes but only clocked out at the end of the loop. So all your multiple writes to the same loop do overwrite each other.You do definitely not want asynchrous updates of IO signals whenever an IO write is executed as that would give you spurious spikes and such and very skewed timing at the output signals.

 

Parallelization works with reentrant VIs even with CLIPS inside but IO nodes are global resources and can't be instantiated multiple times. You can't split an IO pin into multiple pins! 🙂

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 6 of 12
(3,618 Views)

I think I understand now. Is there a difference between using a flat sequence structure or propagating the error channel between IO nodes for breaking up those asynchronous writes?

 

Also I feel as if we've gotten off topic here a bit.  I agree that if I use an IO node I should be using different IO names for parallelization.  I guess my main question is in the instantiation of the CLIP interface itself. In VHDL I could use a "for/generate" loop to generate N instances of any module.  Is there any similar construct in LabVIEW?  Can I generate N instances of a CLIP interface and then interact all of those independently? Or is my only option to manually instantiate each CLIP instance within my project and then allocate dataflows to those IO nodes manually based on signal name?

 

What would be the suggested way to create a reentrant SubVI that can allocate signals to different CLIP IO names?  Is there an example you can point me to?

0 Kudos
Message 7 of 12
(3,590 Views)

@RichC41 wrote:

 

What would be the suggested way to create a reentrant SubVI that can allocate signals to different CLIP IO names?  Is there an example you can point me to?


You would create an IO Constants on the calling diagram and pass this through an IO Reference to the subVI and connect that reference to the according terminal on the IO Node.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 8 of 12
(3,569 Views)
Solution
Accepted by topic author RichC41

Hey RichC41,

 

I want to jump back to your original question, and maybe discuss why I think re-entrant VIs won't get you the behavior that you want in this case.

 

I'll start with the 2 ways to integrate IP into LabVIEW: CLIP and IPIN. I'm going to reference this document: https://knowledge.ni.com/KnowledgeArticleDetails?id=kA03q000000x0jiCAA&l=en-US

 

One important thing to note about CLIP is illustrated in figure 1.

figure1_20110523094400

 

Clip executes asynchronously with the LabVIEW FPGA diagram. Each instance will be instantiated and run independently from what your LabVIEW diagram is doing. This is done at the project level. In the case we're discussing here, specifically around re-entrant VI access, you likely won't get the behavior you're expecting, as you'll be calling the same CLIP instance, just from another point on the diagram. I suspect that this will give a compilation error, but if you see something else, let me know. If you're accessing the CLIP from within a SCTL, that will prevent LabVIEW from arbitrating the accesses, and we should through a compile error.

 

If asynchronous instantiation like this is the style of IP Integration you're looking for, then I suspect managing each instantiation in the project is your simplest/cleanest/only option I can think of.

 

That leads me to the other method we have of instantiating VHDL: the IPIN node. The IPIN node executes synchronously within the LabVIEW diagram. You place it inside a SCTL, and every clock cycle of that diagram, a clock cycle will pass in the HDL. In the case where an IPIN is contained within a re-entrant VI, each 'clone' (I prefer to think of them as inlined subVIs in the FPGA case) will get it's own instance of the IPIN. The trick here is making sure that your HDL is written in a way that properly handshakes with the LabVIEW diagram, unless your algorithm/process accepts new data every clock cycle and produces new data every clock cycle with a latency of 0 cycles.

 

Not sure if that really helps your original architecture question or not, but my suspicion is that the only way to get the behavior I think you want using CLIP is to have multiple instantiations of your IP.

Cheers!

TJ G
Message 9 of 12
(3,529 Views)

That's incredibly interesting! I did not know that actually.  I think that's going to take a lot more thought and implementation on my end, but I do actually think that may solve part of my issue. 

 

One last question I guess:  it looks like this may solve my issue for being able to instantiate multiple copies of the same IP.  The way I'm transferring bulk data to my CLIP nodes now is via the DMA FIFO.  Each instantiation of my code needs a DMA FIFO.  Is there a way to similarly iteratively generate FIFOs within a subVI, or for that do I need to generate all of my FIFOs in the project and explicitly reference them using different names?

0 Kudos
Message 10 of 12
(3,512 Views)