Skip to content
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

Include PLL example in Blinky #1

Open
vstrakh opened this issue Mar 7, 2020 · 8 comments
Open

Include PLL example in Blinky #1

vstrakh opened this issue Mar 7, 2020 · 8 comments

Comments

@vstrakh
Copy link

vstrakh commented Mar 7, 2020

I'm happy I can finally start playing with the AG1KLP chip using your examples as a basis.

But there's one thing that darkens my day. It seems I can't make AF place&route designs with PLL instantiated. Yosys does its job, but AF then either crashes with exception (alternatively sefgaults), or stops, telling that "Slice pll|clkout0~ALTA_GCLK is not yet packed, ignored for placement".

I understand there must be some tech-related strict requirements on global clock nets and pll outputs handling, so the Yosys and AF must include required primitives (alta_gcksel, etc). But when I naively add alta_io_gclk buffer to the PLL output in my sources, I get AF failing to read DB design in place&route, because it did produce intermediate files with syntax errors "unexpected '(', expecting ID at ./output/alta_db/filtered.vx" where it inserted unnamed instance of alta_io_gclk after the alta_gclksel.

I hope you can shed some light on the issue, and include the example of valid PLL instantiation with Yosys, conforming to the chip's requirements. I did try suggested workflow with Quartus, but it seems it's not possible with free Quartus Lite Edition, which doesn't support the design partitions.

@pablomarx
Copy link
Owner

@vstrakh I've added a branch ag1k-pllx which has a new directory under examples, blinky-pll. This resolves the crashing issues with af, and af now emits a bitstream.

@pablomarx
Copy link
Owner

The PLL may not be working on the hardware yet – this is why I've left it in a branch instead of merging into master. Looking at output/Blinky_routed.v this inclk doesn't look terribly reassuring:

alta_io_gclk \pll.PLL40_AD8D879E|clkout0~ALTA_GCLK (
        .inclk(\gnd~I_int ),
        .outclk(clk40));

@pablomarx
Copy link
Owner

The PLL is definitely being enabled in the bitstream.

Using agm-unpack and agm-explain, the existing blinky example has:

.config_chain 1
CLK_EN1: 0
CLK_EN2: 0
CLK_EN3: 0
CLK_EN4: 0
CP: 000
DLYNUM_G1: 000000
DLYNUM_G2: 000000
DLYNUM_G3: 000000
DLYNUM_G4: 000000
M_G1: 000000
M_G2: 000000
M_G3: 000000
M_G4: 000000
M_M: 000000
M_N: 000000
PLL_EN_FLAG: 0
PllClkFbMUX: 0
PllClkInMUX: 00
PllIntFbMUX: 00
PllSeamMUX0: 000
PllSeamMUX1: 000
RLPF: 00
RREF: 00
RVI: 00
SELCLK_G1: 000
SELCLK_G2: 000
SELCLK_G3: 000
SELCLK_G4: 000
__NAME: PLL

Whereas this new blinky-pll has:

.config_chain 1
CLK_EN1: 1
CLK_EN2: 0
CLK_EN3: 0
CLK_EN4: 0
CP: 010
DLYNUM_G1: 000000
DLYNUM_G2: 000000
DLYNUM_G3: 000000
DLYNUM_G4: 000000
M_G1: 000100
M_G2: 111111
M_G3: 111111
M_G4: 111111
M_M: 111111
M_N: 100000
PLL_EN_FLAG: 1
PllClkFbMUX: 0
PllClkInMUX: 10
PllIntFbMUX: 00
PllSeamMUX0: 000
PllSeamMUX1: 000
RLPF: 10
RREF: 10
RVI: 10
SELCLK_G1: 000
SELCLK_G2: 000
SELCLK_G3: 000
SELCLK_G4: 000
__NAME: PLL

@vstrakh
Copy link
Author

vstrakh commented Mar 8, 2020

I see. I didn't know about 'place_pseudo' tcl command. The af help didn't list it.

