Skip to content
Adam Gastineau edited this page May 5, 2023 · 1 revision

For more advanced PLL options, see PLL Reconfig

PLL Constraints

  • Intel PLLs on Cyclone V can be configured as Integer or Fractional. Integer is going to more accurately output integer clocks, whereas Fractional may struggle on integer clocks, but will solidly meet the fractional values (see next item)
  • Sometimes clocks don't have a common divisor, like 11MHz and 7.578MHz. A single PLL block will have trouble meeting both of those frequencies exactly, as they are not easily related by a single divider circuit. You can solve this generally by using a separate PLL, or by making your clocks be a common multiple

Clock Domain Crossings (CDCs)

Clock domain crossings are an easy way to trip up beginners. The following is a copy of a chat discussion I had with someone, teaching them about CDCs:

So when you have any nets that aren't in a given "clock domain" (this could be an async input from a button (doesn't apply to Pocket, they're synced), data from another clock domain, etc), you need to synchronize the data moving between those domains if you use them

Picture clock 1 at 33MHz, and clock 2 at 34MHz. Obviously these are slightly out of phase, and so they will oscillate around each other. Now if you want to read data from clock 1 in clock 2, when you're reading relative to where clock 1 is will keep changing. Depending on your timing, that could change right as your flip flop (the register) is setting the data, and now you have a condition called metastability. This means your flip flop is literally stuck between both voltage levels.

Besides wrecking havoc on your design, this can mess up A LOT of stuff in your FPGA. Completely unrelated things will break randomly and you'll be very confused. For the Pocket stuff, all of the nets coming into your core are synched to the clk_74a clock. Buttons, data from data.json loaded assets, etc (this also applies to the audio and save data coming out of the core) all need to be synchronized against your using clock to prevent weirdness and glitches

Synchronization for a single bit is generally accomplished with a chain of flip flops, where a longer chain increases the MTBF (mean time between failures). 2 registers is a generally agreed upon length, though I always use 3 just because

THIS DOES NOT WORK FOR MULTIPLE BITS. Analogue does this in their examples, and I don't know why. If you try to synchronize multiple bits in this manner, what can happen is while you'll always get a stable value, it won't necessarily be right

Say we switch from 2'b00 to 2'b11. If we pass between clock domains, we could see the output values as 2'b00, 2'b10, 2'b11. Obviously if you care about this, you don't want to do this

So for multiple bits, you use a dual clock FIFO, which is a memory block designed for handling multiple clocks. This is a pain to interface with though

For Pocket, I have wrapped up most of the sync primitives and stuff into relevant IPs. You can use them if you'd like, or not https://github.com/agg23/analogue-pocket-utils

Integer Divisors

Additionally, you can avoid crossings if the clocks have a common integer divisor. Take 100MHz and 10Mhz. These domains remain perfectly in sync with each other, not moving out of phase to one side or the other. Data can transfer from fast to slow (100MHz -> 10MHz) or slow to fast (10MHz -> 100MHz) without potentially having random bits flipped, so in essence they are the same clock domain.

Clone this wiki locally