Open maikmerten opened 4 years ago
Related to #390?
edit: Probably not, that one is talking about timing between clock domains within the FPGA itself.
No there isn't anyway to constraints IO path at the moment. I'm not even sure if the timing data for this has been reversed at all.
Your best best at the moment is using IO registers (so the IO timing are not build dependent) and then use the official lattice tools to do the IO timing analysis once so you get the numbers "manually".
Thank you for your insightful answer!
@smunaut Out of curiosity, is NextPNR smart enough to understand a manually instantiated SB_IO block with the output register flag set doesn't need an intermediate register, and that the register inside the SB_IO should be part of the overall timing analysis? I suspect this is true, but since I'm chasing down a timing related issue that smells strongly of CLK to OUT delay changing with unrelated HDL changes, I need to verify.
Thanks!
The setup on the input is analysed, the clock to out isn't but it should not change based on the design. However, if you don't use a SB_GB_IO, then design changes might mean that the delay from clock input to global network might change due to different GB placement or routing which would change clock to out from an external point of view.
nextpnr does not insert registers in any case.
@madscientist159 If your design is public somewhere I can have a quick look to see if I can spot anything that would cause randomized IO timings.
@smunaut Sure, the timing fluctuation seems to be on the LPC buffers with outgoing signals (incoming seems fine):
As you can tell from the comments, this is an old design dating back to Arachne, but it's always exhibited a quirk where most of the time the outgoing signals will meet setup / hold on the bus, but ~5-10% of the time an unrelated HDL change is required to restore operation.
Since the parameters are #define-controlled, the #defines are here: https://gitlab.raptorengineering.com/raptor-engineering-public/lpc-spi-bridge-fpga/blob/master/main.v#L6
Well you're not using the IO register for the output side of the IO ....
@smunaut You're right! I looked at that several times over several days but each time missed the fact that bits [5:2] define the output type, not bits [3:0]. I need a better rubber duck. :smiley:
Also you might want to look at the verilog array instanciation syntax, things like :
https://github.com/smunaut/ice40-playground/blob/usb/cores/hub75/rtl/hub75_phy.v#L135
@smunaut Thanks for the pointer, will do. The HDL in question actually dates from ~2015 when the tools were fairly raw, and the less advanced features one tried to use the better. If I recall correctly, when this HDL was written there was hope the toolchain would pick up tristate buffer inference but so far as I know that has not happened yet?
No and it wouldn't implement IO registers if it did anyway. The IO registers have very specific constrain associated with them so they remain a manual thing to do since the designer better be aware of what he's doing.
@smunaut Fair enough, though I dimly recall the old Xilinx tools performing a step called "register packing" where they would try to use the IO buffer registers if doing so was legal within the constraints set by the HDL.
If you don't mind me asking, what would be the issue with inferring an I/O buffer register from (pseudo)HDL like this? I do have some knowledge of the SB internal architecture but I may very well be missing the specific bit of knowledge that stops this working.
(
input wire clock,
input wire data_in,
input wire tristate,
output reg buffered_signal
)
always @(posedge clock) begin
if (tristate) begin
buffered_signal <= 1'bz;
end else begin
buffered_signal <= data_in;
end
end
They do have a feature for that. And if it can't because you randomly changed something in your design resulting in that FF no longer being implementable in the IO buffer they just don't do it anymore and throw a warning buried among the other 600 warnings and suddenly your design doesn't work anymore because the IO timings have just changed drastically ...
That totally didn't happen to me 3 days ago ....
And if it can't because you randomly changed something in your design resulting in that FF no longer being implementable in the IO buffer they just don't do it anymore and throw a warning buried among the other 600 warnings and suddenly your design doesn't work anymore because the IO timings have just changed drastically ...
This is exactly why nMigen, if you request a registered IO buffer, always instantiates one explicitly instead of relying on inference.
Understood. Thanks for the insights all!
I'm currently moving a design over to an ECP5 from an iCE40 and might be starting to run into this problem again. On the ECP5, if I'm reading the I/O buffer design documents correctly, it's up to the routing software (e.g. NextPNR) to insert registers from general logic resources to create buffered I/O resources. I have a non-public design where as I push the resource use up it's fairly obvious the clock to out delays are starting to randomize, and I'm wondering what the correct way to counteract this would be in the NextPNR flow?
Thanks!
You can instantiate SB_IO
directly.
@whitequark On an ECP5? How does that work?
Oh sorry I misread. On ECP5 you are supposed to instantiate IFS1P3DX or OFS1P3DX, but nextpnr would not pack them into an IOB at the moment.
Huh ? AFAIK this is supposed to work.
Yosys will convert the IFS*
and OFS*
to TRELLIS_FF
with special attributes on them ( syn_useioff
/ ioff_dir
) and nextpnr will pack those into the IO.
Yes, IFS and OFS should be packed if they meet the constraints.
Oh oops, looks like my information is outdated.
What is the correct primitive to use for a tristateable I/O buffer with registered inputs and outputs? I'm still not 100% sure where you found the IFS1P3DX
info, so a pointer would be appreciated.
Thanks!
@smunaut Where would those attributes show up? The .json file?
Reason I ask is with a design modified to use IFS1P3DX / OFS1P3DX on ECP5 I don't think the FFs are being packed (timing is varying all over the place with predictably bad results) and a quick grep on the output files for syn_useioff
/ ioff_dir
isn't showing those keywords.
Yea in the .json
... if they are not there, check your yosys is not ancient.
@smunaut Yosys was built from GIT hash 8a4841d78690313a91af97e8c6d9aa3e65a3e491, so not exactly ancient. Now that I know what I'm looking for, let me dig around a bit and see what's going on.
@smunaut Found it! This feature doesn't work with -abc9
passed to synth_ecp5
.
Is that intentional?
Most definitely not ! And it used to work ... but just rechecked here and indeed seems broken.
There are some known issues with attributes and abc9, see YosysHQ/yosys#2176
I'll have a look and see what is really going on tomorrow.
Based on a minimal test it is working for me on Yosys master now. If you still have issues then please share a test-case.
Ok, I updated my yosys and it seems to indeed work with master. My previous yosys build was from mid-late june, so I guess it got fixed meanwhile.
Looks like updating to master fixed it on my side as well.
I wonder if nextpnr has a way to put constraints on I/O-timing. In Quartus, there's set_input_delay and set_output_delay (I found http://billauer.co.il/blog/2017/04/io-timing-constraints-meaning/ to be very helpful to get a quick overview).
I found https://github.com/YosysHQ/nextpnr/blob/master/docs/constraints.md - but the constraints mentioned there do not seem to deliver similar functionality. Are there other means to constrain I/O-timing?