It seems that the gnd at the global clock input comes from earlier stages. The file alta_db/flatten.vx has implicitly inserted cycloneive_clkctrl instance which looks totally wrong. Not only it puts the clocks into seemingly wrong order, selecting the gnd for output, it has ena control input grounded too, so at the filtering stage p&r had no options but to ground the clock input. Even if PLL is running, the global clock net will be grounded...

// Location: CLKCTRL_3
cycloneive_clkctrl \pll.PLL40_AD8D879E|clkout0~ALTA_GCLK (
	.inclk({clk40_int, gnd, gnd, gnd}),
	.clkselect({gnd, gnd}),
	.ena(gnd),
	.devpor(),
	.devclrn(),
	.outclk(clk40));

@vstrakh
Copy link
Author

vstrakh commented Mar 8, 2020

Hmm...
Explicitly inserting fixed cycloneive_clkctrl instantiation into Yosys .vqm output seemingly did the trick. To make it with the original source I had to add a blackbox declaration of cycloneive_clkctrl module, it got translated into the .vqm, and af looks satisfied. The *_routed.v has correct alta_io_gclk, taking input from pll's clkout and feeding the global clock network.
agm-unpack/-explain confirms pll instantiated and enabled, but it'll take time to verify the performance within the device, which isn't exactly an evaluation board, so will be inconvenient :)

@pablomarx
Copy link
Owner

Awesome! Cursory test works on my dev board – although it works without any input to the PLL's clkin. This may be expected behavior though - from MANUAL_AG1280.pdf:

AG1280 can use the internal PLL to output the clock when there is no input clock, which can be used as the system clock, thereby simplifying PCB design.
Because the output frequency is divided by the VCO, the actual results and set values will be slightly different, and the characteristics of different chips will be slightly different, so this internal clock is only suitable for designs that do not require high frequency accuracy.

Thank you for figuring this out!

@vstrakh
Copy link
Author

vstrakh commented Mar 9, 2020

Some chinese pdf I've seen tells that pll might work on its own ("saving the crystal") when it is configured with NO_REFERENCE feedback mode, and the example suggested connecting clkout0 to feedback input. The tool reports frequencies that aren't very close to the ones desired, like VCO is fixed to a predefined value corresponding to 370 MHz.
So you need EXT_FEEDBACK to let it lock to external clock.
And the other pdf was telling that the feedback input must always be connected to a clock source. I don't know what it should be in the typical case - the source clk, or one of pll clock's outputs, that's to be tested out on a real hw.
The pllx has no option to use internal feedback at all, though the blurry pic in the public pdf shows mutex that can select internal feedback. But then its inputs are connected to pll's own clkouts, so that might be the expected approach.

It's good it is running, and it would be great if you'd confirm the feedback input behavior, checking the looping options (source clk, own clkout with different dividers, etc), and checking the resulting frequency.

I have a device that needs fpga part bugs fixed, the manufacturing company didn't fixed it for a year, and doesn't tell the time plan for that fix. Since there are no convenient interfaces, any test requires firmware rebuilding and re-flashing the core stm32 chip, and I'd like to avoid the excess experimental writes, to have the device alive for its actual function after I finish new fpga design prototype in some external MAX10/Spartan board :)

@vstrakh
Copy link
Author

vstrakh commented Mar 10, 2020

Probably there's no need in testing feedback input behavior. The overall dividers picture looks consistent with clkout0 being fed to clkfb, no matter if -use_ext_clkout0 option was specified or not.
There is FEEDBACK_CLOCK parameter, and its 2-bit size suggests it could've been used to select the actual clkout as a feedback, but then why expose feedback input pin at all?...

pablomarx pushed a commit that referenced this issue Mar 30, 2020
IO stuff is 100% wrong.

I believe logic, wires and pips might be okay.

Output from a nextpnr session:

