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

nextpnr does not propagate clock constraints across input buffer #200

Closed
dlharmon opened this issue Sep 9, 2019 · 8 comments
Closed

nextpnr does not propagate clock constraints across input buffer #200

dlharmon opened this issue Sep 9, 2019 · 8 comments

Comments

@dlharmon
Copy link
Contributor

dlharmon commented Sep 9, 2019

I'm getting all clocks set to 12 MHz for timing purposes in nextpnr, both for iCE40 and ECP5. I could be missing something.

I looked into fixing it myself, but it's probably beyond me without some guidance.

top.lpf:

FREQUENCY PORT "host_0__hdc__p" 31250000.0 HZ;
FREQUENCY PORT "ssclk_0__io" 27000000.0 HZ;
Info: Max frequency for clock      '$glbnet$clk': 161.58 MHz (PASS at 12.00 MHz)
Info: Max frequency for clock '$glbnet$c250_clk': 658.33 MHz (PASS at 12.00 MHz)
Info: Max frequency for clock '$glbnet$c125_clk': 310.46 MHz (PASS at 12.00 MHz)

ssclk_0__io is $glbnet$clk and the other two are generated by a PLL from host_0__hdc__p.

if I pass this python script to nextpnr with --pre-pack, I get correct clock frequencies.

ctx.addClock("clk", 27.0)
ctx.addClock("c250_clk", 250.0)
ctx.addClock("c125_clk", 125.0)
Info: Max frequency for clock      '$glbnet$clk': 158.50 MHz (PASS at 27.00 MHz)
Info: Max frequency for clock '$glbnet$c250_clk': 658.76 MHz (PASS at 250.00 MHz)
Info: Max frequency for clock '$glbnet$c125_clk': 310.46 MHz (PASS at 125.00 MHz)

I'm not sure how reliable this naming will be, but it seems stable with both of my nextpnr designs.

I'd really like to be able to do platform.add_clock_constraint(ClockSignal("c125"), 125e6) or similar in the module where the generated clocks originate. It would be nice to eventually create a library module from the EHXPLLL and other ECP5 clock producing components that would handle all of this automatically like Vivado does.

Possibly related:
#88, #71

I did a pull and rebuild on nextpnr yesterday:

$ nextpnr-ecp5 --version
nextpnr-ecp5 -- Next Generation Place and Route (git sha1 c0f0256)

I can clean up and publicly share this design if that would be helpful. It's a mess right now as I just started converting from Verilog + Diamond.

@whitequark
Copy link
Contributor

whitequark commented Sep 10, 2019

I'd really like to be able to do platform.add_clock_constraint(ClockSignal("c125"), 125e6) or similar in the module where the generated clocks originate.

This is not currently possible to do with nextpnr reliably because nextpnr arbitrarily discards most signal names. I've added a workaround for specifically I/O pins, but it would not work properly for something like a PLL in general. This issue should be fixed upstream in nextpnr before I would be comfortable committing to an API that constrains arbitrary signals.

It should not even be necessary to define clock constraints for PLLs on ECP5, because nextpnr should be calculating the output frequency based on input frequency and PLL configuration. This functionality is not currently provided for iCE40, and once again, should be added upstream. It has been on my roadmap for a while, and although I am not the best person to add it to nextpnr, if you find its codebase too challenging to work with, let me know and I'll try to add an implementation.

FREQUENCY PORT "ssclk_0__io" 27000000.0 HZ;

This is the interesting part--since this is an IO pin, constraining it should work. Could you share your design? I'm fine with just the build directory, no need for the source. It doesn't matter at all if it's a mess, I just need to see the generated signal names for IOs and figure out what went wrong there.

@dlharmon
Copy link
Contributor Author

The ECP5 one in a single file:
https://gist.github.com/dlharmon/b5d80bcc156908f6e4fcb029fc2d7a8a

For the iCE40 case, examples/board/blinky.py will reproduce it.

I don't mind trying to add PLL output frequency calculation in nextpnr, but it may be a while before I get to it.

@whitequark
Copy link
Contributor

Interesting. So the constraints do work correctly on pins:

Info: constraining clock net 'host_0__hdc__p' to 31.25 MHz
Info: constraining clock net 'ssclk_0__io' to 27.00 MHz

... but for some reason this never propagates to the clock domain:

Info: Max frequency for clock      '$glbnet$clk': 145.39 MHz (PASS at 12.00 MHz)

... even though it's (almost) directly connected in netlist:

  wire width 1 \ssclk_0__i
  cell \IB \ssclk_0_0
    connect \I \ssclk_0__io
    connect \O \ssclk_0__i
  end
  process $group_0
    assign \clk 1'0
    assign \clk { \ssclk_0__i }
    sync init
  end

I feel like this is a nextpnr issue. Could you report it upstream?

@whitequark
Copy link
Contributor

Oh yeah, and I suspect the reason your other clocks aren't constrained properly is because nextpnr can't propagate frequencies across CLKDIVF, but I'm not sure about that.

@dlharmon
Copy link
Contributor Author

Interestingly, it does properly propagate clocks across CLKDIVF if I constrain the PLL output c250_clk manually. I'll report upstream, but it may be a day or two.

@dlharmon
Copy link
Contributor Author

YosysHQ/nextpnr#324

I narrowed it down to the clock constraint not being propagated across the input buffer.

@whitequark
Copy link
Contributor

@dlharmon You should be able to constrain interior signals after 8c30147, but only on Diamond.

@whitequark whitequark changed the title nextpnr clock constraints nextpnr does not propagate clock constraints across input buffer Sep 11, 2019
@dlharmon
Copy link
Contributor Author

This was fixed upstream in nextpnr. YosysHQ/nextpnr#324

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants