Altifigence Academy

20 / 37 · Concept

generate: building static circuits with loops

Use genvar and generate-if to create named circuit instances and check bus lane placement.

A generate loop creates instances, not clock cycles

genvar and a generate loop describe repeated static structure. The elaborator creates all instances before execution. A loop inside always_comb describes a procedural computation whose hardware is determined by synthesis. Neither automatically means one iteration per clock. Serial processing requires explicit state and a clocked controller.

This example splits a packed input bus into LANES words, each W bits wide, and computes one parity bit per word. W and LANES must both be positive integers.

SystemVerilog
module lane_parity #(
  parameter integer W = 8,
  parameter integer LANES = 3
) (
  input  logic [W*LANES-1:0] data,
  output logic [LANES-1:0] parity
);
  genvar lane;
  generate
    for (lane = 0; lane < LANES; lane = lane + 1) begin : g_lane
      wire [W-1:0] word_data;
      assign word_data = data[lane*W +: W];
      assign parity[lane] = ^word_data;
    end
  endgenerate
endmodule

data[base +: W] selects W bits starting at base and moving toward larger bit indices. W is constant for an elaborated instance. With W=8 and LANES=3, lane 0 receives bits 7:0, lane 1 bits 15:8, and lane 2 bits 23:16. The named block g_lane provides stable hierarchy such as g_lane[1].word_data for inspection.

Read the lane order from the declaration

For data=24'h03_01_80, lane values are 80,01,03 from lane 0 upward. Their parity bits are 1,1,0, so the displayed vector parity[2:0] is 3'b011. The leftmost hexadecimal byte is lane 2, not lane 0. Keep numerical indices, display order and transmission order separate.

All lanes compute concurrently. This design has no registered latency. A larger LANES value creates more combinational logic, not a longer sequence of cycles. Physical fanout, routing and timing still need their own implementation checks.

Generate-if chooses one fixed structure

A condition in generate-if must be constant during elaboration, such as a parameter choosing whether an optional register is included. A run-time signal must instead select behavior in a combinational or clocked block. Changing a configuration parameter from registered to unregistered also changes the valid-time contract, so it must be reflected in the port documentation and checker.

Do not use a parameter value of zero to “turn off” this bus. A range such as [−1:0] is not a safe zero-width object. Reject the unsupported setting or use an explicit generate branch whose external interface remains well-defined.

Practice · Detect lane swaps

Check the example above, then set exactly one bit in each lane in turn. Confirm that only the corresponding parity bit changes. Also test a word with two set bits: even parity must return 0. A test with identical words in every lane would fail to reveal swapped slices.

Use an independent checker that extracts a lane numerically and counts its set bits. Test W=1, W=8, LANES=1 and LANES=3. These cases expose assumptions about byte width, repeated hierarchy and minimum configuration.

Finally register the parity vector on a rising edge as a separate experiment. Specify reset, enable and whether the checker compares against the current bus or the bus sampled at the preceding edge.

Your choice applies to this browser. Change it any time using the footer.