LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Reading and writing a local variable in the same Single Cycle Timed Loop

Solved!
Go to solution

I'm trying to determine what the expected behaviour of the code I have snipped below. It's not clear to me from reading the documentation what happens with shared variables in the SCTL. In this snippet I am updating the pulse period by differencing the current value of a tick counter(shift register) with the value of the previous pulse position. This period is written to a local variable.

 

I am concerned because I am also reading from and writing to the previous pulse position variable in the same SCTL. Is it true that the read will be registered at the beginning of the SCTL iteration and that the write will not be registered until the end? If so I expect that the data integrity is maintained; if not, I'm concerned that this could result in unpredictable behaviour.LocalVariableBehaviorTest.png

 

Finally, should my expectations change if I also read from the "Previous Pulse Position" variable in a seperate SCTL or in a top level while loop?

0 Kudos
Message 1 of 13
(5,102 Views)

A SCTL converts your code to VHDL that eliminates any of the pauses to allow for your application to keep up with your desires.  It'd still follow dataflow (as much as you allow it).  It SHOULD read the value, use that value as an input to the calculation, and then overwrite that value in the output.  I say should as you're already playing with some pretty strange design decisions and I wouldn't want to offer anything of a guarantee they'd work as I'd expect.

 

Beyond that, I'd hope a SCTL would throw a compile time error if you used a Shared Variable.  How are you going to have an undeterministic variable in charge of a very deterministic loop with a short period?

 

If you bring a second SCTL into the conversation, you're asking for trouble.  At that point, you're asking us to predict what the LabVIEW code will translate into in terms of VHDL.  Once we have that, you're asking us to measure the time it takes for the electric impulses to push through your FPGA so that we can definitively tell you that you won't have issues with timing between the two SCTLs. 

 

Why aren't you just using a shift register?  It looks like you're creating a variable to handle the primary purpose of a shift register.  It's also far less dangerous than your current method.

 

I didn't download your snippet to verify what interger type you're running.  But, let's explain the problem with a U2 integer (yes, I know it doesn't exist).  Your first iteration is 00, second is 01, third is 10, fourth is 11, fifth is 00, etc.  What happens if your case structure is executed for the first time in the 5th loop?  We see the result is a period of 0.  What if we go from fourth to fifth?  Overflow is a problem when you continually increase the value.  You're not even getting any value out of doing that.  You could get the same behavior by starting with the value 0.  If false, increment.  If true, set back to 0.  Then, you only need to read the value when you go to true instead of subtracting the two points.

0 Kudos
Message 2 of 13
(5,068 Views)

Thanks for the feedback. I will elaborate a little more (perhaps then my decisions wont seems as strange). Also, I see I used the term "Shared Variable" when I meant to say "Local Variable" that might clear things up a little too.

 

The counter is a 64 bit counter, at 40 MHz it would require 14,600 years to overflow so it's not a concern. The reason for doing this is that the counter will be fed to a digital tachometer analysis VI running on the host. The digital tach VI included with the Sound and Vibration suite accept either an event count(ticks) or a period. If you feed the VI a period it just converts it to an event count, so, I thought I'd simply get the count. I'm doing some other processing on the FPGA which requires the period and that is why I'm calculating it.

 

Why not use shift registers? The event counter(Previous Position) needs to be sampled simultaneously with some analog inputs. I can't sample analog channels in the SCTL, so, I thought I'd "sample" the variable in the analog acquisition loop(not shown). The value of "Previous Period" is required for control and protection loops(also not shown).

 

I like the idea you closed with, it neatly avoids reading and writing the same variable in the same loop and saves the difference operation. Can you offer any suggestions for "sampling" or otherwise using(reading) the previous period and position values outside of the SCTL? I had understood from the documentation that this should be acceptable if they all operate within the same clock domain and there are not multiple writers. Is this true?

0 Kudos
Message 3 of 13
(5,061 Views)

How can a boolean be bigger than a boolean? (I guess True is bigger than False, but it might not be if True is -1) That sounds like a dangerous solution.

/Y

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

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 4 of 13
(5,033 Views)

Hi jordani,

 

I see two problems with your code:

- it looks like a race condition to me, when you read from "Previous Pulse Position" and write to it in this case structure. There is no DATAFLOW dependency determining the Read/Write order! (In the FPGA this will be always the same order after compiling, but you don't know the order before compiling…) You know: placing a local variable more to the right doesn't mean it is written later!

 

- There are several coercion dots in your case structures: please define ALL constants with their needed datatype to avoid runtime errors! It seems you initialized the shift register with a I32 constant while your "Position" should be an U64 and your "Period" is a U32. Are you SURE your math is always correct now?

 

Once I heard it might be better to use global variables instead of local variables in the FPGA: this way you remove the FP handling fabric, which allows the host to access the FP elements of the FPGA VI! (This could help when you don't want to read those "variables" from your host VI.)

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 5 of 13
(5,030 Views)

@Yamaeda wrote:

How can a boolean be bigger than a boolean? (I guess True is bigger than False, but it might not be if True is -1) That sounds like a dangerous solution.

/Y



A boolean value being greater than its previous value indicates a rising edge has been received. Initializing the shift to true avoids an initial spurious trigger if the state is changing during FPGA startup and guarantees that the first iteration of the SCTL will not capture a rising edge.

0 Kudos
Message 6 of 13
(5,008 Views)

Thanks for your reply.



I see two problems with your code:

- it looks like a race condition to me, when you read from "Previous Pulse Position" and write to it in this case structure. There is no DATAFLOW dependency determining the Read/Write order! (In the FPGA this will be always the same order after compiling, but you don't know the order before compiling…) You know: placing a local variable more to the right doesn't mean it is written later!


This is exactly why I'm posting here. Outside of an SCTL dataflow would be maintained by registers inserted between the read and the write. Inside the SCTL I know that there are no registers between nodes. It's not clear to me how Labview would implement what I posted any diferently than a shift register. I'm not saying that it wouldn't or shouldn't; just that the diferences are not clear.

 

Regarding type coercion: It's a great point and something I would normaly do. I just put together a minimal example really fast.

0 Kudos
Message 7 of 13
(5,004 Views)
Solution
Accepted by topic author jordani

Hi jordani,

 

why don't you use an additional shift register to hold your "Previous Pulse Position" value? The SCTL should be able to handle it next to those two other shift registers… 😄

 

This way you can assure DATAFLOW and execution order!

check.png

(I have no FPGA module installed on this computer so I cannot compile to test this approach…)

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 8 of 13
(5,001 Views)

@GerdW wrote:

Hi jordani,

 

why don't you use an additional shift register to hold your "Previous Pulse Position" value? The SCTL should be able to handle it next to those two other shift registers… 😄

This way you can assure DATAFLOW and execution order!


This has been suggested (and subsequently implemented); however, I'm still left wishing that I had more information about how the local variables get implemented. My desire to use a local variable is to make this information available to the host using front panel communication.

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

Hi jordani,

 

I had more information about how the local variables get implemented.

They are read/write access to a memory location - however that "memory" is handled in the FPGA…

 

My desire to use a local variable is to make this information available to the host using front panel communication.

What's the problem with the approach in my last message (see the added image)?

You can put local variables in your FPGA VI to access the values of those indicators anywhere…

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 10 of 13
(4,995 Views)