[ < Prev | Up | Next > ]   Node: Limitations

hexforge / limitations

Limitations

This is the most useful page on the site. A toolchain that advertises what it supports and stays quiet about the rest wastes a weekend of your life; here is the rest.

The compiler rejects rather than ignores. With two documented exceptions, every unsupported construct is a hard error with a line number and a code. Silently dropping something and producing hardware that does not match the source is the one behaviour this project treats as unacceptable.

What the subset does accept

Stated first so the rest reads as a boundary rather than a wall. Modules with parameters and port lists; wire and reg with packed vectors and one level of unpacked array; continuous assignment; always @(posedge clk) and always @(*); if, case, casez, for with constant bounds; generate with if and for; automatic functions; arithmetic, logical, bitwise, shift, reduction and comparison operators; concatenation and replication; part selects, including indexed ones; localparam; `define, `ifdef and `include. That is enough for the whole of the example set.

Language: rejected constructs

Error codes are stable across releases; the wording of the message is not.
ConstructCodeWhy, and whether it is planned
defparamE118Order-dependent and awkward to elaborate. Use parameter overrides in the instantiation. Not planned.
Hierarchical names in expressionsE121The design is flattened early, so a cross-module reference has nothing to resolve against. Not planned before hierarchy is preserved.
specify blocks, path delaysE130Only meaningful for simulation and cell libraries. Not planned.
User-defined primitivesE131Table-driven primitives are a simulation feature. Not planned.
wand, wor, trireg, tri0, tri1E134No resolved-net modelling exists in the netlist format. Not planned.
Gate primitives beyond and or not xor bufE136nmos, pullup, rtran and relatives have no mapping on these devices. Not planned.
fork / joinE140No concurrency model in the front end. Not planned.
force, release, procedural assignE141Simulation control. Not planned.
Any delay, including #1E145Rejected rather than ignored, because a design whose behaviour depends on delays will not work as hardware. Not planned.
real, realtime, timeE150No floating-point representation in the netlist. Not planned.
TasksE152Functions are supported, tasks are not: a task with timing control is not synthesisable, and the useful subset would be a function anyway. Not planned.
casexE156Accepting it would require four-state semantics the compiler does not have, and its real-world use is usually a bug. Use casez, which is accepted with a warning.
Unpacked arrays beyond one dimensionE161An implementation limit in the elaborator. Planned for 0.8.
Signed arithmetic wider than 64 bitsE164Constant folding uses a 64-bit signed representation internally. Planned, no date.
Nested generate deeper than four levelsE170A recursion guard, not a design decision. Raise it and rebuild if you genuinely need five.
SystemVerilog of any kindE101logic, always_ff, interfaces, packages, typedef. A different standard; out of scope for this project.
VHDL, or mixing languagesE100One language, one front end. Not planned.

The two exceptions to rejecting: system tasks such as $display and $monitor are parsed and dropped with warning W301, because they are harmless in synthesis and removing them from shared source is tedious. And initial blocks are accepted in exactly one shape - a single assignment per memory word, used to give block RAM its initial contents.

Semantics: two-state only

The compiler has no notion of unknown or high-impedance values internally. A literal containing x is an error (E158); a literal containing z is an error everywhere except a continuous assignment driving an output port, where it becomes a tri-state pad.

The practical consequence is that any behaviour your simulator shows that depends on unknowns will not be reproduced. Reset every register you care about, and do not rely on a design that only works because x propagated somewhere convenient. Simulate before synthesis, with an external simulator; HexForge includes none.

Synthesis

Constraints

Five directives exist: set_io, create_clock, set_input_delay, set_output_delay, set_false_path. Everything else in a constraints file is an error.

So there is no set_multicycle_path, no set_max_delay, no clock group declarations, and no generated clocks - a PLL output must be declared with its own create_clock and the frequency you worked out by hand. Asynchronous crossings cannot be described at all beyond excluding them with set_false_path, and the analyser will keep warning about them, which is the intended outcome.

Devices and hard blocks

Tooling

Open defects

Four defects are both open and visible as failing tests. Nothing else in the suite is red.
IdSinceWhat goes wrong
#1410.4.0Delay model extrapolates beyond six routing hops and reads optimistic. Visible as warning W117 in a timing report.
#1640.5.0Packing above 94% occupancy on M1-8K fails to find a legal arrangement.
#1980.6.0Two-clock designs straddling a clock region boundary get packed illegally; the bitstream loads and the design misbehaves.
#2120.7.0Thistle Edge external clock pin is described in the wrong IO bank in t4.hxd, so only the internal oscillator is usable on that board.

If one of these is in your way, say so at hexforge@hexforge.cloud - priority here is set almost entirely by who is actually blocked. Defect #212 is a two-line fix waiting on someone with that board to confirm the correct bank.

[ < Prev | Up | Next > ]   Next node: Diagnostics
limitations · list reviewed at 0.7.2 · what moved recently