rodinia
rodinia copied to clipboard
Include PLL example in Blinky
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.
@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.
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));
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
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));
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 :)
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!
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 :)
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?...