+ nextpnr-generic --pre-pack simple.py --pre-place simple_timing.py --json blinky.json --post-route bitstream.py --write pnrblinky.json
Creating Basic Elements
Creating PIPs and Wires for BramTILE
... created 59502 PIPs
Creating PIPs and Wires for IOTILE
... created 12612 PIPs
Creating PIPs and Wires for LogicTILE
... created 325280 PIPs
Creating PIPs and Wires for RogicTILE
... created 16800 PIPs

Info: Packing constants..
Info: Packing IOs..
Info: Packing LUT-FFs..
Info: Packing non-LUT FFs..
Info: Checksum: 0xc92363f0

Info: Annotating ports with timing budgets for target frequency 12.00 MHz
Info: Checksum: 0xc92363f0

Info: Device utilisation:
Info:            GENERIC_IOB:     9/   84    10%
Info:          GENERIC_SLICE:    36/ 1280     2%
Info:           GENERIC_BRAM:     0/   15     0%
Info:          GENERIC_ROUTE:     0/    8     0%

Info: Placed 9 cells based on constraints.
Info: Creating initial analytic placement for 34 cells, random placement wirelen = 424.
Info:     at initial placer iter 0, wirelen = 45
Info:     at initial placer iter 1, wirelen = 44
Info:     at initial placer iter 2, wirelen = 26
Info:     at initial placer iter 3, wirelen = 45
Info: Running main analytical placer.
Info:     at iteration #1, type GENERIC_SLICE: wirelen solved = 46, spread = 59, legal = 111; time = 0.00s
Info:     at iteration #2, type GENERIC_SLICE: wirelen solved = 15, spread = 35, legal = 69; time = 0.00s
Info:     at iteration #3, type GENERIC_SLICE: wirelen solved = 21, spread = 26, legal = 60; time = 0.00s
Info:     at iteration #4, type GENERIC_SLICE: wirelen solved = 19, spread = 37, legal = 72; time = 0.00s
Info:     at iteration #5, type GENERIC_SLICE: wirelen solved = 22, spread = 52, legal = 62; time = 0.00s
Info:     at iteration #6, type GENERIC_SLICE: wirelen solved = 28, spread = 33, legal = 48; time = 0.00s
Info:     at iteration #7, type GENERIC_SLICE: wirelen solved = 25, spread = 31, legal = 71; time = 0.00s
Info:     at iteration #8, type GENERIC_SLICE: wirelen solved = 25, spread = 45, legal = 82; time = 0.00s
Info:     at iteration #9, type GENERIC_SLICE: wirelen solved = 45, spread = 42, legal = 79; time = 0.00s
Info:     at iteration #10, type GENERIC_SLICE: wirelen solved = 37, spread = 37, legal = 70; time = 0.00s
Info:     at iteration #11, type GENERIC_SLICE: wirelen solved = 47, spread = 45, legal = 74; time = 0.00s
Info: HeAP Placer Time: 0.02s
Info:   of which solving equations: 0.01s
Info:   of which spreading cells: 0.00s
Info:   of which strict legalisation: 0.00s

Info: Running simulated annealing placer for refinement.
Info:   at iteration #1: temp = 0.000000, timing cost = 0, wirelen = 48
Info:   at iteration #5: temp = 0.000000, timing cost = 0, wirelen = 38
Info:   at iteration #5: temp = 0.000000, timing cost = 0, wirelen = 38
Info: SA placement time 0.01s
Warning: No clocks found in design

Info: Checksum: 0xbbb1d3cb

Info: Routing..
Info: Setting up routing queue.
Info: Routing 141 arcs.
Info:            |   (re-)routed arcs  |   delta    | remaining|       time spent     |
Info:    IterCnt |  w/ripup   wo/ripup |  w/r  wo/r |      arcs| batch(sec) total(sec)|
Warning: Failed to find a route for arc 4 of net ctr[22].
ERROR: Routing design failed.
2 warnings, 1 error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants