Frequently Asked Questions#

Why isn’t there an option for a flat non-struct hardware interface?#

SystemRDL is inherently a very hierarchical language. For small register blocks, flattening the hardware interface may be acceptable, but this ends up scaling very poorly as the design becomes larger and has more complex hierarchy. Using struct compositions for the hardware interface has the benefit of preserving conceptual hierarchy and arrays exactly as defined in the original SystemRDL.

How do I know I connected everything? Structs are harder to review#

Initially this can be daunting, but fortunately the tool has an option to generate a flattened hardware interface report upon export. Try using the --hwif-report command line option when exporting. This is the easiest way to quickly understand the structure of the hardware interface.

Why does the tool generate un-packed structs? I prefer packed structs.#

Packed structs are great when describing vectors that have bit-level structure. In this tool, the use of un-packed structs is intentional since the hardware interface is not something that is meant to be bit-accessible. In the case of the hardware interface structs, using a packed struct is semantically inappropriate.

… Then how can I initialize the struct?#

We get this request most often because designers want to initialize the hwif_in struct with a simple assignment:

always_comb begin
    hwif_in = '0;
end

Of course since the struct actually is unpacked, this will result in a compile error which usually leads to the inappropriate assumption that it ought to be packed. (See this amusing blog post about X/Y problems)

If your goal is to initialize the packed struct, fortunately SystemVerilog already has syntax to do this:

always_comb begin
    hwif_in = '{default: '0};
end

This is lesser-known syntax, but still very well supported by synthesis tools, and is the recommended way to handle this.

… What if I want to assign it to a bit-vector?#

Assigning the hwif struct to a bit-vector is strongly discouraged. This tool makes no guarantees regarding the field ordering of the hwif structure, so doing so should be considered functionally dangerous.

That said, if you still need to do this, it is still trivially possible to without requiring packed structs. Instead, use the SystemVerilog streaming operator:

my_packed_vector = {<<{hwif_out}};

… Why are unpacked structs preferred?#

In the case of the hardware interface ports, unpacked structs help prevent mistakes that are very easy to make. Consider the following situation - a designer has a field that sets the following properties: sw=rw; hw=rw; we;, and wants to assign the hardware input value, so they erroneously do the following assignment in Verilog:

assign hwif_in.my_register.my_field = <some value>;

This is actually a bug since the my_field member is actually a struct that has two members: we and next. If this were a packed struct, this would silently compile and you would potentially have a bug that may not be noticed (depending on how thorough the test campaign is). With an unpacked struct, this gets flagged immediately as a compile error since the assignment is invalid.

The designer may have simply forgotten that the field is an aggregate of multiple members and intended to do the following:

assign hwif.my_register.my_field.next = <some value>;
assign hwif.my_register.my_field.we = <some control signal>;

The generated output does not match our organization’s coding style#

SystemVerilog coding styles vary wildly, and unfortunately there is little consensus on this topic within the digital design community.

The output generated by PeakRDL-BusDecoder strives to be as human-readable as possible, and follow consistent indentation and styling. We do our best to use the most widely accepted coding style, but since this is a very opinionated space, it is impossible to satisfy everyone.

In general, we strive to follow the SystemVerilog style guide by lowRISC, but may deviate in some areas if not practical or would impose excessive complexity on the code generator.

The lint tool I am using is flagging violations in generated code#

Code linting tools are a great way to check for user-error, flag inconsistencies, and enforce best-practices within an organization. In many cases, linter tools may be configured to also enforce stylistic preferences. Unfortunately just like coding styles, lint rules can often be more opinionated than practical.

In general, we will not address lint violations unless they flag actual structural issues or semantically dangerous code. Stylistic violations that pose no actual danger to the correctness of the design will rarely be addressed, especially if the change would add unreasonable complexity to the tool.

If you encounter a lint violation, please carefully review and consider waiving it if it does not pose an actual danger. If you still believe it is a problem, please let us know by submitting an issue that describes the problem.