-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reconsidering AsyncFIFO and resets #181
Comments
Comment by sbourdeauducq Sounds good. |
Comment by whitequark AsyncFIFO currently doesn't support non-power-of-2 memories anyway so it has no illegal states. And I'm not sure if it's possible to support such memories while still using a Gray counter. |
Comment by jordens Good. |
Comment by whitequark
I've thought a bit about this, and the exact same approach would work, since the FIFO is already symmetric: set the write pointer to the read pointer. In fact, it's possible to simplify this further: instead of an explicit clear signal, use the |
Comment by programmerjake one problem you may run into is that resetting changes multiple bits simultaneously in the grey-counter read and write pointers, so relying on just flip-flops to synchronize the signals won't work anymore, so there will need to be some sort of reset synchronization mechanism anyway |
Comment by whitequark @programmerjake You are (unfortunately, for this approach) completely correct. I will need to find a different one. |
Comment by sbourdeauducq For the
|
Can we require that the control sets on the read and write ports share a (logical) reset signal? Reset synchronizers would still result in physically distinct reset signals but if both domains are reset simultaneously the problem becomes much easier (this appears to be the assumption held by the Sunburst Design papers). If not, it may be worth trying to work out a solution to this problem with the reset synchronizer approach:
I'm not completely sure, but it seems like a synchronized feedback mechanism such as that described on page 17 of Cummings' SNUG-2008 paper could be used to solve this problem. Obviously such a solution would need to be thoroughly analyzed and ideally formally proven to be correct, which is why I proposed the first option first. I'll think on this more and maybe float some designs here if I come up with anything. |
What do you mean exactly by "share a logical reset signal"? Would a case where one side uses synchronous reset and has a free-running clock, and another side uses asynchronous reset and has a clock that may be stopped indefinitely, count as sharing? |
What I mean is essentially that the write clock domain is never reset without the read clock domain also being reset. The scenario you describe would count provided that the side with the asynchronous reset could not miss a reset pulse asserted while its clock was stopped. That may or may not be achievable depending on the specific topology, which is why we'd have to impose restrictions in nMigen someplace, I think. |
Per IRC discussion, we decided that it makes the most sense to change AsyncFIFO as follows:
|
Working through a design using an |
Seems a bit niche, but I'm OK with having it. Naming bikeshed: |
Works for me. |
@awygle FYI IIRC the LiteX stream stuff uses "start of frame/packet" and "end of frame/packet" type signals for this. Then on a SOF signal you reset the receiver. There is some complications between a SOP signal signal the data in the fifo synchronization verses SOP being used to reset... |
I think you still need a SOF signal once this issue is fixed, since a read domain reset doesn't flush the FIFO. Thus once the reader comes out of reset it'll have to realign to the framing somehow. |
Is this fixed now? We did make the described changes to resets. |
@awygle I think this part is missing. |
Ah, fair point. |
Issue by whitequark
Thursday Aug 22, 2019 at 02:05 GMT
Originally opened as m-labs/nmigen#180
Both ports of a SyncFIFO belong to the same control set, which means that the entire FIFO is always reset at once.
However, the ports of AsyncFIFO belong to different control sets, which means that, if either if the control sets includes a reset, only half of the FIFO will get reset; and as a result, stale data will be read.
In some cases, this problem may be alleviated by using a reset synchronizer: one port is chosen as the one that resets the entire FIFO, its reset signal is brought into the other clock domain, and used to reset either the entire clock domain, or only the port state. However, if the duration of the reset pulse at the leading port is shorter than the clock period of the following port, the following port will not be reset properly, and stale data will be read. In particular this happens if the clock to one of the ports is gated completely.
In some cases, this problem may be further alleviated by using asynchronous reset (of course, with synchronous release) for the entire clock domain of the following port. However, this carries the restriction that the entire domain has to be reset: since the assertion of the reset is not synchronized to the clock of the following port, it incurs metastability. Further, many FPGA elements will not be inferred from logic that is asynchronously reset, notably BRAMs and DSP blocks, severely penalizing this design.
It seems that there is no easy solution to the issue of resetting AsyncFIFO reliably in all circumstances, making it a completely safe design element that never spuriously produces stale data. I would suggest the following:
This solves everything described above:
ResetSignal("read")
in the FIFO). Therefore any garbage data is eliminated from FIFOs oriented in both directions before the reset is deasserted.One possible logic bug with this scheme would be a case where the CDC FF chain inside AsyncFIFO is for some reason longer than the FF chain inside the reset synchronizer used to reset the following domain. Ideally, the CDC checker (#4) should flag any such cases.
The text was updated successfully, but these errors were encountered: