FPGA - Handling single clock pulse - Page 1
Forum section: electronics / general

author: pigtwo
author_rank: Regular Contributor
timestamp: April 15, 2016, 08:51:57 pm
content: Hello everyone,I have kind of a vague question that has been bothering me for a while and I can't seem to find a good answer.Say I have a RS-232 receiver that collects data off the RX line and when it has a byte of data it puts it (parallel) on the output and then asserts a signal for one clock pulse to let the other part of the system know it has data. Now say I'm designing a module that will use that receiver and will give the data to another module in a more controlled way(IE buffer data if needed, doesn't require a single clock cycle pulse to be detected, ect).So the main problem I have with this is managing the single clock cycle pulse. It seems to me that I must constantly be watching that signal to detect if it clocked or not. This causes my design to become very complicated(the way I handled it can be seenherewhere the idle process is super complicated because I never let it leave that state but still try manage other things).Is there a better/traditional way to do this?My second question is related to giving data from one module to another. Say I want to confirm that the data was received, what is the traditional way to do this? Right now I use a super basic hand shaking kind of method. For example, if A wants to give a byte to B(assume A and B are independent and B may not always be available to read). A puts the data on the lines then asserts a 'data_ready' pin and waits for B. B sees 'data_ready' asserted and reads the data then asserts a 'data_read' pin and waits for A. A sees that 'data_read' is asserted and knows that the data has been read so it deserts(? terminology) 'data_ready' then waits for B. B then sees 'data_ready' go low, so it pulls 'data_read' low as an acknowledgement. Finally A sees 'data_read' go low and knows that the handshake is over and it can send more data if needed or just do something else.This feels super cumbersome to me but I can't think of another(simpler) a way to guarantee that both sides know the data has been received. What is the convention usually?Thanks for any input and tips on stuff like this I'm always happy to read.

author: lincoln
author_rank: Regular Contributor
timestamp: April 15, 2016, 10:12:24 pm
content: For the first part, sorry i'm not able to follow your code but you might take a look at :http://www.fpga4fun.com/SerialInterface.htmlThere is a number of uart implmentations of open cores.org or as part of pico blaze on xilinx.for the second part, are A and B in the same clock domain? If so you likely only need to pass on an enable. If you are going between town different clock domains you need some sort of handshake, The google term is : "clock domain crossing"

author: uncle_bob
author_rank: Unknown
timestamp: April 16, 2016, 12:15:22 am
content: Quote from: pigtwo on April 15, 2016, 08:51:57 pmHiOk, first point:Everything in an FPGA (and pretty much any proper design) will live in a "clock domain". There is a clock running all the time and it keeps things happening in the proper order. That approach came out in the 1960's and has been pretty much standard ever since.First approach, everything is in the same clock domain:My data byte comes in, it's there, I generate a pulse (one clock cycle wide). It feeds into the enable input on a set of D flip flops that hold on to the data for me. The pulse also goes to the "set" input of an SR flip flop. That drives the output high. It stays high until I feed a pulse into the "reset" input. If I do that when I use the data, the SR acts as a "you have data" indicator.Second approach, stuff in two clock domains:Same idea here, you need to know which clock is faster. The D and the SR still work the same way. The D is clocked in with a pulse from the "upstream clock" regardless of it's speed. The SR is clocked so it still works, how complex that gets depends on the speed of the clocks and the ratio of clock speeds. If the ratio is > 2:1 you probably will be ok with the faster clock on the SR. Considering all the odd issues in sync'ing two odd ratio clocks, that's likely to be the least of your problems.In either case, the answer is a very small amount of logic.Bob

author: rstofer
author_rank: Super Contributor
timestamp: April 16, 2016, 01:36:24 pm
content: I used your handshake method extensively on a minicomputer project. Every IO device is asynchronous to the CPU (all in same clock domain but separate processes) and the handshake method works very well. It's been used for this type of thing clear back into the dark ages.Process 'A' has something to say and raises REQ - 'A' holds data availble until ACKProcess 'B' sees REQ and processes data before raising ACK - in my design, 'B' does everything necessary before raising ACK.Process 'A' sees ACK and drops REQProcess 'B' sees REQ drop and drops ACKThis takes very few states in the scheme of things.

author: uncle_bob
author_rank: Unknown
timestamp: April 16, 2016, 01:46:49 pm
content: Quote from: rstofer on April 16, 2016, 01:36:24 pmHiThat's getting more into the state machine end of things. It still does not take a whole lot. The key there is to be very careful that there are not any odd states that hang everything up. Again, not hard to implement. It can take some thought and planning to get it right.Bob

author: amyk
author_rank: Super Contributor
timestamp: April 16, 2016, 03:20:13 pm
content: Quote from: uncle_bob on April 16, 2016, 12:15:22 amIf the incoming pulse is really asynchronous, you may need to delay the signal a few more clocks to avoid metastability.

author: uncle_bob
author_rank: Unknown
timestamp: April 16, 2016, 07:32:18 pm
content: Quote from: amyk on April 16, 2016, 03:20:13 pmHi... thus the comment about odd issue syncing non integer ratio clocks (I did not quite say it that way before). In a lot of designs, everything comes off a single source and all the clocks have well defined edge alignment, even with them at different frequencies. That can make you lazy about crossing clock boundaries. I have also seen people go to a lot of effort finding "magic spots" between two related clocks.Lots of Fun !!Bob

author: hamster_nz
author_rank: Super Contributor
timestamp: April 16, 2016, 08:16:56 pm
content: He is how I would do it (without two-way handshaking), and assuming the target domain is much faster (5x) than the data...(in the source domain)present the parallel data, and toggle a 'toggle_on_new_data' signal.(in the target domain)synchronize the 'toggle_on_new_data' signalwhen you see the synchronized 'toggle_on_new_data' change (either 0->1 or 1->0) then use the data.This ensures that the parallel data has been stable for at lease a short while (the latency of the synchronizer) before it is consumed.As for the second question, the problem is how do you handle the back-pressure when a downstream module doesn't accept data. A FIFO with an 'almost full' signal is really the only way to do do it.

author: uncle_bob
author_rank: Unknown
timestamp: April 16, 2016, 08:27:23 pm
content: HiOnce more we seem to have headed off into a fairly obvious rabbit hole. With no guidance from the original poster, it could easily be the *wrong* rabbit hole none the less....I *think* we are answering his question. Maybe we aren't really answering it.Bob

author: pigtwo
author_rank: Regular Contributor
timestamp: April 17, 2016, 01:32:58 am
content: Thank you for the replies and sorry for the delay. As mentioned I forgot to describe the clock domains. For this I'm assuming everything is in the same clock domain.@uncle_bob The first case you listed(in your first reply) is exactly what I'm asking and that makes sense. Your method is pretty much what I'm looking for. One question though, I was under the impression that latches are generally not used. Is this one of the cases where it makes sense?@rstofer Ok that's good to know. It's nice to hear that how I was doing it is not just like complete garbage.@uncle_bob(second post)QuoteThat's kind of the problem I have. I have to make it really complicated to make sure that the state machine is not off doing something else when the pulse comes in. My solution was to make one really complicated state that at the beginning would always check the asynchronous input and then do the rest of the duties in that same state. This could be fine but I wanted to see if there is a better way.@hamster_nz I should have mentioned that I'm mainly working in just one clock domain. But your method actually pretty much answers it for me. To make sure I understand(in a single clock domain), the basic idea is to have like a shared register from receiver and sender. Where the sender sets the register for data being ready then the reader clears the register when it reads the data. Thus the sender just waits for the register to be zero before setting it again(in the case of more data ready).Thanks again, I'm going to try to write some code to test out some stuff.

author: uncle_bob
author_rank: Unknown
timestamp: April 17, 2016, 02:06:58 am
content: HiOk, so we have been off in more or less the right rabbit hole.There are two basic sorts of "flip flops with a control" in the empire of FPGA primitives. A latch will follow the input (data) for as long as the control line is high. This makes them a not so good thing to use. A flip flop with an enable input is a different beast. It looks at the state of the control line *only* at the rising edge of the clock. Otherwise it ignores the control line. This makes it a good thing to use.State machines and how to design them is one of those things you simply have to sit down and work on. There are (probably) an infinite number of state machine designs that will implement a specific need. Most people settle into a small number of approaches that they understand and stick with them. One example:If your state machine is strictly sequential and is driven by a counter, the number of "unexpected states" is often reduced. The state machine is pretty much *certain* to be both the slowest and the most logic intensive answer to the question. Since it uses < 0.01% of the available logic and runs 1,000X faster than needed ... not a problem (in my contrived example). Simply put -- you can often trade off "easy to understand" against other spec's without paying much of a penalty.Bob