cores/clocks/lattice_ecp5: Fix phase calculation to match Diamond output #1804
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Disclaimer: I am not a Lattice employee and do not have access to internal documentation -- anything below regarding internal workings of the PLL should be taken as conjecture. PLLs are not complicated things though, so it's not that difficult to suss out how they work. 😄
The current phase calculation for ECP5 EHXPLLL has two problems:
div+1
as the scale factor for a complete clock period. This is obviously wrong as a complete period isdiv
VCO cycles, notdiv+1
. I believe the confusion here stems from the fact that the divisor value in the bitstream is actually a counter reload value, and thus one smaller than the divisor. This is not visible in the verilog though; the subtraction is performed in the P&R tool.1 Therefore any assertion thatdiv+1
should be used is likely talking about the bitstream value, not thediv
value used in LiteX which is the verilog value and thus already "+1".With these changes, the following clock setup:
generates
which is identical to Diamond output:
(I created the reference clock manually in this case.)
With the old LiteX code the output was instead
i.e. OP_CPHASE=22, OP_FPHASE=0, OS_CPHASE=11, OS_FPHASE=0 when it should have been OP_CPHASE=21, OP_FPHASE=4, OS_CPHASE=10, OS_FPHASE=2.
Footnotes
This is also why CPHASE should be set to
div-1
for a zero phase -- CPHASE is used as the counter load value on the first cycle, so setting it to the normal reload value ofdiv-1
gives a cycle or normal length, a higher number will result in a longer first cycle giving a phase offset to the following cycles. ↩