• 0
amb5l

new Nexys Video example designs

Question

13 answers to this question

Recommended Posts

  • 0

@amb5l,

Thanks for sharing!  It's always fun to have a project to share, and such projects can be a real encouragement for newcomers.

Looking over your design, I found this piece of it which appears to include a clock domain crossing within it.  Just from a desktop review, it also looks like it would drop samples or duplicate.  Have you tested this using a counter running through it, at both proper clock rates, to see what would happen?

Dan

Share this post


Link to post
Share on other sites
  • 0

Dan,

I appreciate your feedback. audio_axis.vhd moves audio samples from the CPU clock domain (100MHz) to an audio sample rate interface (48kHz). Specifically, it pulls the samples - one at a time - from the AXI Streaming interface of a FIFO that is coupled to the MicroBlaze CPU. The low audio sample rate means timings are very relaxed and it all seems to work fine. Tests on hardware work OK; I've listened to classical music for hours (with the modulation disabled!).

I will look at an exhaustive test; the simulation testbench is very basic and does not yet support automated testing.

-Adam

Share this post


Link to post
Share on other sites
  • 0

@amb5l,

You might want to consider posting this to the Digilent Project Vault, where it belongs. By posting it to where lots of FPGA related questions are posted every day your visibility will disappear making it invisible to most visitors. Just a thought.

Edited by zygot

Share this post


Link to post
Share on other sites
  • 0

@amb5l,

I think you'll find that an asynchronous FIFO is a much better approach to moving data streams across clock domains.

I would also recommend against using the FDRE primitive within your design.  It'll tie you to the Xilinx infrastructure, and make it a challenge to move your design to other (non-Xilinx) contexts.  If you just use a straight VHDL register, Vivado should be able to infer the FDRE directly--so you shouldn't need to instantiate it.  That would also leave you with a more generic, (more) vendor-independent design.

Dan

Share this post


Link to post
Share on other sites
  • 0

@[email protected]

Understood. You're not wrong - I've used FIFOs, in fact I wrote my own hairy controller for an async FIFO on a Virtex-1 about a million years ago; gray coded pointers etc; it was the only way I could get that generation of parts to move data @ 100MHz. I can't remember why I didn't use a FIFO in this design but - given the glacial data rate - the design does function just fine  with double syncing between the domains. I think of the arrival of an audio sample in the FIFO as being a bit like an occasional button press - and by the time the FIFO ready status has ripped through the syncing registers, the data is well and truly stable. I think I used multi cycle clock constraints previously rather than asynchronous groups to make this reasoning a bit more apparent.

I take your point about vendor specific libraries, and inference. This project started life as an experiment to design yet another clone of the good old 6502 CPU. That design is not up yet, but is nearly ready. I've had to go quite vendor specific to get it to perform (it runs like an original NMOS 6502 clocked at 150MHz). In fact the VHDL is a bit like a schematic converted straight into VHDL. I've developed a few bad habits along the way!

Share this post


Link to post
Share on other sites
  • 0

I regularly use the dual clock FIFO IP from vendors for moving data between clock domains. I'm not sure that @[email protected] and I have the same definition for  asynchronous fifo but if you read the vendors IP documentation it does mention issues with flag timing. When necessary I just find alternate methods of keeping track of data counts.  If you instantiate the Series7 hardware IO_FIFO then what you get is a dual clock FIFO, though it isn't BRAM or LUT based.

Really, I believe that the point to make is that you need to understand what it is that you instantiate and how it behaves.   

Share this post


Link to post
Share on other sites
  • 0

@zygot,

I didn't think there were that many possible definitions for asynchronous FIFOs, so I'm not sure how our definitions might have gotten crossed.  By my definition, an Asynchronous FIFO is a FIFO that crosses clock domains.  It may (or may not be) mapped to specific hardware.  The pointers are typically passed across clock domains via gray pointer, as @amb5l has mentioned.  The full/empty flags of the resulting FIFO can also be used to make certain that the FIFO isn't read while empty or written to while full.  Further, until full, the write side can operate at full speed.  Likewise, until empty, the read side can operate at full speed.  The pointers prevent the data path from getting near too close to the actual clock domain crossing.  What other definition would you offer?

Dan

Share this post


Link to post
Share on other sites
  • 0
49 minutes ago, [email protected] said:

By my definition, an Asynchronous FIFO is a FIFO that crosses clock domains.

