09-15-2011 06:47 PM
I have some basic FPGA code that transmits data bits over a serial bus (RS485), The code is written so that it waits in the first state of a state machine in a single cycle timed loop. Upon a certain trigger, it starts reading a FIFO containing data and sends the data out on a Tx line. It does this until all bits are send then it goes back to the first state to wait for the next trigger. The trigger is needed because windows has to fill the FIFO first before the FPGA can start sending.
I need two instances of this code running because I have two com busses (one is redundant). So I am using the FPGA code as a subvi and I wrote a main FPGA vi to call two separate instances of the subvi in parallel. A regular windows vi writes to the FIFOs for Tx and reads FIFOs for Rx. No problem so far.
The trick is that I have to start both transmissions within 200nS of each other (yes, nanoseconds). Windows will write to both FIFOs in parallel, but the timing is 4uS apart, too long. I tried setting up a boolean flag in the FPGA subvi, but windows can't write to the subvi control directly. FPGA won't allow it (the Write function is greyed out). I tried using a FIFO for a flag, but the problem is a race condition. One of the instances will read the FIFO first and wipe it out. The other does not get to read it. I need one common trigger point to be used by both subvi instances.
My final solution was to use a memory in the FPGA subvi and a numeric control in the main FPGA vi. Windows write to the numeric control, It can because the control is in the main FPGA vi. Inside the main FPGA, I run a timed loop that looks for the numeric to be other than zero. If so, it writes the value to the memory location used by the FPGA subvi. After some time, the main writes a zero back to the memory to prevent the subvi from starting up again, and it writes a zero to the numeric to reset it. The whole thing repeats, waiting for windows to write to the numeric again for the next transmission.
I had to do it this way because sometimes I want to transmit on both busses, and sometimes just one or the other. Numeric values are used to determine which to transmit on. Now the transmissions start at almost exactly the same time, 1 or 2 nanoseconds apart. But the trigger process seems very far fetched to me. I was wondering if there is a better solution. I'm pretty new to FPGA.
Solved! Go to Solution.
09-15-2011 09:17 PM
How about a variation on your current idea: create 2 FPGA-only FIFOs. In your main VI, when you want to trigger the transmit, write to the FIFO (one or both depending on which channel you want to trigger). Inside the subVIs, wait for an element in the FIFO, and when one appears, send packets. No need to worry about resetting a memory location. In your subVI you can put a case structure to determine which FIFO to read, so that you don't need two separate copies of the subVI to handle the two FIFOs. With a constant wired to the case selector (even indirectly, from the main to the subVI) the FPGA compiler should be able to optimize out the unused case in each subVI. I expect this will be more space-efficient on the FPGA than your current approach.
09-16-2011 10:38 AM
I've already tried that approach. The problem is that windows will not write to each FIFO at the exact same time, even though the two operations are in parallel. The result is that data appears in one FIFO approximately 4uS before the other. So one transmission starts 4 uS before the other. This is not acceptable. I need the two transmissions to start within at most 200nS of each other. Ideally I want the transmissions to start within 2nS of each other. That is why I need one trigger to start both transmissions at the same time. I don't like the way I'm doing it, but I see no other method. It would be nice if I could set up a Wait for Occurance in the FPGA code and send the occurance from Windows code. Then I could load the FIFOs, and then send the occurance. I haven't really tried this, but I was told that you can't write to a FPGA subvi from Windows code because the windows code connects to the main FPGA vi only.
09-16-2011 10:59 AM
09-16-2011 11:45 AM
tbob
Could you put both instances into the same State-Machine subVI. You could even add code to write A or b or A&B where A & B are two independant RS485 serial busses.
I had to do this for a special instance of a dual SPI where I had two Data Out lines to write simeltaneously.
09-19-2011 11:52 AM
@nathand wrote:
You've misunderstood. You can create an FPGA-only FIFO to allow FPGA loops to pass data. You would use two of these, on for each loop. Windows would send a single value to your main FPGA VI (over fpga or front-panel control). The main fpga VI then puts values in the FPGA FIFOs to trigger the transmission.
I think I understand. From windows, write to a FIFO that is in the FPGA Main vi. From FPGA Main, write to two FIFOs which reside inside the FPGA subvi. Inside the subvi, I could read each FIFO, dependant on the bus I am using. The two FIFO triggers should then execute at the same time, or at least within a few nanaoseconds of each other.
Basically I did the same thing using FPGA Memory. From windows I write to a numeric control which resides inside the FPGA Main vi. In the FGPA main, I write to the Memory. Inside the FPGA subvi, I read the memory and decode the value to either use one or the other or both busses. After fooling with this for some time, because the Read Memeory needs to use a shift register (probably due to it taking an entier clock cycle), I got it to work. Both busses trigger at the same time. I guess it really doesn't matter if I use a FIFO or if I use Memory. The main issue is that I have to write from Windows to the FPGA Main, and then from the FPGA Main to the FPGA subvi. Then the timing is exact as far as the subvi is concerned.
Thanx for you help.
09-19-2011 12:03 PM
@SPECTRE Dave wrote:
tbob
Could you put both instances into the same State-Machine subVI. You could even add code to write A or b or A&B where A & B are two independant RS485 serial busses.
I had to do this for a special instance of a dual SPI where I had two Data Out lines to write simeltaneously.
I actually thought about that. But since I sometimes have to start one bus 200nS later than the other, I would have to put independent loops for each bus in the same vi, so that each had its own state machine. The route I took seemed less complicated. Same code, just two instances. Now I can trigger one or the other or both, and I can skew the start times of each relative to the other.
Thanx.
09-20-2011 11:53 AM
tbob wrote:
Basically I did the same thing using FPGA Memory. From windows I write to a numeric control which resides inside the FPGA Main vi. In the FGPA main, I write to the Memory. Inside the FPGA subvi, I read the memory and decode the value to either use one or the other or both busses. After fooling with this for some time, because the Read Memeory needs to use a shift register (probably due to it taking an entier clock cycle), I got it to work. Both busses trigger at the same time. I guess it really doesn't matter if I use a FIFO or if I use Memory. The main issue is that I have to write from Windows to the FPGA Main, and then from the FPGA Main to the FPGA subvi. Then the timing is exact as far as the subvi is concerned.
There are a couple of advantages to using two FIFOs over your approach. First, you don't need the shift register for the memory location. Second, you don't have to worry about which VI is responsible for clearing the memory location, nor do you run the risk that one of your subVIs will execute twice, or not at all, if the memory isn't cleared at the right time. Perhaps most importantly, you'll save yourself space on the FPGA because you won't need arbitration - the extra code that gets added when two parts of the FPGA try to access the same resource at the same time. In your case, both instances of the subVI access the memory block concurrently, so the FPGA compiler adds extra logic to prevent conflicts. If you only read the memory block in one place and only write it in one place (the read and write can be in different loops or subVIs) there's no need for arbitration. By using two FIFOs you can keep them independent and avoid the conflict resolution code. See the help for "arbitration" for more details.
09-22-2011 05:52 PM
nathand:
I did implement the FIFO approach. It works just as well as the memory approach. Now I don' t have to worry about clearing the memory before the next transmission. Reading the FIFOs already does that. Thanx for your help.