Intro
These are my notes to self for the next time I’ll have a PCB design to make. This is definitely not my expertise.
My original intention was to start this post with some kind of apologize, saying I only needed to make a simple board, so KiCad was good enough for this purpose. However it seems like KiCad is about to become the preferred tool many PCB designers quite soon, if it’s not there already. It’s surely handy and relatively easy to learn (at least for me, an experienced Electrical Engineer with no previous hands-on in board design). Does it match up with the expensive tools out there for a heavy and complicated design? I don’t know.
Everything in KiCad is text based in a simple manner. Important for version control, and using it to monitor my changes. Also very handy for fiddling with the files to get the things right on spot. In particular useful when creating footprints.
All said here relates to KiCad 5.1.4 under Linux Mint 19.
Getting started
- The KiCad version that went along with Mint 19 was heavily outdated. Compare what packages are available directly from KiCad.
- When upgrading from 4.x to 5.x, be sure to uninstall the previous version and purge it (apt purge) before installing the new one. Also, delete .config/kicad/ as it contains the paths to libraries for symbols and footprints.
- The ‘Footprint library path “…” does not exist’ error may be a result of not cleaning up an old installation as mentioned in the previous item.
- The official documentation, in particular the Getting Started with KiCad guide, is definitely the right place to start and refresh memory.
EESchema
- Before starting to work: Verify that the page size is correct and that the grid is 50 mils or so, no lower: View > Grid Settings… to ensure this.
- Basic components: In the “Device” library.
- Aiming the cursor on something accurately and right-clicking is usually the start for modifying virtually anything.
- Better still: Note the hotkey and use it while hovering over the relevant place.
- “Drag” keeps connections. “Move” doesn’t. Use “Drag”.
- If wires don’t snap to the ports, and components are placed regardless to the grid, it’s most likely that the grid is too dense.
- Useful hotkeys: Hover-Delete (well, delete), Hover-G (drag, think Blender) and Hover-C (duplicate).
- “Value”: Each component has a value assigned to it. The value appears on the assembly layer (F.Fab or B.Fab) of the PCB. In other words, the person doing the assembly of the board will see this value in the component’s position, and select what to put there accordingly. For resistors and capacitors, it’s obviously the value of the component. For other components, a useful hint on the nature of the device should be there.
- “Reference”: The symbol’s unique identifier in the schematics and netlist. U1, J15, C225 etc. By default, they’re C?, R? etc. until Annotate Schematic… is done.
- Net names: Designated with “Place Net Label” or by pressing “l”. Makes things easier during layout, and differential pairs must be with “+” and “-” suffixes (or _p/_n), or PCBNew won’t play ball later on.
- Footprints are assigned on each component’s Properties (and are not associated with symbols, unlike other tools), or more conveniently, with Tools > Assign Footprints. The association affects the schematic (.sch) file, appearing as a string property consisting of the library name and the footprint’s name, separated by a colon. Don’t associate to library footprints, but copies of them, defined explicitly on a local library. Or upgrading KiCad may change the design. See below on footprints.
- Plain holes are “virtual components”. Add a MountingHole symbol for each, and assign a matching footprint (hole only).
Symbol Editor
- Read the Symbol Guidelines in KiCad Library Convention document (KLC), after the daunting naming convention part (start at S3, maybe). It’s how to get it right.
- Check the grid. 50-100 mils, or the wires won’t snap to ports when the symbol is used (official guideline is 100 mils).
- Symbol Editor: When drawing a rectangle, click at the corner points, don’t hold the mouse button.
- It doesn’t hurt setting the “Description” property for each symbol — it appears on the library’s list as well as the output netlist.
- If a pin has multiple pads assigned to it, KiCad expects them to have track wires on the PCB connecting between them all.
Understanding footprints
Footprints are a set of graphical shapes in different layers that serve several purposes, all of which much be addressed when setting up a custom footprint:
- Putting the pads in place: Front copper layer (F. Cu, and also B. Cu with thru pads) and solder mask (F. Mask). Actually, the solder mask layer is the hole in the solder mask. Even though the shape of these is the same, the solder mask is widened slightly when Gerber files are created.
- Solder paste: When used, where the stencil holes should allow solder paste to be applied (F. Paste). As with solder mask, the shape is usually the same as the pads, but the datasheet may require a different pattern.
- Holes (drilling): These are a side effect of thru-hole pads, and appear in the footprint layers as is there was copper there.
- Silk Screen: Descriptive information on the board, in particular the component reference (F. SilkS)
- Assembly: Mark the place where the device actually is (F. Fab). The placement’s origin should also be the footprint’s (x,y) origin for automatic placement. The reference designator (“%R”) is written inside the component’s boundaries, and its “value” (what it is) typically underneath.
- Clearance: Ensure that nothing else is placed in the space that the device requires. This no-place space is called “courtyard” (F. CrtYd). The idea is simple: If, during layout (with PCBnew), the courtyards of two components overlap, it’s a DRC error at the very least, and possible also a refusal to generate Gerber files. So the courtyard should be the area that the component must occupy exclusively.
The layer assignment assumes that the component is placed on the front. When placing on the back side, the Layout Editor flips the layer assignment as necessary.
Holes is a bit tricky, because they are an implicit result of pads with holes. In particular, NPTH is Non-Plated Thru Holes, and appear in the footprints as pads of this type.
Footprints
There’s another post of mine, which discusses pads and footprint manipulation.
- Rule number one: Copy or imitate an existing library footprint rather than reinventing the wheel. Preferably imitate one that is likely to be heavily used.
- Read the Footprint Guidelines in KiCad Library Convention document (KLC). Skip the naming convention, and start at F4 (or so). This might be the best source on the planet for setting up a footprint. Odds are that these rules are tuned based upon real-life experience of a lot of people.
- Never ever use a footprint directly from the libraries to a component in the design. That makes the outcome dependent on the KiCad version running.
- Rather, create a project-dedicated footprint library (a directory with a .pretty suffix) in the Footprint editor, and put it in the Project’s library table. Then open the desired footprint in Footprint editor, and save it into the project’s library.
- Note that the 3D model still points at a KiCad library even after this, but that’s less important.
- Monitor the changes with git. It’s quite straightforward and allows a safe double-check.
- Don’t hesitate editing the footprint file manually, in particular for nailing exact positions. Exit the Footprint Editor and re-enter it, and then load the footprint. Using “Revert” for updating changes won’t work.
- To verify that a footprint is OK:
- At the very least view each layer separately, and make sure it contains what it should. Drill holes are covered by absence of material in the copper layers.
- Verify that SMT pads cover F.Cu, F.Mask and F.Paste (check each separately!). For thru pins, also on the back.
- Read through the text file (with _mod suffix) and look for unexpected stuff (one pad having different dimensions for no reason etc.)
- Pads may not have a pad number. This is useful for e.g. stencil pattern not matching the shape of the pad.
- If multiple pads have the same pin number assigned to them, track wires must be connected between them during the layout.
- Pads and other elements may very well not be on the footprint nor layout grid. I find myself calculating their X/Y position rather than placing them, so any position goes.
- For adding anything other than a pad, the drawing or text falls on the layer marked with a small arrow in the list of layers.
- Text substitutions: %R is replaced with the reference, %V with the value.
- Even though the name of the footprint is shown as the “value” in the Footprint Editor, it will be the component’s “value” field in Pcbnew. So it’s useful information during assembly of the board.
- Right-click on a pad, select “Array” to produce several identical pads with equal spacing. In extreme cases, write a simple script to manipulate the footprint file directly (exotic positions or pad naming).
- Use the measurement tool for assurance. It snaps to the grid.
- Any line thickness is implemented as a filled circle drawing along the line. This makes rounded corners.
- Pads can have arbitrary shapes. See this post.
PCBnew (layout)
- When starting a new project, remove the *.kicad_pcb file as well as .config/kicad directory, and start from scratch. KiCad’s defaults are usually good, so if a detail is overlooked, better have the default than some previous setting.
- File > Board Setup… and set the board’s thickness, trace parameters etc. It’s also a good idea to define the net classes (in particular high frequency nets).
- PCBnew depends on the current netlist as well as the footprint libraries. They are updated only on explicit request, so each time the schematics or footprints in use are updated, the changes must be synchronized by user request. As for the schematics, there an “Update PCB from Schematics” button. Or export the netlist from EESchema in default format and load it into PCBnew. It’s fine to do this iteratively (and even finer when covered by version control to cover up for mishaps).
- Grid: Pads may be off the grid, and there’s no problem selecting them as a start and end point for a route. The track itself will generally go on the grid, except for leaving it in order to reach a pad in a sane manner (usually with a 45-degree detour, not on a grid point). The grid pitch should hence be the approximately most used track width + the track clearance if a dense design is desired. Possibly make it in line with crucial footprints’ pitch, to keep straight traces, aligned with the grid.
- Ratsnest: Straight lines showing connections between pads. View all at once with View > Show Ratsnest (default on) or turn off, and view individual lines with “Display local ratsnets” icon on the toolbar to the right.
- The origin’s position has no significance, expect that it places the grid. However the absolute position values appear in the Gerber files, but this can be fixed by adding an auxiliary axis (more on this below).
- There are no 90 degree turns on tracks (except for power lines), only 45 degrees (and possibly smaller angles when aligning to the grid). Feels a bit awkward in the beginning but sharp turns are evil.
- There is no dragging of components (footprints), only moving them, which results in disconnection of all tracks going to it.
- While drawing tracks, press “v” for a via, press “/” to change the posture (the position of the 45 degree detour, if present).
- Always start and end a track by clicking at the center of a pad (the “anchor”), in particular if it’s off-grid.
- Ground / power planes: Create a fill zone, which is a polygon which is designated to a net. After setting up the zone, select it, right-click and pick Zones > Fill. This may not work unless there is already a track with the desired net going through the area. The track may remain, as it’s harmless. It’s probably the via, which connects the area to the net that does the trick. Once set up, a via is enough to connect to the plane.
- Repeat the zone fill after each change that may affect it.
- If the zone fill gets too close to a specific footprint’s pads, open the “Local Clearance and Settings” tab on the footprint’s Properties, and set a larger (actually, non-zero) clearance.
- In the end, tracks are a sequence of segments with a start and end position, width, layer and net designation in the *.kicad_pcb file (with “segment” keyword), vias are elements with the “via” keyword etc. Everything is absolutely positioned. Therefore moving a component (actually, its footprint) disconnects everything. All in all, PCBnew is just a smart drawing program for geometric shapes.
- Differential pairs: Route > Differential Pair. Then Route > Tune Differential Pair Skew / Phase, in order to check the skew and possibly tune it (or possibly move a component if that helps).
- Setting the parameters for track length and skew tuning: After selecting the track to tune, instead of moving the mouse to get those humps, right click and select Length Tuning Settings (or CTRL-L). The amplitude and length of these humps can be set, as well as the target length (instead of the default 100 mm).
- There’s a measurement tool (“Add dimension”) which is handy to verify certain distances, in particular the dimension of the board. The tool shown an indication when it’s on a line end, so one can be sure the accurate measurement is made. Best done on a separate drawing layer.
- Optionally, add an auxiliary axis origin to the layout, placing the (0,0) point of Gerber and drill files. This changes the aux_axis_origin parameter of the PCB design from (0 0) to whatever it was set to, and the coordinates in the Gerber files will have an offset relative to the layout files. Useful if the entire layout was drawn with some meaningless origin position. Then check “Use auxiliary axis as origin” when generating Gerbers and drill files.
3D viewer
I didn’t understand the point of a 3D view at first, but it’s surprisingly helpful, in particular during PCB layout — even though it’s also handy with the Footprint Editor. There’s something reassuring seeing the silk screen as white text on a green solder mask, and the drill holes as see-throughs. Click the mouse’s middle button to move the scenery.
Launch with View > 3D viewer (or Alt-3).
Generate Gerber files
You have reviewed the DRCs in EESchema and PCBnew, right…?
So to the final check before taping out. Export the files in PCBnew with File > Plot… and as follows (for a two-layer design):
(click image to enlarge)
and then generate a drill file (click “Generate Drill File”, of course).
(click image to enlarge)
All the settings above are KiCad’s defaults, by the way. Changes in these settings are stored in the *.kicad_pcb file for the next time these windows are opened (and not KiCad-globally).
Note that two drill files are (usually) generated: One for plated holes (vias and pads) and one for non-plated holes (typically mechanical holes for mounting).
A component positioning file can be generated with Fabrication Outputs > Footprint Position (.pos) file, however this file uses the internal footprints and their names. In particular, if the footprint’s origin isn’t where the automatic placement machine thinks it should be, the device may end up in the wrong place.
Viewing Gerber files
KiCad’s Gerber is fine, but it’s recommended to install gerbv as well (plain “apt install gerbv” on Mint 19). It’s part of gEDA, and it allows changing the order of the layers, but even more important, to export the current view to pdf. KiCad’s viewer prints one layer per page, and it’s hardly helpful. Use the export feature, don’t print — the latter generates a microscopic printout.
The main motivation for printing layers is to print the fabrication layer (preferably without values, KiCad has that option) on top of the edge cut and possibly a copper layer. For manual assembly, this gives a good indication of what goes where. To run it, just go
$ gerbv &
For KiCad’s viewer, load both the Gerber files and the drill files into Gerbview, and take a close look. The layers are displayed in the order they were loaded, so load the drill files first. As they are usually loaded with multiple selection of files, that’s probably alphabetical order, putting the bottom layer above the front.
Right-click on the layer list and select “Sort Layers if X2 mode” (should be “in X2 mode”, I guess) for layers ordered in physical order.
The active layer is always visible (drawn last).
Most important: Verify that the drill holes, plated and not, are in the correct places.
The DCodes are the aperture with which each line is drawn. An aperture is like a paintbrush, which is defined in each Gerber file for its own drawings. It’s usually a filled circle or rectangle with specific dimensions. The benefit of having these on the screen is to identify tracks with the same width and pads with the same dimensions, if they have the same DCode and are on the same layer. The same DCode on different layers (and hence Gerber files) has no meaning. For example, D10 and D11 are typically the DCodes of the first apertures defined in Gerber file, and are practically on every layer.
Create assembly sheet
If the design is going to be hand-assembled, better have a simple drawing that tells what goes where. To do this, plot the Gerber files as before, but uncheck “Plot footprint values” (but keep “Plot footprint references” checked, of course). Check F.Fab layer for plotting.
Recall that PCBnew remembers this in the *.kicad_pcb file, so be sure to revert it (with git) afterwards.
Next, open the files with gerbv (not KiCad’s Gerber viewer). Display the F_Fab layer, which should have the component references printed small inside boxes, along with the edge cuts and a copper layer. Change the colors for convenience.
Then File > Export > SVG… and generate a file. Import that file into a Libreoffice Writer document, and export that document as a pdf. Why not directly as pdf? Because the output pdf is broken, and even when I managed to open it, turning it into a pdf with a decent size turned out impossible.
A similar SVG export can be done from PCBNew: Pick File > Export > SVG… and select “Board area only” under “SVG Page Size”. For Pagination, pick “All layers in a single file”. However I haven’t figured out how to get rid of the values, and they clutter everything.
Manufacture
- Holes: Manufacturers typically make the hole slightly larger than required, as commented on this thread. The difference is typically no more than 0.1mm, so it’s not a big deal.
- PCB material: FR-4 is de-facto industry standard for rigid boards. 1 oz copper thickness is by far the most common. Pick thicker only for high currents. Board thickness: 0.6/0.8/1.0/1.2/1.6/2.0 mm. Tolerance is typically ±0.1 mm.
- Drill size: 0.2 – 6.3mm (but don’t go lower than 0.4 mm = 16 mils for basic PCB)
- Trace width: 6 mil seems to be a common minimal trace width, but Protel used to set 10 mil as the default (the latter seems to carry up to 1A, but check with a calculator). Unless there are current to carry, stick to these figures in general.
- Minimal trace space: 3 mil seems to be possible, but 10 mils should be chosen unless there’s a reason to push it. Minimal trace to board edge clearance should be 0.3 mm, but standard edge connector footprints tend to take 0.5mm for their pads. So better go for the latter.
- All in all, it seems like 10 mils for minimal trace width and space, and 0.4mm mils for vias are the sane choice. If the board gets tight, go smaller.
- If the board has an edge connector (“Gold Finger”), it’s ENIG (Electroless Nickel Immersion Gold) surface finish (sometimes referred to as just Immersion Gold). This is required only at the edge connector itself, because the gold’s role is to ensure good contact. According to the IPC-4552 standard, the default thickness of the gold layer is 0.05μm (sometimes referred to as 2U”). Sometimes ENIG is offered as the finish only for the edge connector, but this is relevant only for a large board. For a small board like mine, ENIG applies to the entire board.
- The assembly is the expensive part. Manufacturing should be at around $5-10 for 5 copies for a small board.
- HASL is not RoHS compliant, because of the use of lead. Lead-free HASL should be used instead (or any of the other, more expensive, options).
What to submit:
- Gerber files in RS-274x format for board outline, copper layers, silk screen(s), solder masks and solder paste. NC drill sometimes required in Gerber format instread of Excellon.
- NC Drill file, in Excellon format
- For assembly, this page summarizes it well. An assembly sheet as described above is a good idea.
Finding a manufacturer
My board involved small SMT components, so no chance to do the assembly myself. Actually, 10 simple components, on a plain FR4 53 x 22 mm board with two 1 oz layers and an edge connector (hence ENIG finish). The price for a turn-key project is at least $100. Don’t expect less.
And the minimal order quantity is 5. Everywhere.
The place to make a comparison is PCB shopper. I also suggest look at Manufacturing Reports for some painfully detailed reviews on PCB quality. If you need assembly (PCBA service, A for assembly), select service by assembly costs, as it’s going to be the dominant part.
So these are the estimated prices I got for a small board.
- Smart Prototyping, assembly at $80.
- Elecrow, assembly at about $106.
- PCBWay, assembly at $30 as a Turnkey project, $88 as kitted or partly kitted. Something tells me they’re going to charge a lot for the devices. They do send stuff with regular E-Packet = 16 days.
- ShenZhen2U, assembly at $50 (pretty much fixed price), allowing plain mail shipping. Headquarters in Hong Kong, but apparently the factory is in Shenzhen (China).
I have no affiliation with any of these companies, and this reflects the situation as of September 2019.
These costs didn’t change much when I changed the parameters of the assembly task. It’s sensible to assume it’s mostly the tooling cost (the cost for programming and setting up the automatic manufacturing equipment).
So I sent the files to PCBWay and ShenZhen2U. My personal impressions:
- PCBWay: Nice web interface, quick and professional response (an hour or so, during Chinese daytime). The price difference between the turnkey and the kitted was indeed a hint to their tendency to make up for the low assembly cost by adding fees everywhere: The components were 50-100% more expensive than Mouser (in low quantity prices). When I asked about it, I got some BS answer that it’s more expensive for them, taxes etc. PCB manufacturing at $39, which is pretty high. And they add $8 Paypal fee and $20 for shipping and handling with E-packet. And then there’s an “assembly promotion discount” of $30, ending up at $108 next to the “Confirm & Pay” button.
- ShenZhen2U: Slightly slower response (1 day each time), the website is slightly less useful. The flow was that I ordered the assembly first, then a few emails back and forth (I filled in their BOM form, where I also defined the PCB, and then got an accurate quote) and then the order at the website was updated manually to reflect their quote. They stood behind the $50 assembly cost. Their BOM costs are only slightly higher than Mouser, and they charge $10 for E-packet shipping. PCB manufacturing at $26, which is pretty low. All in all $110, when paid though Paypal (including a Paypal fee of $4.86, which they were clear about and is reasonable).
So there we have it: Almost exactly the same bottom line. One company reached it after fiddling with the prices, and the second just listed them upfront. This is why I went for ShenZhen2U, even though its review on Manufacturing Reviews complained a lot about dirt and bad silkscreen. The parallel review for PCBWay complained about traces being too thin, which is much more serious IMHO.
My experience with ShenZhen2U is overall good: Even though there was very little communication with them, they manufactured and shipped the boards fairly quickly (I selected very slow shipping and was explicit about the project not being urgent). The five boards arrived, one of which had a defective Micro-B USB 3.0 connector, which short-circuited two pins under a certain mechanical load. This issue showed only with a certain (wiggling) USB plug, so I can’t rule out that they actually tested this connector but didn’t spot the issue because they used a proper USB plug, and not what I have.
As a surprise bonus, they sent a bunch of unassembled boards along. Doesn’t hurt.
Other than the said connector, all boards were OK. As they were manually assembled, there were slight imperfections that are seen in a very detailed view, but the work was definitely good enough for functional purposes. So all in all, the work was good, the price very good, and there was a sense that they know what they’re doing — this is me appreciate that there were zero misunderstandings on those unspoken details. I’m probably going to stay with these guys, and not just because of the price.
I then followed up the same project, with a production of 110 pieces with the same company (ShenZhen2U). In June 2020, I got it done at $690, including everything and shipping with DHL — which is a reasonable price drop for the amount. They got it done quicker than promised, and the result was flawless. They did the panelizing in a sensible way (following my request on which part of the circuit must be smooth) and all cards except one passed a rather rigorous electronic QA test. The one that failed had the same problem with the connector, which might be my fault this time (I might have broken it while pushing the card into its place). Bottom line: They’re good at automatic assembly too.
Finding a manufacturer reloaded (2023)
Fast forward three years, and I needed to fill up the stock with another round of boards. I would have loved to go back to Shenzhen2u again, but they were not responsive, and probably out of business, even though their website was fully functional (but a running website means nothing, as we all know).
So the initial question is: Should I make a test round of 5 boards, and then go for the 110 boards, or jump to the second phase immediately? Back in 2019, the first 5 boards served the purpose of validating my own design, but this time there’s no need for that. So is a test run of 5 boards really worth its cost? I was in no hurry.
For a project with few components like mine, one can expect that the assembly of 5 boards will be done completely by hand, but for 110 boards a machine will be used. So these 5 boards don’t mean much in that respect.
Quality of PCB? It will probably be the same, if both manufacturing rounds are made at the same place. But I will not be surprised if there are several manufacturing facilities behind a PCB company, so each time I’d issue an order it may be handled by a different facility. So making a test with 5 units doesn’t necessarily mean anything about what will happen when I order 110 of them.
And then we have components. There are a lot of replacement components out there, and some of the companies offered these replacements upfront with a lower BOM cost. And they are indeed much cheaper. But what if they use these cheap replacements without telling me? If they do that with a USB plug, I can tell that by the marking on the component, but what about SMT capacitors and resistors? They can put whatever junk they have. How would I tell?
Fake components is a problem even with the most respectable dealers. I’ve actually had a client of mine receive an FPGA that was completely different and incompatible with the one ordered. Yet the marking on the chip was as the one requested. So it was a deliberate fake job, probably by the component dealer’s vendor. And that happened even before COVID-19 and the shortage of components that came with it.
So a 5 board test round probably gives me an idea of whether they put components that aren’t catastrophic and something about the PCB quality. Plus if there are some China-style unexpected surprises in store. Never underestimate the Chinese capability of doing something unexpected.
Whether this round is worth its cost depends, well, on this 5-board round’s price.
What I learned from 3D printing: The only thing I know for sure about is the price. Higher price doesn’t necessarily mean better quality. Returning to the same vendor doesn’t necessarily mean the same result. So go for the offer in terms of price, unless there are bad omens during the initial communication. The chance for failing is basically the same no matter who I choose, so the strategy is to reduce the stake.
There are plenty of reviews for several PCB related companies. Except for the obvious problem that reviews may not be authentic, there’s also a great difference between the needs and expectations of the person who writes the review. An unprofessional maker who builds a simple 2-layer board is not like a professional engineer who submits a super tight and super-complicated multi-layer board and expects the same quality as an expensive European-standard alternative. That said, I’ve also seen expensive manufacturers screwing up completely. The difference is that the latter speak better English.
Which brings me back to the same conclusion: There is really no bulletproof way to know who to work with. The only thing you know for sure is the price.
Getting started, 2023 version
Even today, PCB shopper was the best place to start. There are also reviews on this website, but I had to Google for them – there was no direct link from the homepage to these review pages (only along with price estimations for a specific board). Even though they are clearly affiliated with some of the manufacturers, it still offers some automatic quotes to start with. Then I used ChatGPT in order to get a few additional names. The question was “which manufacturers are often mentioned along with X?”.
Another starting point is to submit the manufacturing files to PCB Directory. They forward the requirements to some manufacturers, and the quotes from these arrive through email. I got two quotes this way (from HiTech Circuits and CanmTech). Needless to say, use a temporary email for this purpose (I get tons of PCB related spam only because of this page).
That said, I checked how much spam I received to email addresses that I used with PCB manufacturers. Surprisingly enough, absolutely none. Except for direct follow-up offers from the same companies, nothing. None of them disclosed my email to third parties. Maybe I shouldn’t be surprised: These are serious businesses, after all.
Speaking of which, of course I didn’t think about turning to all those companies that have been spamming me for years about their PCB factory. I actually checked all candidates, and none of them had ever sent me spam randomly (“your coupon will soon expire” mails is something I won’t consider spam for this purpose).
Elecrow and Seeed Studio did however send me a newsletter promoting their products after subscription, but with an efficient option to unsubscribe. PCB Directory also sent me a newsletter later on, and I unsubscribed.
As for Manufacturing Reports, it doesn’t appear to have been updated since 2023, so it’s not relevant anymore.
So: Picking a manufacturer, 2023 version
Don’t ask me how and why, I ended up with 7 quotes. I asked them for a full turnkey project (including component sourcing) for 5 boards and 110 boards. These are the prices per board as I got them, in USD, including the lowest shipping option that each company offered and all kinds of weird extra fees. In short, these are the price per unit as it would actually cost me.
The table is sorted according to the price for 110 pcs. Keep in mind that this is a simple small board with two layers and 10 components. YMMV.
Don’t get upset if the price jumps up and down throughout the process, and that the estimate of the online calculated might have been too optimistic. Neither how the price is broken down into PCB, PCBA manufacturing, shipping and handling, possibly a separate cost for the stencil and whatnot. The only thing that counts is the total price in the final quote. The rest is just noise that comes from the company’s marketing guys, and they’re out of the way as soon as the order is made, no matter which company you choose.
It’s also fine that their component prices are higher than I can get from Mouser and similar component dealers. They probably get much better prices, yes, but they also add a fee for the work, risk and the extra amount that one has to buy in order to cover up possible mishaps during assembly. Actually, if the price is better that you can get yourself, ask if they didn’t give you a cheap Chinese replacement part, by any chance.
In short: Look at the bottom line only. Never mind how they got to it.
I wrote earlier that the only thing I know for sure is the price, and Elecrow, won with a margin in both quantities. The communication with them was brief, efficient and to the point (unlike several other companies that was between 10-22 mails, just to get the quoting done).
More about Elecrow below…
There were two companies that deserve a comment:
- JLCPCB is maybe the most controversial manufacturer out there. Some love them, some say that they’re a disaster. They have a lot of reviews, for example in Trust Pilot and in Facebook. The reviews of all sorts appear legit, so no doubt there were unhappy people out there. On the other hand, maybe it’s a result of having a lot of customers? Not clear. Anyhow, seeing those reviews, I stayed away.
- PCBWay: Communication with them was really lame and somewhat worrying. I asked for 110 boards, and they said the can only manufacture 125 PCBs. Is that OK? Yes, of course, throw 15 boards to the trash. But then they asked if it’s OK to panelize the board, and if so, if they should depanel them. Even just mentioning the silly idea of not depaneling the boards is worrying. One can only hope that the silliness is limited to their sales, and that the engineering people know better. Regardless, obtaining a quote from these guys was relatively very slow. And tedious.
My experience with Elecrow
They initially suggested a low-cost replacement for the most expensive part, and they were very upfront about it. When I refused, they gave a very reasonable BOM cost (not too low, but neither high).
Placing an order for a turn-key projects was a bit tricky, because their web interface doesn’t suggest how to do that. But I got instructions for that by email, which boils down to this: The idea is to request an online quote for a PCB Assembly, and that allows uploading Gerber files, BOM and files related to assembly. The quote is then found under My Account > Service Orders, and once it has been made, it’s just a matter clicking “Check out” in order to put it in the cart, and then from there to submit an order. The issue of shipping is a bit messed up, because it’s included in the original quote, and then there are shipping options while checking out. So pick “free shipping” to prevent the price from increasing. All in all, their web interface for obtaining quotes and placing orders is not ideal, but once you get the principle it’s smooth.
I put an order for five pieces with Elecrow (92 USD). The Service Orders section in my web account got successively updated as the manufacturing went on, and they uploaded photos of an assembled PCB and even a small video. At some point, I got an email asking me to review the results and confirm shipment.
And this is where things got a little twist. I saw a small notch on the edge of the PCB, which was clearly going to be problematic. But since I only had the picture from one board, and this was a test round, I confirmed the shipment. In this situation, I preferred to see the situation as is, rather than having them fix the problem.
The shipping was quick and smooth, even though I selected a low-cost option: They rely on a postal company that avoids the Israeli postal company (which is problematic lately), so it was a matter of just 10 days. Which is very quick from China.
Once the boards arrived, I tested them electronically, and they were all 100% OK. There were no surprises. The correct parts were used, no unsolicited replacements. As for the cutting of the boards, they all had this same notch, as shown in this picture that I’ve taken:
It’s important to reiterate: I saw this problem in the picture that was shown to me before confirming the shipment, and I had the opportunity to complain about it. So even though one can question their QA for passing through something like this, odds are that this would have ended well, had it not been for me insisting to get the boards as is.
I wrote a mail to them, asking for the reason to this notch. The answer I got was that the notch is between the cutting machine’s starting point and ending point, as it makes the trajectory to cut out this small board. They emphasized that this is something that happens only for small-volume orders, and that someone simply forgot to remove the notch manually. As for the rather odd position of this notch, I suppose they manufacture several small boards on the same PCB. So the position was convenient in the context of this larger PCB, I guess.
So the question was whether to continue with them or not. I decided to go on with them for the 110 pieces, mainly because everything was perfect, except for this notch thing. And even if this mishap would have happened on 110 boards, it’s not a big deal to remove the notches with a nail file. Silly, but not a big deal.
The results? Excellent. All 110 boards passed the electronic test with no issues at all. And there was no issue with any notch. I couldn’t ask for more.
What to track with git
For a project named projname, this is the list of files I found sufficient to track:
.gitignore
fp-lib-table
projname.dcm
projname.kicad_pcb
projname.lib
projname.pretty/*.kicad_mod
projname.pro
projname.sch
sym-lib-table
as for .gitignore itself, this is my somewhat bloated file, which eventually did the job.
*-save.pro
*-cache.lib
*-rescue.lib
*-save.kicad_pcb
_autosave-*.*
*.kicad_pcb-bak
*.000
*.net
*.net~
*.bak
*.sch-bak
*.bck
*.gbr
*.drl
*.pos
*.wrl
*.csv
*.rpt
*.step
*.stp
*.svg
*.ps
*.pdf
*.dxf
*.plt
*.cad
fp-info-cache
*~
This ignores files produced by KiCad as well as backups. Plus a lot of garlic against files that were never seen.
Introduction
Even though this is definitely not my expertise, I made a simple adapter board carrying USB 3.0 signals.
The name of the game with such boards is to make a minimal impact on the signals, which means, among others, selecting the attributes of these two pairs of differential lines (SSRX and SSTX) in a way that minimizes the damage their very existence causes.
The other name of the game is to minimize the financial damage by ensuring that the board can be manufactured everywhere and by everyone, in particular those low-cost services.
There are a lot of things to be aware of, and I suggest reading application notes of devices that deal with the relevant type of signals. For example, TI’s board design guidelines for one of their SuperSpeed USB related devices, sllu149e.pdf.
This post focuses on selecting the track width (W) and spacing between the two differential pairs (S) of a coupled microstrip line. This is the widely recommended way to carry RF-frequency differential signals on a PCB, and it simply means that the two wires are routed at one of the exposed layers (top or bottom), and that there’s a ground plane layer immediately underneath it. See drawing at the bottom left of the image below.
Quite interestingly, there is little relation to the W and S of the differential pair in most application notes, so it’s not all that clear what considerations should be made. However, it’s well-known that W and S influence the differential impedance, and this is mentioned everywhere. The USB 3.0 specs requires the differential characteristic impedance to be 90Ω ± 7Ω in section 5.6.1.1.1. So there’s a start.
Assumptions on the PCB
These are the attributes of the most typical PCB one can find (and therefore hopefully low-cost to manufacture):
- Board material: 1 oz copper (0.035 mm thick) on FR4 resin
- Minimal track width: 10 mil. I’m generous here, as several low-cost manufacturers offer as low as 4 mil, but 6 mil is often the minimum for the lowest price. Often there’s a remark saying “>8 mil recommended”. So this indicates what’s considered easily manufactured.
- Minimal spacing between tracks: 10 mils, exactly for the same reasons. Manufacturers tend to give the same figures for both.
- Vias: I didn’t have any (on the differential pairs, that is).
The PCB calculator
There are plenty of online calculators and other utilities for calculating the impedance of microstrip pairs. Since I used KiCad 5.1.4 for the PCB design, I also went for its PCB calculator (image of screenshot below). It’s not the easiest one however.
(click image to enlarge)
Quite obviously, the board’s parameters are on the left column, and the track’s data to the right. So let’s start with the board’s parameters. Note that the “…” to the right allows selecting materials instead of feeding numbers, and guess what, they’re correct (at least those related to my board).
- Er: Select FR4, and the dialectric constant is set correctly to 4.6.
- TanD: Select FR4 here as well, and don’t bother that it’s not accurate (because of the frequency): It doesn’t influence the impedance, but the only the loss calculation.
- Rho: Select copper. It’s resistivity is correct.
- H: The height to the ground plane. In my case, it’s a dual-layer board, so the ground plane is the back side. Hence H is the thickness of the entire board, 1 mm.
- H_t: The height to the ground plane (?) above the board. Luckily, doesn’t have much influence on the impedance unless it’s really small.
- T: The strip thickness. 0.035 mm for 1 oz.
- Conductor roughness: Irrelevant for impedance calculation, but will influence conductor loss calculations
- Relative permeability of conductor: Set to 1 for copper. Copper’s relative permeability, according to Wikipedia, is 0.999994, and this has no influence on impedance calculations.
- Frequency: For a USB 3.0 link, I set it to 5 GHz. Its influence on the impedance is quite small, so no need to be worried about the idea that a digital signal isn’t really band limited and such.
OK, so now what?
The goal is to find W and S. To the right, there’s also L, the length of the trace. It has no influence on the impedance, so any positive number goes. Likewise, we don’t care about the electrical length (Ang_l) which basically says how much delay, in terms of sinusoidal phase of the given frequency, the conductor imposes.
So there are two input parameters, W and S, and two output parameters, Zeven and Zodd. As the signal is differential with no common mode component, we don’t care about Zeven at all: Since Zdiff = Zodd * 2, we just need to make Zodd = 45Ω, more or less.
Or in other words, there is one degree of freedom. There isn’t one pair of W and S for a given board and impedance, but we get to select one of them.
So the rather silly methodology is to pick some initial W and S, more or less at random, and click the down arrow (or “Analyze”). See what we got. Then set Zodd to 45, and click the up arrow (or “Synthesize”). And then some manual iteration, until the result is fine.
But that leaves us with the need to make a decision.
What is a good pair of W and S?
To make a long story short, as small as possible. These wires aren’t carrying any significant currents, so their size is only limited by the manufacturing process (or: How much we’re ready to pay for it). For low-cost manufacturing, consider that they sometimes make the trace thinner by a mil or two (this is the low-quality side of low-cost). So it’s important to be aware of how this would impact the impedance.
Why is small good? Mainly for crosstalk and noise immunity: The closer the wires are to each other, the more do they behave as a differential pair. Being closer to each other, noise signals are added more equally, leading to a smaller differential noise signal. A common rule of thumb is that a differential pair should have a clearance of 5W from any other conductor.
It’s also a matter of taking up less physical space on the board (in particular when respecting the 5W rule above).
As for signal losses, it doesn’t seem to make a big difference.
There is however no defined way to iterate with the calculator to obtain good values. One may select a minimal W and try out several S until Zodd is 45Ω, but it may be below the minimal S allowed.
In that case, start with the minimal S, and increase W until Zodd is 45Ω. If we want to follow the 5W rule, that is probably the best pair achievable.
As for my own choice, it’s the one shown in the image above: W = 0.8 mm, S = 0.2 mm. This makes S a bit smaller than 8 mils. Even though me original intention was not to go below 10 mils, this settings allows me to meet the 5W rule. And it should still be fine to manufacture virtually anywhere.
These rather bulky tracks weren’t easy to connect to the USB receptacle’s footprint, as discussed in another post.
Other calculators
Given the importance of getting these figures right, it’s reassuring to feed the results into other calculators before etching them in metal.
Note that some calculate Zodd and some give you the differential impedance (plus, possibly some other figures). Don’t get confused, and no panic.
Introduction
It just so happened that I went for a pair of 0.8mm thick wires, with 0.2mm between them, in order to achieve 90Ω differential impedance on a 1 mm thick FR4 board. No wonder PCBnew (KiCad’s layout program) refused connecting these wires to a USB SuperSpeed receptacle’s footprint, with its 0.4 mm side pads, spaced 0.65 mm apart: They simply can’t get squeezed in.
A similar problem occurred with the 0402-sized coupling capacitors in series with one of the differential pairs: Even though there was no problem connecting the differential wires to the capacitors (after reducing the clearance limit for the relevant tracks), the tracks ran over the capacitors’ pads.
This post suggests manipulating the footprints to match the specific width and spacing of a differential pair. Not the easiest way out, but the result is clean and elegant.
The quick and dirty solution is to draw the tracks until close to the footprint, and do the last segment with a thinner track width. Possible, works, but creates ugly discontinuities, and maybe even signal integrity issues due to reflections.
There is more than one way to do it, and I hope it won’t be too confusing as I jump around between the different options. Each has its advantages and disadvantages.
As a side benefit, this post goes into the technique of making arbitrarily shaped pads.
All said below relates to KiCad 5.1.4, which is up to date as of September 2019. On Linux Mint 19, not that it matters.
Footprints, pads, tracks
Before getting into business, let’s talk a bit about pads and how wire tracks are connected to them.
First of all, the footprint: It’s a collection of graphic elements, each assigned to one or more layers, that are plotted on the PCB layout as a group. The relative position between some elements are fixed, and others can be moved (text labels in particular).
A well-known special element is the pad. Aside from the fact that it’s a useful shortcut to draw a shape on several layers at a time, there are three things that are exclusive for pads:
- Only a pad can be assigned a pin number
- A pad is the final destination for a wire track (it has an “anchor”).
- Drill holes (plated or not) can only be defined with pads.
The first two relate to the capability to connect wires to the component’s pin: The pin number, with respect to the netlist, tells PCBnew which wire track to connect to the pad. The anchor tells where to, geometrically, the wire should be connected. Each wire track starts and end at an anchor point. For simple pads, it’s always at their center.
Remember that if you want to draw something on copper or some other layers, and don’t need any of the three exclusives listed above, just drawing filled polygons on the relevant layers might be a better idea.
And now to the wire track’s geometry.
The final product of the PCB layout is Gerber files. Without getting into the details, the way graphics is defined in these files is with straight lines or arcs (part of a circle, or the entire circle), which are given their thickness with an aperture. This aperture is a filled geometric shape, in most cases either a circle or a square with a per-aperture given size.
The circle aperture is apparently dominant in KiCad: When drawing a wire track on a copper layer, it’s effectively a line with a circular aperture. Think of painting the track’s with a marker having a circular shape, with the diameter of the track’s designated thickness.
Actually, it seems like any line thickness in KiCad is implemented with circular aperture. For example, when drawing filled polygons, there are rounded corners when the line thickness is non-zero, due to the circular aperture.
The conclusion of all this: If the pad is circular, with a diameter matching the wire track’s thickness, there will be a perfect overlap between the pad and the track’s end, no matter what direction the track came from. For a rectangular pad, this holds true only if the track comes straight in, and its edge length matches the thickness of the pad in the same direction.
Modifying footprints
We’ll start with the simpler, and less impressive example: The capacitors’ 0402 footprint. The original 0402 footprint looks like this, with 0.59 x 0.64 mm rounded rectangle pads:
The 0.8 mm thick tracks do connect to a pair of such capacitors, but only after reducing the minimal clearance to 0.15 mm (which is the wrong thing to do):
(click image to enlarge)
It’s quite evident that the tracks are all over the pads. This isn’t all that bad, because the solder mask is still correct (not visible on image above). And yet, the tracks get too close to each other, and they’re not supposed to extend the pads on the copper layer.
So this is what an extended 0402 looks like, with the beginning of a 0.8 mm track on each side:
Each pad actually consists of three elements: The original pad (without the pad number), a filled polygon and a circular pad, which has the pad number assigned to it.
Moving these elements apart a bit for clarity, it looks like this:
But the real need for this technique came from the USB 3.0 receptacle’s footprint, having pads too small for the 0.8 mm tracks:
(click image to enlarge)
To overcome this, extension were added, making pads 0.8 mm wide and 0.2 mm apart. The pad is square in this example, so the track can only arrive directly from above:
(click image to enlarge)
Pad 10 of the image above has been separated for the sake of demonstration.
This is what the result looks like in a PCB design using these:
(click image to enlarge)
Exaggerated perfectionism or the right thing for a 5 or 10 GHz signal, who knows.
How to do this
A pad with type Custom (having rectangular or circular anchor) can be merged with any number of geometrical shapes, turning it into a larger pad, with the shape of the union of all merged areas.
So:
- Draw a filled polygon (on the F.Silk for example) and then change its line thickness to 0.
- Create a pad with “Shape” set to “Custom (Rect. Anchor)”, which will be the actual pad that the wire will be connected to.
- Select both, right-click, and pick “Create Pad from Selected Shapes”.
The attributes (which layers etc.) are taken from the anchor pad, but the shape is the union of the pad and the polygon. As mentioned above, a circular anchor pad with the diameter of the track width is easiest to work with later (but more difficult to match the polygon for).
In fact, getting the polygons just right is a bit of a headache. I found myself editing the polygons’ coordinates manually in the footprint files to get exact positions. The “Move Exactly” feature is also helpful for placing items accurately.
Note that the extra pad (actually, the anchor pad) should be designated for the copper layer only: No solder mask nor paste layers. We define it as a pad so a track will connect to it, but it’s not going to be soldered on.
What about the courtyard? Should it be extended? Well, no: There’s no problem having other components placed over the extended area, which is part of the wiring. PCBnew ensures no other copper traces get near by virtue of clearance requirements.
Having said all this, note that the trickery with “Create Pad from Selected Shapes” isn’t really necessary. It just makes it simpler to manipulate the shapes as one unit. It also moves the filled polygon from its original layer to the copper layer, but that can be done on the polygon’s own attributes. This way or another, the track connects to the anchor pad (in the merged version) or a simple pad. It doesn’t really matter if the extra geometry is linked to the pad or not.
But now we have two pads
There is the original pad, which is left in place, partly for laziness: It’s already at the right size and place, covering the correct layers (including solder mask and paste), so why mess with it? And then there’s the new pad, which is part of the extension, only for the copper layer.
The question is whether the original pad should also have the pin number, or if it should be pinless. There are basically three options:
- Keep the pin number, so both pads have the same number. In this case, PCBnew requires both pads to be connected (wires explicitly with tracks) or the original pad is considered unconnected, and will generate a DRC error. Signing off a PCB layout with unconnected nets errors requires a certain amount of courage. And drawing the internal wire without adding dirt may be tricky.
- Remove pin number designation from original pad. But this will cause PCBnew to complain that the new and original pads are too close (in fact, they’re touching). They are considered two different pads, and generate a DRC error like the following:
ErrType(19): Pad too close to pad
@(201.775 mm, 57.300 mm): Pad of J1 on F.Cu and others
@(204.850 mm, 57.950 mm): Pad 9 of J1 on F.Cu
Well, in some cases this can be solved by skipping the “Create Pad from Selected Shapes” part, and have two (non-custom) pads, with the filled polygon on the copper layer between them, and hence also making enough space between the pads. It’s a question of the size of the polygon vs. the required pad clearance.
- Replace the original pad with plain graphics, drawing it as three distinct and overlapping polygons: One for the copper layer, one for the solder mask and one for the solder paste. Rounded corner are achieved with the polygon’s line thickness, if so desired. Haven’t tried this (it’s a bit tedious, after all), but it should work. Note that just merging the original pad’s geometry into the new pad will only cover the copper layer (as the new pad is defined not to cover the two other layers).
I went for the second option, because I allow myself to ignore DRCs on pad-to-pad clearances, but not unconnected net errors. If pad-to-pad clearances are violated because of components placed too close, courtyards are there to prevent them. So making a habit of ignoring pad-to-pad DRC errors is fairly OK.
Impact on signal integrity
I started with this pad manipulation thing because I thought I had no choice, but then I asked myself what this does to the signals. Short answer: I don’t really know, because I haven’t run an electromagnetic simulation on this.
But the word is that any sudden change and discontinuity causes reflections, so connecting to a pad with a gradually changing track width should be better. Maybe, one day, there will be a KiCad feature making all or selected connections between pads and tracks adapting this way.
In fact, think of a thin wire connected to a thicker pad. Wouldn’t it be better if it became gradually thicker as it approaches the pad, so there’s no discontinuity there?
Or maybe it won’t make enough difference to care about this at all. Once again, I don’t know. I guess it’s something the RF guys care more about, and much less us dealing with digital signals.
I should also mention that the way that the pads go sideways on the receptacle shown above, creates a certain difference in the track length, which isn’t accounted for. One can measure the difference manually and feed it into “Pad to die length” in the pad’s attributes, but that was a bit too much for me.
Once in a while, there’s a piece of junk on the desktop, and the question is who should be blamed for it.
The short answer is:
$ xwininfo
and fetch the window’s ID from the line at the beginning saying e.g.
xwininfo: Window id: 0x860000a "xclock"
And next, fetch the alleged process ID:
$ xprop -id 0x860000a | grep _NET_WM_PID
_NET_WM_PID(CARDINAL) = 58637
Note that it’s the duty of the program that generated the window to set this value correctly, so it may be absent or wrong. If the window belongs to a client on another machine, this process ID might be misleading, as it’s on the process table of the client (check out WM_CLIENT_MACHINE, also given by xprop).
If _NET_WM_PID isn’t helpful, try to look for other hints in xprop’s answer, or the correct process can be found with the rather complicated method described on this page.
These are a few notes when implementing an FPGA design for Stratix 10 with a Makefile flow (i.e. command-line utilities) with Quartus 19.2.
So I wanted was to implement a design including the PCIe 16x block for Stratix 10. I added a line going
set_global_assignment -name IP_FILE pcie_s10_16x.ip
in the relevant QSF file. And by the way: Don’t add a Verilog black box module on behalf of this IP in the the design. It will override the IP, and implement an empty module.
Anyhow, attempting to synthesize with quartus_syn failed, saying the RTL files haven’t been generated:
Error (16556): The synthesis RTL for pcie_s10_16x.ip has not been generated. Generate the synthesis RTL from within Platform Designer.
Which was a bit odd. I’m quite used to adding IP files like this, and well, good old quartus_map used to take care of this gracefully. But no.
OK, so I went for building the IP manually. Changed to the relevant directory, and
$ qsys-generate --synthesis pcie_s10_16x.ip
but that appeared to be stuck. Or more like in some kind of infinite loop. And taking ~ 11 GB of virtual memory with some Java process apparently running forever. But it wasn’t forever. Actually, on a rather strong machine, it eventually ended:
$ time qsys-generate --synthesis pcie_s10_16x.ip
[ ... ]
real 7m28.275s
user 10m8.443s
sys 0m34.967s
There’s a lot of output there in the middle, but the bottom line is 7 and a half minutes for generating the sources for a PCIe block. Quite amazing. The full transcript is given at the end of this post, for reference.
What apparently seems to take a lot of time is that some preparations are made for each of the PCIe lanes, and there is 16 of them.
Actually, use quartus_ipgenerate instead
This isn’t directly related, but it’s probably better to go something like
$ quartus_ipgenerate --run_default_mode_op projname -c projname
instead of qsys-generate (where projname is the name of the project, i.e. the prefix to the .qsf file). This generates all .qsys and .ip files mentioned in the QSF file, and skips generating them if the already exist. The –run_default_mode_op flag is a shortcut for “do the right thing” but isn’t documented, so it may not work on future versions of Quartus Pro. In that case, go something like:
$ quartus_ipgenerate --clear_ip_generation_dirs --generate_project_ip_files --synthesis=verilog projname
This is actually somewhat different, because it clears the directories, and hence always rebuilds the HDL files.
This way or another, quartus_ipgenerate runs qsys-generate to do the actual work. The former just comes handier in scripts, since it’s something one can (and should) put just before the call to quartus_syn. It doesn’t hurt if there are no IPs in the project, but it makes sure they are generated if they are.
And yet another unrelated fact: If an included QSYS file is referred to, all the sub-IPs must be listed in the QSF file explicitly as well (possibly as QSYS_FILE), or the quartus_syn will not find them.
The output
So this is what a full session looks like. I’ve cut out the parts that are just repetitions.
$ time qsys-generate --synthesis pcie_s10_16x.ip
2019.08.16.15:11:30 Warning: Quartus project not specified. Use --quartus-project and --rev to specify a Quartus project and revision.
2019.08.16.15:11:40 Info: Saving generation log to /home/user/try/pcie_s10_16x/pcie_s10_16x_generation.rpt
2019.08.16.15:11:40 Info: Generated by version: 19.2 build 57
2019.08.16.15:11:40 Info: Starting: Create HDL design files for synthesis
2019.08.16.15:11:40 Info: qsys-generate /home/user/try/pcie_s10_16x.ip --synthesis=VERILOG --output-directory=/home/user/try/pcie_s10_16x --family="Stratix 10" --part=1SG280HU2F50E2VG
2019.08.16.15:11:41 Warning: pcie_s10_hip_ast_0: Used altera_pcie_s10_hip_ast 20.0.0 (instead of 18.0)
2019.08.16.15:11:45 Info: pcie_s10_16x.pcie_s10_hip_ast_0: Gen2 (5.0 Gbps) x16 256-bit
2019.08.16.15:11:45 Warning: pcie_s10_16x.pcie_s10_hip_ast_0.rx_st: The empty signal width should be 1 bits.
2019.08.16.15:12:10 Info: pcie_s10_hip_ast_0.fpll_g1g2xn: For the selected device(1SG280HU2F50E2VG), PLL speed grade is 2.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: The TX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: The RX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: For the selected device(1SG280HU2F50E2VG), transceiver speed grade is 2 and core speed grade is 2.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: For current configuration, TX PCS FIFO depth is "16" and TX Core FIFO depth is "16".
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: For current configuration, RX PCS FIFO depth is "16" and RX Core FIFO depth is "32".
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: "PCS clkout" (pcs_clkout) is selected to drive tx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: "PCS clkout x2" (pcs_x2_clkout) is selected to drive tx_clkout2 port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: "PCS clkout" (pcs_clkout) is selected to drive rx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: A design example cannot be generated for "Tx PLL reference clock frequency"=="125.0" && "Selected CDR reference clock frequency"=="100.000"
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: Design example cannot be generated for the current configuration. Please check under Design Example tab and system message below for more detailed information.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch0: Note - The external TX PLL IP must be configured with an output clock frequency of 2500.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: The TX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: The RX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: For the selected device(1SG280HU2F50E2VG), transceiver speed grade is 2 and core speed grade is 2.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: For current configuration, TX PCS FIFO depth is "16" and TX Core FIFO depth is "16".
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: For current configuration, RX PCS FIFO depth is "16" and RX Core FIFO depth is "32".
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: "PCS clkout" (pcs_clkout) is selected to drive tx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: "PCS clkout x2" (pcs_x2_clkout) is selected to drive tx_clkout2 port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: "PCS clkout" (pcs_clkout) is selected to drive rx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: A design example cannot be generated for "Tx PLL reference clock frequency"=="125.0" && "Selected CDR reference clock frequency"=="100.000"
2019.08.16.15:12:11 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch1: Design example cannot be generated for the current configuration. Please check under Design Example tab and system message below for more detailed information.
[ The same over and over again... ]
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: The TX PCS-Core Interface FIFO is operating in half-rate transfer mode.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: The RX PCS-Core Interface FIFO is operating in half-rate transfer mode.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: For the selected device(1SG280HU2F50E2VG), transceiver speed grade is 2 and core speed grade is 2.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: For current configuration, TX PCS FIFO depth is "8" and TX Core FIFO depth is "8".
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: For current configuration, RX PCS FIFO depth is "8" and RX Core FIFO depth is "16".
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: "PCS clkout" (pcs_clkout) is selected to drive tx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: "PCS clkout x2" (pcs_x2_clkout) is selected to drive tx_clkout2 port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: "PCS clkout" (pcs_clkout) is selected to drive rx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: A design example cannot be generated for "Tx PLL reference clock frequency"=="125.0" && "Selected CDR reference clock frequency"=="100.000"
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: Design example cannot be generated for the current configuration. Please check under Design Example tab and system message below for more detailed information.
2019.08.16.15:12:24 Info: phy_g2x16.altera_xcvr_pcie_hip_channel_s10_ch15: Note - The external TX PLL IP must be configured with an output clock frequency of 2500.0 MHz.
2019.08.16.15:12:24 Info: pcie_s10_16x: "Transforming system: pcie_s10_16x"
2019.08.16.15:12:24 Info: pcie_s10_16x: "Naming system components in system: pcie_s10_16x"
2019.08.16.15:12:24 Info: pcie_s10_16x: "Processing generation queue"
2019.08.16.15:12:24 Info: pcie_s10_16x: "Generating: pcie_s10_16x"
2019.08.16.15:12:24 Info: pcie_s10_16x: "Generating: altera_pcie_s10_hip_ast"
2019.08.16.15:12:24 Info: phy_g2x16: "Generating: phy_g2x16"
2019.08.16.15:12:24 Info: fpll_g1g2xn: "Generating: fpll_g1g2xn"
2019.08.16.15:12:24 Info: pcie_s10_16x: "Generating: phy_g2x16"
2019.08.16.15:12:24 Info: pcie_s10_16x: "Generating: fpll_g1g2xn"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_wqso57y"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: "Generating: altera_xcvr_pcie_hip_channel_s10_ch0"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch1: "Generating: altera_xcvr_pcie_hip_channel_s10_ch1"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch2: "Generating: altera_xcvr_pcie_hip_channel_s10_ch2"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch3: "Generating: altera_xcvr_pcie_hip_channel_s10_ch3"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch4: "Generating: altera_xcvr_pcie_hip_channel_s10_ch4"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch5: "Generating: altera_xcvr_pcie_hip_channel_s10_ch5"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch6: "Generating: altera_xcvr_pcie_hip_channel_s10_ch6"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch7: "Generating: altera_xcvr_pcie_hip_channel_s10_ch7"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch8: "Generating: altera_xcvr_pcie_hip_channel_s10_ch8"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch9: "Generating: altera_xcvr_pcie_hip_channel_s10_ch9"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch10: "Generating: altera_xcvr_pcie_hip_channel_s10_ch10"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch11: "Generating: altera_xcvr_pcie_hip_channel_s10_ch11"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch12: "Generating: altera_xcvr_pcie_hip_channel_s10_ch12"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch13: "Generating: altera_xcvr_pcie_hip_channel_s10_ch13"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch14: "Generating: altera_xcvr_pcie_hip_channel_s10_ch14"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch15: "Generating: altera_xcvr_pcie_hip_channel_s10_ch15"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_fpll_s10_htile_1911_xs4xrjq"
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./altera_std_synchronizer_nocut.v VERILOG PATH ../../../../primitives/altera_std_synchronizer/altera_std_synchronizer_nocut.v
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./s10_avmm_h.sv SYSTEM_VERILOG PATH ../../../altera_xcvr_native_phy/altera_xcvr_native_s10/source/s10_avmm_h.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./altera_xcvr_native_s10_functions_h.sv SYSTEM_VERILOG PATH ../../../altera_xcvr_native_phy/altera_xcvr_native_s10/source/altera_xcvr_native_s10_functions_h.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./alt_xcvr_native_anlg_reset_seq.sv SYSTEM_VERILOG PATH ../../../altera_xcvr_native_phy/altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./alt_xcvr_pll_rcfg_arb.sv SYSTEM_VERILOG PATH ../../common/alt_xcvr_pll_rcfg_arb.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./alt_xcvr_pll_embedded_debug.sv SYSTEM_VERILOG PATH ../../common/alt_xcvr_pll_embedded_debug.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./alt_xcvr_pll_avmm_csr.sv SYSTEM_VERILOG PATH ../../common/alt_xcvr_pll_avmm_csr.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./alt_xcvr_resync.sv SYSTEM_VERILOG PATH ../../../../altera_xcvr_generic/ctrl/alt_xcvr_resync.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: add_fileset_file ./alt_xcvr_arbiter.sv SYSTEM_VERILOG PATH ../../../../altera_xcvr_generic/ctrl/alt_xcvr_arbiter.sv
2019.08.16.15:12:25 Info: fpll_g1g2xn: Building configuration data for reconfiguration profile 0
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_3e57toy"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_zj3agaa"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_prgcfha"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_jgm5cfa"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_ykdbt6y"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_lzoehjq"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_r73nlzi"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_3qbzhci"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_4b2ohhy"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_45l4xnq"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_ipejypi"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_jtr36ma"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_dfssemq"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_dtiglpy"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_lh3sg5q"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_pcie_hip_native_s10_191_zgzdh3a"
2019.08.16.15:12:25 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq"
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_arbiter.sv SYSTEM_VERILOG PATH ../../../../altera_xcvr_generic/ctrl/alt_xcvr_arbiter.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./altera_std_synchronizer_nocut.v VERILOG PATH ../../../../primitives/altera_std_synchronizer/altera_std_synchronizer_nocut.v
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_resync_std.sv SYSTEM_VERILOG PATH ../../../alt_xcvr_generic/alt_xcvr_resync_std.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_reset_counter_s10.sv SYSTEM_VERILOG PATH ../../../altera_xcvr_reset_control_s10/alt_xcvr_reset_counter_s10.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./altera_xcvr_native_s10_functions_h.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/altera_xcvr_native_s10_functions_h.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./s10_avmm_h.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/s10_avmm_h.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_avmm_csr.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_avmm_csr.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_prbs_accum.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_prbs_accum.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_odi_accel.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_odi_accel.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_rcfg_arb.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_rcfg_arb.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_early_spd_chng_s10_htile.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_early_spd_chng_s10_htile.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_anlg_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_dig_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_dig_reset_seq.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_reset_seq.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_anlg_reset_seq_wrapper.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq_wrapper.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_re_cal_chnl.v VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_re_cal_chnl.v
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_pcie_rx_eios_prot.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_pcie_rx_eios_prot.sv
2019.08.16.15:12:25 Info: altera_xcvr_pcie_hip_channel_s10_ch0: add_fileset_file ./alt_xcvr_native_rx_maib_wa.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_rx_maib_wa.sv
2019.08.16.15:12:26 Info: altera_xcvr_pcie_hip_channel_s10_ch0: Building configuration data for reconfiguration profile 0
ip-deploy --component-name=altera_xcvr_native_s10_htile --output-name=pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq --output-directory=/tmp/alt8124_4770953449535589358.dir/0005_altera_xcvr_pcie_hip_channel_s10_ch0_gen --component-param=rcfg_enable=1 --component-param=device=1SG280HU2F50E2VG --component-param=base_device=ND5U {--component-param=device_die_types=HSSI_CRETE2E MAIN_ND5} {--component-param=device_die_revisions=HSSI_CRETE2E_REVB MAIN_ND5_REVC} --component-param=protocol_mode=pipe_g2 --component-param=set_data_rate=5000 --component-param=bonded_mode=pma_pcs --component-param=pcs_reset_sequencing_mode=bonded --component-param=enable_manual_bonding_settings=1 --component-param=manual_pcs_bonding_mode=ctrl_slave_blw --component-param=manual_pcs_bonding_comp_cnt=2 --component-param=manual_tx_hssi_aib_bonding_mode=ctrl_master_bot --component-param=manual_tx_hssi_aib_bonding_comp_cnt=6 --component-param=manual_tx_core_aib_bonding_mode=ctrl_master_bot --component-param=manual_tx_core_aib_bonding_comp_cnt=6 --component-param=manual_tx_hssi_aib_indv=indv_dis --component-param=manual_tx_core_aib_indv=indv_dis --component-param=set_cdr_refclk_freq=100.000 --component-param=enable_hip=1 --component-param=enable_hard_reset=1 --component-param=set_hip_cal_en=1 --component-param=hip_mode=user_chnl --component-param=hip_prot_mode=gen2 --component-param=hip_channels=x16 {--component-param=std_tx_byte_ser_mode=Serialize x4} {--component-param=std_rx_byte_deser_mode=Deserialize x4} --component-param=std_tx_8b10b_enable=1 --component-param=std_tx_8b10b_disp_ctrl_enable=1 --component-param=std_rx_8b10b_enable=1 --component-param=std_rx_rmfifo_mode=pipe --component-param=std_rx_rmfifo_pattern_n=192892 --component-param=std_rx_rmfifo_pattern_p=855683 {--component-param=std_rx_word_aligner_mode=synchronous state machine} --component-param=std_rx_word_aligner_pattern_len=10 --component-param=std_rx_word_aligner_pattern=380 --component-param=std_rx_word_aligner_renumber=16 --component-param=std_rx_word_aligner_rgnumber=15 --component-param=enable_ports_pipe_sw=1 --component-param=enable_ports_pipe_rx_elecidle=1 --component-param=enable_ports_pipe_hclk=1 --component-param=tx_fifo_pfull=10 --component-param=rx_fifo_pfull=10 --component-param=enable_port_tx_clkout2=1 --component-param=tx_clkout2_sel=pcs_x2_clkout --component-param=qsf_assignments_enable=1 --component-param=rx_pma_term_sel=r_r4
***************************************************************
Quartus is a registered trademark of Intel Corporation in the
US and other countries. Portions of the Quartus Prime software
code, and other portions of the code included in this download
or on this DVD, are licensed to Intel Corporation and are the
copyrighted property of third parties. For license details,
refer to the End User License Agreement at
http://fpgasoftware.intel.com/eula.
***************************************************************
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: The TX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: The RX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: For the selected device(1SG280HU2F50E2VG), transceiver speed grade is 2 and core speed grade is 2.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: For current configuration, TX PCS FIFO depth is "16" and TX Core FIFO depth is "16".
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: For current configuration, RX PCS FIFO depth is "16" and RX Core FIFO depth is "32".
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: "PCS clkout" (pcs_clkout) is selected to drive tx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: "PCS clkout x2" (pcs_x2_clkout) is selected to drive tx_clkout2 port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: "PCS clkout" (pcs_clkout) is selected to drive rx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: A design example cannot be generated for "Tx PLL reference clock frequency"=="125.0" && "Selected CDR reference clock frequency"=="100.000"
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: Design example cannot be generated for the current configuration. Please check under Design Example tab and system message below for more detailed information.
2019.08.16.15:12:48 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq: Note - The external TX PLL IP must be configured with an output clock frequency of 2500.0 MHz.
2019.08.16.15:12:48 Info: Deploying pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq to /tmp/alt8124_4770953449535589358.dir/0005_altera_xcvr_pcie_hip_channel_s10_ch0_gen/pcie_s10_16x_altera_xcvr_native_s10_htile_1920_3nhmcmq.ip
2019.08.16.15:12:49 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y"
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_arbiter.sv SYSTEM_VERILOG PATH ../../../../altera_xcvr_generic/ctrl/alt_xcvr_arbiter.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./altera_std_synchronizer_nocut.v VERILOG PATH ../../../../primitives/altera_std_synchronizer/altera_std_synchronizer_nocut.v
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_resync_std.sv SYSTEM_VERILOG PATH ../../../alt_xcvr_generic/alt_xcvr_resync_std.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_reset_counter_s10.sv SYSTEM_VERILOG PATH ../../../altera_xcvr_reset_control_s10/alt_xcvr_reset_counter_s10.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./altera_xcvr_native_s10_functions_h.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/altera_xcvr_native_s10_functions_h.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./s10_avmm_h.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/s10_avmm_h.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_avmm_csr.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_avmm_csr.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_prbs_accum.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_prbs_accum.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_odi_accel.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_odi_accel.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_rcfg_arb.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_rcfg_arb.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_early_spd_chng_s10_htile.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_early_spd_chng_s10_htile.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_anlg_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_dig_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_dig_reset_seq.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_reset_seq.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_anlg_reset_seq_wrapper.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq_wrapper.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_re_cal_chnl.v VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_re_cal_chnl.v
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_pcie_rx_eios_prot.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_pcie_rx_eios_prot.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: add_fileset_file ./alt_xcvr_native_rx_maib_wa.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_rx_maib_wa.sv
2019.08.16.15:12:49 Info: altera_xcvr_pcie_hip_channel_s10_ch1: Building configuration data for reconfiguration profile 0
ip-deploy --component-name=altera_xcvr_native_s10_htile --output-name=pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y --output-directory=/tmp/alt8124_4770953449535589358.dir/0006_altera_xcvr_pcie_hip_channel_s10_ch1_gen --component-param=rcfg_enable=1 --component-param=device=1SG280HU2F50E2VG --component-param=base_device=ND5U {--component-param=device_die_types=HSSI_CRETE2E MAIN_ND5} {--component-param=device_die_revisions=HSSI_CRETE2E_REVB MAIN_ND5_REVC} --component-param=protocol_mode=pipe_g2 --component-param=set_data_rate=5000 --component-param=bonded_mode=pma_pcs --component-param=pcs_reset_sequencing_mode=bonded --component-param=enable_manual_bonding_settings=1 --component-param=manual_pcs_bonding_mode=ctrl_slave_blw --component-param=manual_pcs_bonding_comp_cnt=4 --component-param=manual_tx_hssi_aib_bonding_mode=ctrl_slave_abv --component-param=manual_tx_hssi_aib_bonding_comp_cnt=4 --component-param=manual_tx_core_aib_bonding_mode=ctrl_slave_abv --component-param=manual_tx_core_aib_bonding_comp_cnt=4 --component-param=manual_tx_hssi_aib_indv=indv_dis --component-param=manual_tx_core_aib_indv=indv_dis --component-param=set_cdr_refclk_freq=100.000 --component-param=enable_hip=1 --component-param=enable_hard_reset=1 --component-param=set_hip_cal_en=1 --component-param=hip_mode=user_chnl --component-param=hip_prot_mode=gen2 --component-param=hip_channels=x16 {--component-param=std_tx_byte_ser_mode=Serialize x4} {--component-param=std_rx_byte_deser_mode=Deserialize x4} --component-param=std_tx_8b10b_enable=1 --component-param=std_tx_8b10b_disp_ctrl_enable=1 --component-param=std_rx_8b10b_enable=1 --component-param=std_rx_rmfifo_mode=pipe --component-param=std_rx_rmfifo_pattern_n=192892 --component-param=std_rx_rmfifo_pattern_p=855683 {--component-param=std_rx_word_aligner_mode=synchronous state machine} --component-param=std_rx_word_aligner_pattern_len=10 --component-param=std_rx_word_aligner_pattern=380 --component-param=std_rx_word_aligner_renumber=16 --component-param=std_rx_word_aligner_rgnumber=15 --component-param=enable_ports_pipe_sw=1 --component-param=enable_ports_pipe_rx_elecidle=1 --component-param=enable_ports_pipe_hclk=1 --component-param=tx_fifo_pfull=10 --component-param=rx_fifo_pfull=10 --component-param=enable_port_tx_clkout2=1 --component-param=tx_clkout2_sel=pcs_x2_clkout --component-param=qsf_assignments_enable=1 --component-param=rx_pma_term_sel=r_r4
***************************************************************
Quartus is a registered trademark of Intel Corporation in the
US and other countries. Portions of the Quartus Prime software
code, and other portions of the code included in this download
or on this DVD, are licensed to Intel Corporation and are the
copyrighted property of third parties. For license details,
refer to the End User License Agreement at
http://fpgasoftware.intel.com/eula.
***************************************************************
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: The TX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: The RX PCS-Core Interface FIFO is operating in full-rate transfer mode.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: For the selected device(1SG280HU2F50E2VG), transceiver speed grade is 2 and core speed grade is 2.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: For current configuration, TX PCS FIFO depth is "16" and TX Core FIFO depth is "16".
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: For current configuration, RX PCS FIFO depth is "16" and RX Core FIFO depth is "32".
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: "PCS clkout" (pcs_clkout) is selected to drive tx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: "PCS clkout x2" (pcs_x2_clkout) is selected to drive tx_clkout2 port and the clock frequency is 0.0 MHz.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: "PCS clkout" (pcs_clkout) is selected to drive rx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: A design example cannot be generated for "Tx PLL reference clock frequency"=="125.0" && "Selected CDR reference clock frequency"=="100.000"
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: Design example cannot be generated for the current configuration. Please check under Design Example tab and system message below for more detailed information.
2019.08.16.15:13:12 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y: Note - The external TX PLL IP must be configured with an output clock frequency of 2500.0 MHz.
2019.08.16.15:13:12 Info: Deploying pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y to /tmp/alt8124_4770953449535589358.dir/0006_altera_xcvr_pcie_hip_channel_s10_ch1_gen/pcie_s10_16x_altera_xcvr_native_s10_htile_1920_prfyb7y.ip
2019.08.16.15:13:13 Info: pcie_s10_16x: "Generating: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_cqbemta"
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_arbiter.sv SYSTEM_VERILOG PATH ../../../../altera_xcvr_generic/ctrl/alt_xcvr_arbiter.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./altera_std_synchronizer_nocut.v VERILOG PATH ../../../../primitives/altera_std_synchronizer/altera_std_synchronizer_nocut.v
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_resync_std.sv SYSTEM_VERILOG PATH ../../../alt_xcvr_generic/alt_xcvr_resync_std.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_reset_counter_s10.sv SYSTEM_VERILOG PATH ../../../altera_xcvr_reset_control_s10/alt_xcvr_reset_counter_s10.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./altera_xcvr_native_s10_functions_h.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/altera_xcvr_native_s10_functions_h.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./s10_avmm_h.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/s10_avmm_h.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_avmm_csr.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_avmm_csr.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_prbs_accum.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_prbs_accum.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_odi_accel.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_odi_accel.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_rcfg_arb.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_rcfg_arb.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_early_spd_chng_s10_htile.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_early_spd_chng_s10_htile.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_anlg_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_dig_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_dig_reset_seq.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_reset_seq.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_reset_seq.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_anlg_reset_seq_wrapper.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_anlg_reset_seq_wrapper.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_re_cal_chnl.v VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_re_cal_chnl.v
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_pcie_rx_eios_prot.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_pcie_rx_eios_prot.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: add_fileset_file ./alt_xcvr_native_rx_maib_wa.sv SYSTEM_VERILOG PATH ../../altera_xcvr_native_s10/source/alt_xcvr_native_rx_maib_wa.sv
2019.08.16.15:13:13 Info: altera_xcvr_pcie_hip_channel_s10_ch2: Building configuration data for reconfiguration profile 0
ip-deploy --component-name=altera_xcvr_native_s10_htile --output-name=pcie_s10_16x_altera_xcvr_native_s10_htile_1920_cqbemta --output-directory=/tmp/alt8124_4770953449535589358.dir/0007_altera_xcvr_pcie_hip_channel_s10_ch2_gen --component-param=rcfg_enable=1 --component-param=device=1SG280HU2F50E2VG --component-param=base_device=ND5U {--component-param=device_die_types=HSSI_CRETE2E MAIN_ND5} {--component-param=device_die_revisions=HSSI_CRETE2E_REVB MAIN_ND5_REVC} --component-param=protocol_mode=pipe_g2 --component-param=set_data_rate=5000 --component-param=bonded_mode=pma_pcs --component-param=pcs_reset_sequencing_mode=bonded --component-param=enable_manual_bonding_settings=1 --component-param=manual_pcs_bonding_mode=ctrl_slave_blw --component-param=manual_pcs_bonding_comp_cnt=6 --component-param=manual_tx_hssi_aib_bonding_mode=ctrl_slave_abv --component-param=manual_tx_hssi_aib_bonding_comp_cnt=2 --component-param=manual_tx_core_aib_bonding_mode=ctrl_slave_abv --component-param=manual_tx_core_aib_bonding_comp_cnt=2 --component-param=manual_tx_hssi_aib_indv=indv_dis --component-param=manual_tx_core_aib_indv=indv_dis --component-param=set_cdr_refclk_freq=100.000 --component-param=enable_hip=1 --component-param=enable_hard_reset=1 --component-param=set_hip_cal_en=1 --component-param=hip_mode=user_chnl --component-param=hip_prot_mode=gen2 --component-param=hip_channels=x16 {--component-param=std_tx_byte_ser_mode=Serialize x4} {--component-param=std_rx_byte_deser_mode=Deserialize x4} --component-param=std_tx_8b10b_enable=1 --component-param=std_tx_8b10b_disp_ctrl_enable=1 --component-param=std_rx_8b10b_enable=1 --component-param=std_rx_rmfifo_mode=pipe --component-param=std_rx_rmfifo_pattern_n=192892 --component-param=std_rx_rmfifo_pattern_p=855683 {--component-param=std_rx_word_aligner_mode=synchronous state machine} --component-param=std_rx_word_aligner_pattern_len=10 --component-param=std_rx_word_aligner_pattern=380 --component-param=std_rx_word_aligner_renumber=16 --component-param=std_rx_word_aligner_rgnumber=15 --component-param=enable_ports_pipe_sw=1 --component-param=enable_ports_pipe_rx_elecidle=1 --component-param=enable_ports_pipe_hclk=1 --component-param=tx_fifo_pfull=10 --component-param=rx_fifo_pfull=10 --component-param=enable_port_tx_clkout2=1 --component-param=tx_clkout2_sel=pcs_x2_clkout --component-param=qsf_assignments_enable=1 --component-param=rx_pma_term_sel=r_r4
[ The same over and over again... ]
***************************************************************
Quartus is a registered trademark of Intel Corporation in the
US and other countries. Portions of the Quartus Prime software
code, and other portions of the code included in this download
or on this DVD, are licensed to Intel Corporation and are the
copyrighted property of third parties. For license details,
refer to the End User License Agreement at
http://fpgasoftware.intel.com/eula.
***************************************************************
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: The TX PCS-Core Interface FIFO is operating in half-rate transfer mode.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: The RX PCS-Core Interface FIFO is operating in half-rate transfer mode.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: For the selected device(1SG280HU2F50E2VG), transceiver speed grade is 2 and core speed grade is 2.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: For current configuration, TX PCS FIFO depth is "8" and TX Core FIFO depth is "8".
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: For current configuration, RX PCS FIFO depth is "8" and RX Core FIFO depth is "16".
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: "PCS clkout" (pcs_clkout) is selected to drive tx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: "PCS clkout x2" (pcs_x2_clkout) is selected to drive tx_clkout2 port and the clock frequency is 0.0 MHz.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: "PCS clkout" (pcs_clkout) is selected to drive rx_clkout port and the clock frequency is 0.0 MHz.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: A design example cannot be generated for "Tx PLL reference clock frequency"=="125.0" && "Selected CDR reference clock frequency"=="100.000"
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: Design example cannot be generated for the current configuration. Please check under Design Example tab and system message below for more detailed information.
2019.08.16.15:18:55 Info: pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i: Note - The external TX PLL IP must be configured with an output clock frequency of 2500.0 MHz.
2019.08.16.15:18:55 Info: Deploying pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i to /tmp/alt8124_4770953449535589358.dir/0020_altera_xcvr_pcie_hip_channel_s10_ch15_gen/pcie_s10_16x_altera_xcvr_native_s10_htile_1920_esxl67i.ip
2019.08.16.15:18:56 Info: pcie_s10_16x: Done "pcie_s10_16x" with 38 modules, 428 files
2019.08.16.15:18:57 Info: qsys-generate succeeded.
2019.08.16.15:18:57 Info: Finished: Create HDL design files for synthesis
***************************************************************
Quartus is a registered trademark of Intel Corporation in the
US and other countries. Portions of the Quartus Prime software
code, and other portions of the code included in this download
or on this DVD, are licensed to Intel Corporation and are the
copyrighted property of third parties. For license details,
refer to the End User License Agreement at
http://fpgasoftware.intel.com/eula.
***************************************************************
real 7m28.275s
user 10m8.443s
sys 0m34.967s
Introduction
The PCIe blocks on Intel (formerly Altera) FPGAs have a somewhat peculiar, yet useful interface for exposing some of the interface’s configuration information, called “Transaction Layer Configuration”. For the purposes of this post, it consists of two output signals, tl_cfg_add[3:0] and tl_cfg_ctl[31:0]. Both are driven by the PCIe block, and clocked by the same clock. The documentation seems to be a bit confused on whether this clock is pld_clk or coreclkout_hip however (even in different versions of the same user guide).
Recall that coreclkout_hip is driven by the PCIe block, and pld_clk is an input to it. The straightforward choice is to connect the pld_clk input to coreclkout_hip, so the PCIe block, as well as the application logic, are both driven by the clock the PCIe block generates. It’s actually not clear to me why anyone would go for a different solution, but the user guide keeps this option open.
So I’ll assume pld_clk and coreclkout_hip are the same signal here. Hence the said confusion in the documentation makes no difference. However it may be hint to why Intel changed the guidelines to interacting with the tl_cfg_add / tl_cfg_ctl pair, probably around the release of Quartus 16.0.
The interface in brief
It’s more or less like a cyclic slide show: tl_cfg_add is incremented every 4th or 8th clock (i.e. pld_clk = coreclkout_hip), and tl_cfg_ctl contains a value that corresponds to the position in some register array, at the address shown in tl_cfg_add. Both change on the same rising edge of the same clock.
This register array appears in the relevant FPGA family’s user guide, has no relation to anything standard, and varies from one FPGA family to another. The data is packed into this 16-word register array in a creative manner at times. The information that can be obtained on an endpoint PCIe interface is in particular the bus address, Max_Payload_Size, Max_Read_Request_Size and if the RCB is 128 bytes. On post-Cyclone IV devices, the data for producing an MSI interrupt can be obtained from this interface as well.
The old API
In older revisions of the user guides (and even the current revision for Cyclone IV), the guideline is to treat tl_cfg_add and tl_cfg_ctl as synchronous signals, so it made perfect sense to go (on Cyclone 10 and several others)
always @(posedge pld_clk)
case (tl_cfg_add)
0: cfg_dcommand <= tl_cfg_ctl[31:16];
2: cfg_lcommand <= tl_cfg_ctl[31:16];
endcase
The fact that tl_cfg_add dwells a few clocks on each address makes no difference, as tl_cfg_ctl contains the same, correct, value on all of these clock cycles.
The update
In more recent user guides issued by Intel, in particular for Series V and Series 10 FPGAs, the guidelines have changed. Apparently, the timing constraints were not properly applied before Quartus 16.0.1, and one can’t treat tl_cfg_add and tl_cfg_ctl as synchronous signals anymore. Rather, the guidelines require that application logic detects the change in tl_cfg_add’s least significant bit, and then sample both signals with a safe time margin. Without saying it explicitly, the user guides treat these two as signals from an unrelated clock domain.
The fact that both signals remain constant for a fixed number of clock cycles makes it possible to write simple logic that ensures proper sampling.
From a practical point of view, I can testify that the old API works well regardless of the new, stricter, guidelines. It’s not clear whether the sampling mechanism is actually required for proper operation, or if it’s a leftover in the guidelines for Quartus revisions that didn’t enforce the timing constraints properly on the said signals. This way or another, if the user guide requires something, do it. Nevertheless, odds are that FPGA designs already out there, based upon the old API, are still fine.
The new guideline
In short, updated user guides require that the tl_cfg_add and tl_cfg_ctl are sampled in the middle of their time window with stable values. The beginning of each such time window is detected by the application logic by a change in the least significant bit of tl_cfg_add.
There are however a few things to note:
- The user guides state that the said time window is either 4 clocks or 8 clocks, “depending on the parameterization”, but don’t say how to tell which one applies for a given design.
- As tl_cfg_add is considered an asynchronous signal, detecting changes on its least significant bit must be done on a register that samples it on each clock, and not comparing directly with tl_cfg_add[0].
- It’s not possible to sample in the middle of a time window consisting of an even number of clock cycles. In the user guide’s example, the sampling is timed at the clock cycle after the middle of the time window.
The user guide shows sample Verilog code for a clock window of 8 clocks, but doesn’t relate to the 4 clock case.
Verilog code
The following Verilog code can be used to implement the generation of the sampling strobe:
reg [3:0] tl_cfg_add0_d;
reg strobe;
reg [3:0] counter, prev_counter;
always @(posedge pld_clk)
begin
tl_cfg_add0_d <= { tl_cfg_add0_d, tl_cfg_add[0] };
if (prev_counter > 5)
strobe <= (tl_cfg_add0_d[2] != tl_cfg_add0_d[3]);
else
strobe <= (tl_cfg_add0_d[0] != tl_cfg_add0_d[1]);
if (tl_cfg_add0_d[0] == tl_cfg_add0_d[1])
counter <= counter + 1;
else
begin
prev_counter <= counter;
counter <= 0;
end
end
and then this strobe can be used to sample the two signals:
always @(posedge pld_clk)
if (strobe)
begin
tl_cfg_add_samp <= tl_cfg_add;
tl_cfg_ctl_samp <= tl_cfg_ctl;
end
The idea is to detect whether the time window is 4 or 8 clock cycles by counting them, and storing the value just before resetting the counter back to zero in prev_counter. For a 4 clock window, it’s expected to be 4, but may also turn out 3 or 5 due to momentary timing glitches. Likewise, prev_counter may turn out either 7, 8 or 9 when an 8 clock window is in effect.
prev_counter is used to select when to assert strobe: If it’s larger than 5, a timing suitable for an 8-clock window is selected. If not, the timing for a 4 clock window. Even though prev_counter may fluctuate from one window to another, it’s not expected to change in a way that alters the selection. Therefore, the fact that prev_counter was measured on one time window, and is used to time the sampling of a another, has no significance. It might as well have been measured on one time window and applied forever afterwards, but that would have required logic that determines when it’s valid.
The sampling instance for a 4-clock time window is two clocks after the change in tl_cfg_add[0], which is consistent with the guideline to sample at the middle of the window (actually, on the closest clock cycle after the middle). For an 8-clock cycle, the delay is 4 clocks, exactly as demonstrated in the examples in the user guides.
Finally, the sampled data can be consumed, e.g.
always @(posedge pld_clk)
begin
strobe_d <= strobe;
if (strobe_d)
case (tl_cfg_add_samp)
0: cfg_dcommand <= tl_cfg_ctl_samp[31:16];
2: cfg_lcommand <= tl_cfg_ctl_samp[31:16];
endcase
end
Note that strobe_d is used rather than strobe for consuming that sampled values (even though it would work likewise with strobe, just with a slight delay of the update).
The goal
Quite simple: Set a fixed graphics mode on the computer screen.
More precisely, make Cinnamon (version 3.2.6) on Linux Mint 18.1 (Serena) show the desktop with a predefined resolution, no matter what happens. Spoiler: I failed. But I got close enough for practical purposes, and collected a lot of knowledge while trying. So here it is.
The reason I need this: On the machine mentioned here, I have an two screens connected through an HDMI splitter, so the monitor identification is somewhat shaky, and it’s not clear which piece of info the computer gets each time. To make it even trickier, the graphics mode I need is only listed in the EDID information submitted by one of the monitors. In other words: More often than not, the computer doesn’t know it’s allowed to use the mode I want it to use.
This situation meets the somewhat arrogant “I know what’s best, I never fail” attitude often seen by graphics software. There is more than one automatic mechanism for changing the resolution to “what is correct”, so just changing the resolution with xrandr doesn’t cut. The underlying mechanisms seem to change frequently from one version to another, and having them documented is probably too much to ask for. It seems like there are some race conditions taking place between different utilities that have a say on this matter. Possibly the reason for the problem I tried to solve on this post.
For clarity: EDID is a chunk of data that is typically stored on a small flash memory on the monitor. This data is fetched through I2C wires that are part of an DVI / HDMI / VGA connector when the monitor is plugged in. This is how the computer knows not only the commercial name of the monitor, but also what graphics modes it supports and prefers.
I have another post which solves this in a more aggressive way, and also one with a related discussion regarding an newer OLED display.
How cinnamon selects the resolution to use
So — the first question is: How does (my very specific) Cinnamon determine which screen resolution is the “correct” one?
This is a journey into the realm of mystery and uncertainty, but it seems like the rationale is to remember previously connected monitors, along with a separate user-selected graphics mode for each.
So the steps are probably something like:
- Grab the list of allowed resolution modes, as presented by xrandr, for the relevant monitor (through libxrandr?). This is typically the set of modes listed in the monitor’s EDID information, but it’s possible to add modes as well (see below).
- If there’s a user logged in, look up .config/monitors.xml in that user’s home directory. If there’s a match between the monitor’s product identification, apply the selected resolution. This file is changed by Cinnamon’s Display setting utility (among others, I guess), and presents the user’s preferences.
- There’s possibly also a globally default monitor.xml at /etc/gnome-settings-daemon/xrandr/. I don’t have such file, and it’s not clear if it’s in effect had it existed. I haven’t tried this one.
- If there’s no matching (or adequate?) mode setting in monitor.xml (or no user logged in), choose the preferred mode, as pointed at by xrandr.
This way or another, monitors.xml only lists width, height and rate for each graphics mode, without the timing details that are required to run it properly. So if the resolution requested in monitors.xml isn’t listed by xrandr, there is no way to request it, as there is crucial information missing. This isn’t supposed to happen ever, since the utility that sets the user’s preferences isn’t supposed to select a mode that the monitor doesn’t support. But if it does, the logical thing would be to ignore the resolution in monitors.xml, and go on with the monitor’s preferred mode. In reality, it appears like this causes the blank screen that I’ve mentioned on this post.
The automatic setting of resolution seems to take place when some kind of X session starts (the login screen and after the user logs in) as well as when a new monitor is hotplugged. Setting a monitor’s mode with xrandr seems to trigger an automatic setting as well sometimes. Having tried to set the resolution with xrandr a few times, it reverts sometimes to the automatic setting, and sometimes it stays with the one I set. Go figure.
It seems to be related to Cinnamon’s setting daemon (executed as /usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/csd-xrandr), which, according to this thread, can be turned off by going to Menu > Startup Applications and switch off “Cinnamon Setting Daemon – xrandr” (that simple?!). It has also been suggested to remove ~/.config/autostart/cinnamon-settings-daemon-xrandr.desktop, but I don’t have such file on my computer. Anyhow, I discovered this possibility after solving my own problem in another way, so I didn’t get further into this.
How I got it done (hopefully)
IMPORTANT: I’ve added another post on how to really nail down the graphics mode, even if the trick below fails.
Since there are all kinds of ghosts in the system that insist on “fixing” the display resolution, I might as well play along. So the trick is as follows:
- Edit ~/.config/monitors.xml (manually), setting the resolution for all monitors listed to the one I want.
- Make sure that the desired graphics mode, along with its timing parameters, is listed by xrandr, even if the monitor didn’t mention it in its EDID info.The first step is relatively easy. The entries in the XML file look like this:
<output name="HDMI3">
<vendor>SNY</vendor>
<product>0x0801</product>
<serial>0x01010101</serial>
<width>1360</width>
<height>768</height>
<rate>60</rate>
<x>0</x>
<y>0</y>
<rotation>normal</rotation>
<reflect_x>no</reflect_x>
<reflect_y>no</reflect_y>
<primary>yes</primary>
</output>
This is after editing the file. I needed 1360 x 768 @60 Hz, as shown above. So just set the width, height and rate tags in the XML file for all entries. No matter what monitor the system thinks it sees, the “user preference” is the same.
Now making sure that the mode exists: Add something like the following as /etc/X11/Xsession.d/10add-xrandr-mode (owned by root, not executable, no shebang):
xrandr -d :0 --newmode "hdmi_splitter" 85.5 1360 1424 1536 1792 768 771 777 795 +hsync +vsync
xrandr -d :0 --addmode HDMI3 hdmi_splitter
xrandr -d :0 --output HDMI3 --mode hdmi_splitter
Needless to say (?), this relates to the specific graphics mode.
So this file is executed every time X is started (and hence the xrandr modes list is cleared). All it does is making sure that the relevant output port (HDMI3) knows how to display 1360 x 768. Note that the name of the mode has no particular significance, and that the frame rate isn’t given explicitly, but is calculated by the tools. I got these figures from an xrandr readout with the desired monitor connected directly. See the full listing at the end of this post. It’s the first entry there.
The third command actually switches the display to the desired mode. It can be removed actually, because it’s overridden very soon anyhow. Nevertheless, it shows the command that can be used manually on console, given the two earlier commands (should not be needed, given that the mode is invoked automatically, fingers crossed).
That’s it. Except for occasional glitches (getting full control of this was too much to expect), the two actions mentioned above are enough to get the mode I wanted. Not the “no matter what” I wanted, but close enough.
As for the -d :0 flags, it’s required in remote sessions and scripts. Alternatively, start with an
$ export DISPLAY=:0
Using cvt to obtain the timing parameters (not!)
It’s suggested on some websites to obtain the timing parameters with something like
$ cvt 1360 768 60
# 1360x768 59.80 Hz (CVT) hsync: 47.72 kHz; pclk: 84.75 MHz
Modeline "1360x768_60.00" 84.75 1360 1432 1568 1776 768 771 781 798 -hsync +vsync
I tried this, and the monitor didn’t sync on the signal. It’s indeed a pretty lousy monitor to miss on a DVI signals, and still.
Note the small differences between the timing parameters — that’s probably the reason for this failure. So when the real parameters can be obtained, use them. There is no secret catch-all formula for all graphics modes. The formula works on a good day.
Hands off, Cinnamon’s daemon!
My original idea was to turn off all automatic graphics mode setting mechanisms, and stay with a single xrandr command, running from /etc/X11/Xsession.d/ or something. It was a great idea, but it didn’t work: I saw a momentary switch to the mode I wanted, and then it changed to something else. I could have added some kind of daemon of my own, that waits a bit and then changes the mode with xrandr, but that’s just adding another daemon to wrestle with the others.
So this didn’t really help, but I’ll leave it here anyway, in case someone wants to change the display mode without having some daemon change it back. Note that according to this page, using gsettings as shown below works only up to Cinnamon before version 3.4, after which the procedure is different (haven’t tried it however): Copy /etc/xdg/autostart/cinnamon-settings-daemon-xrandr.desktop to $HOME/.config/autostart. Then append the line Hidden=true to the copied file.
In short, YMMV. Here’s how I did it on my system (and then found it’s not good enough, as mentioned above).
Resolution mode settings made with xrandr will be sporadically overridden by cinnamon-settings-daemon, which has a lot of plugins running for different housekeeping tasks. One of them is to keep X-Window’s display resolution in sync with .config/monitors.xml. So disable it.
Following my own post, this is typically the setting for the said plugin:
$ gsettings list-recursively org.gnome.settings-daemon.plugins.xrandr
org.gnome.settings-daemon.plugins.xrandr active true
org.gnome.settings-daemon.plugins.xrandr priority 0
org.gnome.settings-daemon.plugins.xrandr default-monitors-setup 'follow-lid'
org.gnome.settings-daemon.plugins.xrandr default-configuration-file '/etc/gnome-settings-daemon/xrandr/monitors.xml'
So turn it off:
$ gsettings set org.gnome.settings-daemon.plugins.xrandr active false
and then check again with the list-recursively command above.
xrandr output: The full list of modes
Just for reference, these are the modes given by xrandr for the monitor I did all this for:
$ xrandr -d :0 --verbose
[ ... ]
1360x768 (0x4b) 85.500MHz +HSync +VSync *current +preferred
h: width 1360 start 1424 end 1536 total 1792 skew 0 clock 47.71KHz
v: height 768 start 771 end 777 total 795 clock 60.02Hz
1920x1080i (0x10b) 74.250MHz -HSync -VSync Interlace
h: width 1920 start 2008 end 2052 total 2200 skew 0 clock 33.75KHz
v: height 1080 start 1084 end 1094 total 1125 clock 60.00Hz
1920x1080i (0x10c) 74.250MHz +HSync +VSync Interlace
h: width 1920 start 2008 end 2052 total 2200 skew 0 clock 33.75KHz
v: height 1080 start 1084 end 1094 total 1125 clock 60.00Hz
1920x1080i (0x10d) 74.250MHz +HSync +VSync Interlace
h: width 1920 start 2448 end 2492 total 2640 skew 0 clock 28.12KHz
v: height 1080 start 1084 end 1094 total 1125 clock 50.00Hz
1920x1080i (0x10e) 74.176MHz +HSync +VSync Interlace
h: width 1920 start 2008 end 2052 total 2200 skew 0 clock 33.72KHz
v: height 1080 start 1084 end 1094 total 1125 clock 59.94Hz
1280x720 (0x10f) 74.250MHz -HSync -VSync
h: width 1280 start 1390 end 1430 total 1650 skew 0 clock 45.00KHz
v: height 720 start 725 end 730 total 750 clock 60.00Hz
1280x720 (0x110) 74.250MHz +HSync +VSync
h: width 1280 start 1390 end 1430 total 1650 skew 0 clock 45.00KHz
v: height 720 start 725 end 730 total 750 clock 60.00Hz
1280x720 (0x111) 74.250MHz +HSync +VSync
h: width 1280 start 1720 end 1760 total 1980 skew 0 clock 37.50KHz
v: height 720 start 725 end 730 total 750 clock 50.00Hz
1280x720 (0x112) 74.176MHz +HSync +VSync
h: width 1280 start 1390 end 1430 total 1650 skew 0 clock 44.96KHz
v: height 720 start 725 end 730 total 750 clock 59.94Hz
1024x768 (0x113) 65.000MHz -HSync -VSync
h: width 1024 start 1048 end 1184 total 1344 skew 0 clock 48.36KHz
v: height 768 start 771 end 777 total 806 clock 60.00Hz
800x600 (0x114) 40.000MHz +HSync +VSync
h: width 800 start 840 end 968 total 1056 skew 0 clock 37.88KHz
v: height 600 start 601 end 605 total 628 clock 60.32Hz
720x576 (0x115) 27.000MHz -HSync -VSync
h: width 720 start 732 end 796 total 864 skew 0 clock 31.25KHz
v: height 576 start 581 end 586 total 625 clock 50.00Hz
720x576i (0x116) 13.500MHz -HSync -VSync Interlace
h: width 720 start 732 end 795 total 864 skew 0 clock 15.62KHz
v: height 576 start 580 end 586 total 625 clock 50.00Hz
720x480 (0x117) 27.027MHz -HSync -VSync
h: width 720 start 736 end 798 total 858 skew 0 clock 31.50KHz
v: height 480 start 489 end 495 total 525 clock 60.00Hz
720x480 (0x118) 27.000MHz -HSync -VSync
h: width 720 start 736 end 798 total 858 skew 0 clock 31.47KHz
v: height 480 start 489 end 495 total 525 clock 59.94Hz
720x480i (0x119) 13.514MHz -HSync -VSync Interlace
h: width 720 start 739 end 801 total 858 skew 0 clock 15.75KHz
v: height 480 start 488 end 494 total 525 clock 60.00Hz
720x480i (0x11a) 13.500MHz -HSync -VSync Interlace
h: width 720 start 739 end 801 total 858 skew 0 clock 15.73KHz
v: height 480 start 488 end 494 total 525 clock 59.94Hz
640x480 (0x11b) 25.200MHz -HSync -VSync
h: width 640 start 656 end 752 total 800 skew 0 clock 31.50KHz
v: height 480 start 490 end 492 total 525 clock 60.00Hz
640x480 (0x11c) 25.175MHz -HSync -VSync
h: width 640 start 656 end 752 total 800 skew 0 clock 31.47KHz
v: height 480 start 490 end 492 total 525 clock 59.94Hz
The vast majority are standard VESA modes.
What’s that good for?
This isn’t about maintaining a local repository that mirrors its original, following along with its changes. The idea is to avoid the upgrades of a lot of packages every time I want to install a new one with apt. Maybe I should mention that I don’t allow automatic upgrades on my machine? Exactly like I don’t leave my car keys to the mechanic, so he can make any fixes he considers would make my car better. Every day.
Before I get into the technical details, I’ll have my say on the culture of upgrading everything all the time. Just in case someone with influence on the matter reads this. Or maybe someone ready to maintain a non-updating mirror…?
The way packaging is made today is that each package requires the latest-latest dependencies just because they happened to exist, not because they’re needed. I mean, forcing an unnecessary upgrade of other packages is fine, because how could upgrading be wrong? Or go wrong?
But upgrading is good…?
Most people believe upgrading software is generally good. Personally, I don’t. Every now and then, an upgrade breaks something that worked, and even seemingly harmless upgrades of minor pieces of software can force me into a session of debugging my system. It may very well be that the upgrade rectified something that was wrong before. But this way or another, my computer worked before, and after the upgrade it didn’t. As has already been said:
If it ain’t broke, don’t fix it.
Upgrades sometimes involve security fixes. Staying with old versions is considered neglecting your security. This may be true when the computer is a server or a multiuser machine, and strangers are allowed to do this and that with it. However when it comes to single-user desktops that are properly set up (plus a firewall), the risk for an upfront security exploit is rather minimal. I always ask people when they last heard about a personal Linux desktop being compromised by virtue of a vulnerability, and nobody can come up with such case.
I’ve also discussed this issue with several guys who are responsible for major Linux systems, for which a downtime means real damage, and stability is important. The typical conversation contains an apology for using old distributions and old software, and them reassuring me that they understand that upgrading is important. It’s just that in their specific case they have to stick to a certain, old Linux distribution to keep the system running continuously.
So it’s a risk management question: The risk of having the computer messed up by an upgrade (with probability converging to 1 as time increases) vs the probability of desktop being attacked (probability not known, as no such event is known to me). Given that I fix significant security issues by other means, as they occur.
So my decision is clear, and here’s how to do it.
apt-mirror
All said below relates to Linux Mint 19, but most likely applies to a wide range of Debian-based distros.
apt-mirror is a cleverly written Perl script that mirrors selected Debian repositories into the local disk. It’s one of those utilities that simply do the job with the practical, real-life details taken care of correctly. In the proper Perl spirit, in short.
In essence:
- Install apt-mirror with a plain apt command.
- Change the ownership the directory to which the packages go (given as base_path in the config file) to apt-mirror.
- Don’t set up the cron job, as we’re not into having it updated (possibly delete /etc/cron.d/apt-mirror).
Set up mirror.list
The default /etc/apt/mirror.list is generally fine, with nthreads set to 20 by default, which is OK.
You may want to set base_path in /etc/apt/mirror.list to something else than the default.
Then copy all repositories listed in /etc/apt/sources.list.d into mirror.list. This is just copying the lines beginning with “deb” as is.
Well, probably not. If you’re running on a 64-bit machine (is there anyone not?), set /etc/apt/mirror.list to download packages for amd64 and i386. This will grow the disk consumption from 140 GB to 193 GB (YMMV), but sometimes these i386 packages are handy.
For this to work, each line must appear twice. So if the original “deb” line said
deb http://packages.linuxmint.com tara main upstream import backport
these two should appear in mirror.list:
deb-i386 http://packages.linuxmint.com tara main upstream import backport
deb-amd64 http://packages.linuxmint.com tara main upstream import backport
Otherwise apt-mirror downloads only the packages for the current arch. One can also add a deb-src for the mirror repository as well, if desired.
Running apt-mirror
Run apt-mirror as root with
# su - apt-mirror -c apt-mirror
The cool part with running it this way is that if you go CTRL-C (you want to do that, apt-mirror runs forever on the first attempt, downloading ~200 GiB or so), the child processes (a lot of wgets) are killed gracefully as well.
How it works: First it does some crunching of the repositories’ metadata. After not too long time, it generates 20 processes, each for downloading a list of URLs:
wget --no-cache --limit-rate=100m -t 5 -r -N -l inf -o /opt/apt-mirror/var/archive-log.0 -i /opt/apt-mirror/var/archive-urls.0
all of which run in /opt/apt-mirror/mirror, which is the target for the files.
and then it just waits. The output shown on console (like “[20]…”) is the number of processes still running.
Configure apt to use local repositories only
First of all, move the “mirror” subdirectory away to some other place, so it’s out of sight for apt-mirror. No more updates. For example, into /var/local-apt-repo. I also suggest changing its owner to root at this stage:
# chown -R root:root local-apt-repo/
So a line saying
deb http://packages.linuxmint.com tara main upstream import backport
changes into (if the repository is kept in /var/local-apt-repo/)
deb file:///var/local-apt-repo/packages.linuxmint.com tara main upstream import backport
and make apt aware of the change:
# apt clean
# apt update
Verify that only local files are accessed (it prints out the paths) and that there are no errors. Those opting out downloading the i386 repositories as well will get a lot of error messages at the end, like
E: Failed to fetch file:/var/local-apt-repo/packages.linuxmint.com/dists/tara/main/binary-i386/Packages File not found - /var/local-apt-repo/packages.linuxmint.com/dists/tara/main/binary-i386/Packages (2: No such file or directory)
I suppose it’s harmless to the end that there will be no i386 packages to work with, but I don’t really know, as I went for downloading packages for both archs.
And then comes the last session of upgrades. At a convenient time for tackling possible upgrade side effects, go
# apt list --upgradable
and then try to upgrade packages in small chunks, so that the changes each make can be tracked (in particular if you have a git repo on /etc, like myself), with
# apt install --only-upgrade package-name
For convenience, package-name may include wildcards with * (use single quotes or escape it with backslash, i.e. \*).
After all this is done, fix whatever broke because of all upgrades. In my case I lost graphics acceleration on my NVidia card, solved by manually reinstalling the drivers as originally downloaded from the vendor. Just to remind me why I’m doing all this.
If apt-file is also installed (it’s a good idea to have it), this is also a good time to go
# apt-file update
How and why the local repo is self-contained
It’s not worth much to take a snapshot that can’t be relied upon forever. The fact that the download process typically takes a few days, most likely with several interruptions in the middle, doesn’t contribute to the feeling of reassurance. I ran my downloads on nights only, for example (hey, I want a decent internet connection during the day).
This is solved in a surprisingly simple manner: The Packages files contain the list of files required for constituting a self-contained repository. apt-mirror first downloads these files, then it downloads the files it requires, and then uploads the Packages files in the mirror. At all times, all required files are in place.
This is why it’s safe to stop apt-mirror in the middle: Even though the running wget processes will leave some files half-downloaded, they will be fixed on the next run: apt-mirror compares the size of the file on disk with the size declared in the respective Packages file (in its need_update() function). So all files in the Packages files must exist and be of the correct size. This is apt-mirror’s view of a file being in place.
One could also compare the SHA sums of each file in the entire repo. I haven’t found such utility, and I’m not sure it’s worth the effort.
There’s somewhat reassuring to run apt-mirror after its completion, and see that it downloads nothing. It seems like that doesn’t happen. I ended up downloading one archive file of 596 MiB each time (or so apt-mirror said), but then going
$ find /opt/apt-mirror/ -iname \*.deb -cmin -3
found no files. So this was probably only metadata loaded (indeed, dropping the *.deb requirement listed a lot of files).
Reducing wasted disk space
A side effect of the way apt-mirror works, is that outdated packages remain in the repository: When apt-mirror is re-run, it makes sure that all files in the current Packages files are downloaded. When a package is updated, a new package file is enlisted, and the old one just vanishes from the Packages file. But apt-mirror doesn’t delete it, as it’s in the process of updating the repository. The old Packages file is still in effect.
Also, in a real-life mirror scenario, someone could be in the middle of an installation which is based upon several files. So the unnecessary files can only be deleted after the Packages files have been updated (i.e. when apt-mirror finishes) plus the maximal time one could imagine an installation to take. Actually, in a continuously updating web mirror situation, removing a package file will break things for end-users until they run “apt update”. So a real mirror with happy end users should probably not delete files all that often.
Anyhow, apt-mirror creates a clean.sh script in the var/ subdirectory, which deletes all files that aren’t required by the current set of Packages files. It should be executed to get rid of those, when it’s good time. Note that the script changes directory to the absolute path to which it downloaded the mirror (so watch out if you’re moving that directory eventually).
# su - apt-mirror -c /opt/apt-mirror/var/clean.sh
For this script to be generated, add “clean” lines in mirror.list, like
clean http://packages.linuxmint.com
If there are several “deb” lines for the same host, one “clean” line like the above covers them all.
Another waste of disk space is that security.ubuntu.com contains a lot of packages that are already in other repositories. As this entire repo takes 40 GB (30 GB for amd64 alone), it’s unfortunate. One possibility would be to write a script than scans the directories for identical files (based upon SHA sums) and removes one file, replacing it with a symbolic link. Or maybe get this info from the Packages file. Or, like I did, not bother at all.
You have been warned
This post shows how to cripple the installation of a Debian package, and make the system think it went through OK. This might very well bring your system’s behavior towards the exotic, unless you know perfectly what you’re doing.
In some few cases, like the one shown below, it might actually be a good idea.
Introduction
Sometimes the post-installation script of Debian packages fails for a good reason. So good that one wants to ignore the failure, and mark the package as installed, so its dependencies are in place. And so apt stops nagging about it.
On my Linux Mint 19 machine, this happened to me with grub-efi-amd64: Its installation involves updating something in /boot, which is mounted read-only, exactly for that reason: The system boots perfectly, why fiddle?
And indeed, it’s not fully installed (note the iF part):
$ dpkg -l grub-efi-amd64
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=====================================================-===============================-===============================-================================================================================================================
iF grub-efi-amd64 2.02-2ubuntu8.13 amd64 GRand Unified Bootloader, version 2 (EFI-AMD64 version)
There must be an easy way around it…?
OK, so how about giving it a push?
# dpkg --configure --force-all grub-efi-amd64
Setting up grub-efi-amd64 (2.02-2ubuntu8.13) ...
Installing for x86_64-efi platform.
grub-install: error: cannot delete `/boot/grub/x86_64-efi/lsacpi.mod': Read-only file system.
Failed: grub-install --target=x86_64-efi
WARNING: Bootloader is not properly installed, system may not be bootable
cp: cannot create regular file '/boot/grub/unicode.pf2': Read-only file system
dpkg: error processing package grub-efi-amd64 (--configure):
installed grub-efi-amd64 package post-installation script subprocess returned error exit status 1
Errors were encountered while processing:
grub-efi-amd64
Not only didn’t it work, but this error message appears every time I try installing anything with apt. It will always attempt to finish that installation. And fail.
After quite some googling, I’m convinced that there’s no way to tell apt or dpkg to ignore a failed post-installation. Not with a million warnings and confirmations. Nothing. The post installation must succeed, by hook or by crook. The packaging machinery simply won’t register a package as fully installed otherwise.
Maybe apt-mark?
Ehm, the truth is I wasn’t aware of this utility when I went through this. So maybe apt-mark can be used to mark the relevant package as installed, and that’s it. Will update if I run into a similar issue again.
The ugly fix
So that leaves us with the crook. Luckily, the script in question is in a known place, waiting to be edited:
# vi /var/lib/dpkg/info/grub-efi-amd64.postinst
For any other package, just replace the grub-efi-amd64 with what you have.
And just add an “exit 0″ as shown below. This makes the script return with success, without doing anything. You may want to examine what it would do, possibly perform some of the operations manually etc. But anyhow, it’s just this:
#!/bin/bash
set -e
exit 0;
[ ... ]
And then try again:
# dpkg --configure grub-efi-amd64
Setting up grub-efi-amd64 (2.02-2ubuntu8.13) ...
Like a charm, of course. And now the package is happily installed:
$ dpkg -l grub-efi-amd64
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-============-============-=================================
ii grub-efi-amd64 2.02-2ubuntu amd64 GRand Unified Bootloader, version
And don’t forget to remove that edit afterwards. Or possibly it might cause issues in the future…?
There are many ways to ask a Linux machine how it’s doing. I’ve collected a few of them, mostly for my own reference. I guess I’ll add more items as I run across new ones.
General Info
- inxi -Fxxxz (neat output, but makes the system send me security “password required” alert mails because of attempts to execute hddtemp).
- hwinfo
- lshw
- Temperature and fans: sensors
- hostnamectl (host name, kernel version, Distribution etc.)
- dmidecode: Lots of info on and by the BIOS (From computer model an make down to exact part number of installed DIMM memories etc.)
Status
- Logs: journalctl and dmesg
- systemctl, with all its variants
- Network: ifconfig
- Wifi: iwconfig
- Bluetooth: hciconfig, bluetootctl, btmon (for dumping traffic)
- CPU: lscpu
- PCI bus: lspci
- USB: lsusb
- RAID: mdadm –detail /dev/md0
Operating system
- List open files: lsof
- Memory usage: free, lsmem and read /proc/buddyinfo
- Various kernel statistics (including memory): vmstat (takes info from /proc/stat and /proc/meminfo in particular)
- Block devices and partitions: blkid and lsblk
- List namespaces: lsns
- List loaded kernel modules: lsmod
- List locks: lslocks