By my definition a Dual Clock FIFO is one that allows for moving data from one clock domain to another.  A Single Clock FIFO can't do that. Asynchronous to me implies combinatorial logic that isn't clocked. But perhaps we've just been reading different material.

I've got no problem with your home grown FIFO. But I would point out that all IP, vendor supplied or home grown, has limitations which have to be documented, In all of my years of VHDL development I've never felt the need to write my own basic IP like FIFOs, RAM, etc. If you need to minimize resource usage, then it might be worth the effort. For FIFOs I often have asymmetric widths on the write and read sides. Yes you could design your own but at some point you realize that trying to make one grand Ip that does everything for all purposes for all applications suffers the the law of diminishing returns. As long as I can use vendor IP for FIFOs I've found it to be quicker than the alternative. I'm betting that I've completed more designs instantiating clock domain data fifos than you have so I'm not ignorant on the subject.

Of course, as a learning exercise,  which is what your asynchronous fifo link points to, writing your own can be a worthy use of time.

 

 

Share this post


Link to post
Share on other sites
  • 0

@zygot,

27 minutes ago, zygot said:

By my definition a Dual Clock FIFO is one that allows for moving data from one clock domain to another.  A Single Clock FIFO can't do that. Asynchronous to me implies combinatorial logic that isn't clocked. But perhaps we've just been reading different material.

Ok, that's fair.  I'll agree we've probably been reading different material, but this idea is new to me.  Thank you for sharing it.  I like your distinction, and I may choose to use it in the future.

28 minutes ago, zygot said:

I've got no problem with your home grown FIFO. But I would point out that all IP, vendor supplied or home grown, has limitations which have to be documented

You didn't read far enough.  The article I quoted didn't include my home grown FIFO, but rather one I found on line that came highly recommended to me by others.  The article goes through explaining how that FIFO works, and then how to go about formally verifying it--which also (BTW) involved pointing out any assumptions made when building it.  I found it a very useful exercise, and one that helped prepare me for a job where I didn't have access to either Xilinx or Intel's vendor libraries.

31 minutes ago, zygot said:

Yes you could design your own but at some point you realize that trying to make one grand Ip that does everything for all purposes for all applications suffers the the law of diminishing returns. As long as I can use vendor IP for FIFOs I've found it to be quicker than the alternative.

That's fair, and it's a valid position as well.  I'm glad it's worked for you so far, and I wish you the best using it into the future.  Certainly I enjoy making my dollars by posting the grand "it does everything" item, and then building the customized versions for individual customers.  It's worked for me so far, and I've certainly enjoyed it.  Even better, that article was among the top-3 all time hits on the blog all last year, even ranking so high as #8 on a search for "Asynchronous FIFOs"--so there are plenty of others interested in it as well who have also enjoyed reading it.

Dan

 

Share this post


Link to post
Share on other sites
  • 0

@[email protected],

All good. Perhaps my first post turned a non-issue into a paper dragon. I really just wanted to mention that vendor IP, especially for basic structures, doesn't need to be ignored. I'm all for designing my own IP as long as it ends up doing what I think that it should. It's a balancing act. A lot of my paid projects wouldn't fit if I only used vendor IP. On the other hand doing you own requires extensive verification, and more importantly lots of use running on hardware. I didn't look through the code so I'm guessing that he used a single clock FIFO without considering clock domain crossing analysis. Perhaps if I'd read his code  I wouldn't have adding my 2 cents in the first place.

I have no doubt that there are a lot of people finding your blog interesting an informative as not everyone has someone knowledgeable to offer mentoring.      

Share this post


Link to post
Share on other sites
  • 0

I have discovered the  xpm_cdc_handshake macro ("Bus Synchronizer with Full Handshake") which appears to be a well sorted way to do what I want (to move parallel data from a slow to a fast clock domain, without consuming FIFO resources). I'll try it and report back.

Edited by amb5l

Share this post


Link to post
Share on other sites
  • 0
6 hours ago, amb5l said:

I have discovered the  xpm_cdc_handshake macro

Xilinx script generated code and resources provide a lot of interesting solutions to problems. Some of what Vivado deposits into your project directory is encrypted sources, but most are not particularly easy to read text, and often well worth the gander. One problem with script generated code are irritating things like std_logic_vector(0 downto 0). Still, I say you're on the right track.

Just make sure that you understand what your found solutions are doing and what they are intended for. But that's just SOP.

Edited by zygot

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now