Skip to content

Verilog · Chapter 5.2 · Data & Variables

Register Data Types in Verilog

The first half of Chapter 5 covered the net side of Verilog, the language's model for physical interconnect. This section covers the other half, variables. A variable holds a value the procedural code assigns to it, and the simulator stores it across time and across clock edges. Verilog gives variables their own keywords such as reg, integer, and real, their own assignment statements inside always and initial blocks, and their own type system. The most confused name in the language sits at the top of this section, because reg does not mean register. A reg is a procedural-assignment target, and whether it becomes a flip-flop, a latch, combinational logic, or no hardware depends entirely on how the code writes to it. This page is the section overview and the synthesis rule every RTL engineer carries by reflex.

Foundation20 min readVerilogregintegerrealVariablesProcedural

Chapter 5 · Section 5.2 · Data & Variables

1. The Engineering Problem

A junior engineer writes their first piece of synthesisable Verilog. The intent is a synchronous up-counter:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module counter (
    input  wire        clk,
    input  wire        rst_n,
    output reg  [7:0]  count_q
);
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) count_q <= 8'h00;
        else        count_q <= count_q + 8'h01;
    end
endmodule

A second engineer writes what they think is the same counter but uses reg differently:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module counter_broken (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [7:0]  count_in,
    output reg  [7:0]  count_q
);
    always @(*) begin
        count_q = count_in + 8'h01;
    end
endmodule

Both modules declare count_q as reg [7:0]. The first synthesises to an 8-bit flip-flop with an asynchronous reset. The second synthesises to an 8-bit combinational adder — no flip-flop, no storage, no clock. The keyword reg is identical; the resulting hardware is different. The synthesis tool decided based on the always block style, not the keyword.

This is the single most-confused part of Verilog. Every textbook says "reg is for registers" and every working RTL engineer has to unlearn that and replace it with the real rule: reg is a procedural-assignment target. What it becomes after synthesis depends on the procedural code. The same keyword can produce a flop (clocked always), a latch (combinational always with incomplete assignments), a wire (combinational always with complete assignments), or no hardware at all (testbench-only reg driving stimulus).

The variable side of Verilog — reg, integer, real — is the second half of Chapter 5. This page is the section overview: what variables are, how they differ from nets, the four data types the section covers, and the synthesis-interpretation rule that decides what hardware each one becomes.

2. Why Verilog Has Two Type Families

The net side of Chapter 5 (5.1.x) covered constructs whose value is determined by continuous resolution over multiple drivers — every cycle, the simulator runs a resolution function over the active drivers and computes the net value. Nets model physical interconnect; their drivers are continuous-assignment statements (assign) or module-instance outputs.

The variable side of Chapter 5 (5.2.x) covers constructs whose value is determined by procedural assignment — explicit statements inside always or initial blocks that set the variable's value as the procedural code executes. Variables model the simulator's algorithmic state. Their assignments are = (blocking) or <= (non-blocking) statements inside procedural blocks.

The two halves of the language exist because hardware has two distinct kinds of signals:

  • Wires carry values produced by combinational logic — the value at any instant is determined by the current inputs, with no memory. A wire matches this electrical model directly.
  • State carries values produced by sequential logic — the value at any instant depends on the previous value and the conditions under which it was written. A flop or latch matches this model directly, and Verilog's reg is the language's procedural-assignment target that the synthesis tool maps to flops, latches, or combinational logic depending on how the code writes to it.

Confusing the two is the bedrock mistake of beginner Verilog. You cannot drive a wire from inside an always block (the compiler errors out). You cannot drive a reg from a continuous assign (compiler error again). The language enforces the type-family split syntactically; the synthesis tool then interprets the procedural code to decide what hardware to generate.

3. Mental Model

The mental-model has four practical consequences:

  • reg is a syntactic category, not a hardware category. The synthesis tool reads the always block to decide what hardware to generate; the keyword's role is to mark "this signal is procedurally assigned" (vs wire, which marks "this signal is continuously assigned").
  • You can declare a reg and never have it synthesise to hardware. Testbench-only regs (stimulus generators, scoreboards) live entirely in the simulator's memory and don't appear in the netlist.
  • You can declare a reg that synthesises to a wire. A reg assigned by a combinational always @(*) with full coverage of all input combinations becomes a piece of combinational logic — no flop, no latch, no storage in the gates.
  • The reverse is also true: you can have storage without a reg. Some constructs (the task and function argument bindings; automatic variables in tasks) introduce variables without explicit reg declarations.

4. The Three Variable Types

Verilog defines three variable data types. Each has a distinct purpose and a distinct synthesis story.

TypePurposeWidth4-state / 2-stateSynthesis
regGeneral-purpose procedural-assignment targetConfigurable ([N-1:0])4-state (0, 1, Z, X)Maps to flop / latch / wire based on always block
integerSigned arithmetic; loop variables; counters in testbenchesFixed 32 bits, signed4-stateSynthesisable but unusual — typically used in testbenches and generate loops
realFloating-point values; analog modelling; testbench stimulus64-bit IEEE 754 (host platform)2-state (no X / Z)Not synthesisable — simulation-only

The next four sub-topics (5.2.1–5.2.4) drill into the three types and into the dimensions (scalar / vector / array) that shape every one of them:

  • 5.2.1 reg — the workhorse. Procedural-assignment target with explicit width. Becomes flop / latch / wire depending on the always block.
  • 5.2.2 integer — 32-bit signed. The "I just need a counter" variable; primarily testbench / for-loop usage; synthesisable with caveats.
  • 5.2.3 real — floating-point. Simulation-only. Used for analog modelling, timing-extraction post-processing, and testbench analytics.
  • 5.2.4 Scalar vs Vector vs Arrays — the three dimensions a variable can take. Scalar (1 bit), vector (multi-bit packed [N-1:0]), array (multiple instances [M-1:0] after the name).

The section's structure mirrors how engineers reach for the types in real work: reg for almost everything, integer for testbench iteration and counter variables, real for analytics, and the dimensions topic for the array vs vector decision that turns a one-bit register into an 8-bit bus or a 1024×8 memory.

5. The Net-vs-Variable Rules

The language enforces strict rules about where each type family can be used. Violating a rule produces a compile error, not a runtime surprise — which is fortunate, because the synthesis interpretation downstream would otherwise be impossible.

ContextAllowed typeReason
Left side of assignnet (wire, tri, tri0, etc.)Continuous assignment produces a continuously-resolved value
Left side of = / <= inside always / initialvariable (reg, integer, real)Procedural assignment requires storage
Right side of any assignmenteitherReading a value imposes no constraint
Module input portnet (wire by default)Driven by the parent module's continuous expression
Module output porteither (wire or reg)A reg output port is set by an internal always; a wire output port is set by a continuous assignment
Module inout portnet onlyBidirectional ports must support contention-aware resolution
Sensitivity list of always @(...)eitherRead-only context
Initial value of a declaration (reg [7:0] x = 8'h00;)variable onlyThe initial value is a procedural assignment at t = 0
for loop iteration variablevariable (integer or reg)Loop variables are procedurally assigned each iteration

Three rules a working engineer carries by reflex:

  1. wire for combinational interconnect. Anywhere you'd write assign, the target is a wire. Never a reg.
  2. reg for procedural storage. Anywhere you'd write inside an always or initial block, the target is a reg (or integer / real). Never a wire.
  3. output reg for module outputs set by an internal always. The most common port-list pattern in RTL — drive the output from a clocked always block.

The fourth rule is the synthesis rule that converts the procedural code to hardware:

  • A reg assigned inside always @(posedge clk) becomes a flip-flop.
  • A reg assigned inside always @(*) with all branches assigning all output variables becomes combinational logic (no storage).
  • A reg assigned inside always @(*) with missing assignments in some branches becomes a latch. (Almost always a bug — see §10.)

The first sub-topic (5.2.1) drills into these synthesis rules for reg specifically; this page introduces them at the framing level.

6. Visual Explanation

Three figures cover the structural picture.

6.1 Visual A — the type-family tree

The two halves of Chapter 5 side by side. Section 5.1 covered the left half (nets); section 5.2 covers the right half (variables).

Verilog data type families — nets (5.1) and variables (5.2)

data flow
Verilog data type families — nets (5.1) and variables (5.2)Chapter 5: DataTypesthe language's type system5.1 Netscontinuous resolution; physical interconnect5.2 Variablesprocedural assignment; algorithmic storagewire, tri, ...covered in 5.1.1–5.1.6reg, integer,realcovered in this section (5.2.1–5.2.4)
The two halves of Chapter 5. Nets and variables are syntactically distinct, assignment-style distinct, and synthesis-rule distinct. They are NOT just 'different keywords for similar things' — they model fundamentally different parts of the design.

6.2 Visual B — net vs variable assignment

Side-by-side: the same logical signal, modelled as a wire (continuous assignment) and as a reg (procedural assignment). The two produce the same hardware behaviour in this simple case, but the language constraints differ.

wire continuous assignment vs reg procedural assignmentwire a;inputwire b;inputwire y;assign y = a | b;reg y;always @(*) y = a | b;OR gatesame hardware aftersynthesis12
Both express 'a OR b'. Left: declared as wire, driven by a continuous assign — combinational by language design. Right: declared as reg, driven inside an always @(*) block — combinational by synthesis interpretation. Functionally equivalent here, but the variable form requires the always block; the net form is one line shorter and more idiomatic for pure combinational expressions.

6.3 Visual C — what reg becomes after synthesis

The same reg declaration, in three different always-block contexts, produces three different pieces of hardware. The keyword does not decide; the always block does.

reg synthesis interpretation depends on always blockreg q;declarationalways @(posedge clk)clockedflip-flopsynthesised gatesalways @(*)full coveragewireno storagealways @(*)incomplete coverageLATCHusually a bug12
A reg declared at the module level is just a procedural-assignment target. The synthesis tool reads the always block that drives it and decides the hardware. Clocked always → flip-flop. Combinational always with full coverage → wire (no storage). Combinational always with incomplete coverage → latch.

7. The Canonical reg Patterns

Three short examples cover the three synthesis outcomes. Every working engineer recognises these patterns by reflex.

7.1 reg → flip-flop (clocked always)

rtl/reg_to_flop.v — the most common pattern in synthesisable RTL
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`default_nettype none
 
module up_counter (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        en,
    output reg  [7:0]  count_q       // reg in the port list, driven by clocked always
);
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)        count_q <= 8'h00;        // asynchronous reset
        else if (en)       count_q <= count_q + 8'h01;
    end
endmodule

The always @(posedge clk or negedge rst_n) sensitivity list signals "clocked process" to the synthesis tool. The <= non-blocking assignment inside the block is the canonical flop-write idiom. The synthesis tool produces an 8-bit flip-flop bank with asynchronous-reset capability — one flop per bit, 8 D-FFs in the netlist.

Three discipline rules in this pattern:

  • Use <= for clocked assignment. The non-blocking assignment makes the synthesis tool's job unambiguous (flop input, sample on posedge clk) and produces deterministic simulation across simulators.
  • Reset every reg unconditionally. Every flop in the design should reset to a defined value during !rst_n; missing reset paths produce X-propagation issues at gate-level simulation.
  • Either reset or hold the previous value. The else if (en) pattern is correct: when en=0, the flop simply holds its previous value because there's no assignment for that case. The synthesis tool infers a clock-enable flop, which is the right hardware.

7.2 reg → combinational (always @(*) with full coverage)

rtl/reg_to_comb.v — combinational reg, no storage
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`default_nettype none
 
module adder_decoder (
    input  wire [3:0]  a,
    input  wire [3:0]  b,
    input  wire        sub_n_add,
    output reg  [4:0]  result        // reg in port list, driven by always @(*)
);
    always @(*) begin
        if (sub_n_add)  result = {1'b0, a} - {1'b0, b};   // = sign-extend, subtract
        else            result = {1'b0, a} + {1'b0, b};   // = sign-extend, add
    end
endmodule

The always @(*) sensitivity list signals "combinational process." The = blocking assignment is the canonical combinational idiom. Both branches assign result — full coverage of every input combination. The synthesis tool produces a 5-bit adder / subtractor mux — no flop, no latch, no storage. Same hardware as assign result = sub_n_add ? ... : ...; would produce on a wire.

The pattern is useful when the combinational expression is too complex for a single assign (e.g., a case statement, a multi-branch decoder, a state-encoded mux). The choice between assign on a wire and always @(*) on a reg is mostly stylistic for this case — same gates either way.

7.3 reg → latch (always @(*) with incomplete coverage)

rtl/reg_to_latch.v — almost always a bug
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`default_nettype none
 
module unintended_latch (
    input  wire        en,
    input  wire [3:0]  data_in,
    output reg  [3:0]  data_out      // INTENDED combinational; ACTUAL latch
);
    always @(*) begin
        if (en) data_out = data_in;
        // BUG: no else branch → data_out is not assigned when en=0
        //                       → synthesis infers a latch to "remember" the value
    end
endmodule

The always @(*) sensitivity list signals combinational intent. But the procedural code only assigns data_out when en=1; when en=0, the code path doesn't touch data_out, so the simulator's value of data_out is whatever it was on the previous activation of the block. The synthesis tool interprets this as "storage required" and produces a transparent latch.

A latch is almost always a bug. Latches:

  • Are transparent (pass-through) during the active level of the enable, then hold during the inactive level — they make timing analysis much harder than a flop.
  • Are forbidden by most ASIC sign-off rules — the synthesis tool will emit a lint warning ("LATCH inferred at signal data_out") that should be treated as an error.
  • Are easy to write accidentally — any incomplete-coverage if or case in a combinational always produces one.

The fix is to assign every output in every branch:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
always @(*) begin
    if (en) data_out = data_in;
    else    data_out = 4'b0000;   // explicit default value
end

Or, equivalently, set the default at the top of the block:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
always @(*) begin
    data_out = 4'b0000;            // default: zero
    if (en) data_out = data_in;    // override when en=1
end

Either form gives the synthesis tool full coverage and produces combinational logic (a 4-input mux), not a latch. The 5.2.1 reg sub-page covers this rule in detail with worked examples and lint outputs.

8. Simulation Behavior

Variables in Verilog have three behaviours that distinguish them from nets:

  • Procedural assignment, not resolution. A variable's value changes only when a procedural statement (= or <=) assigns to it. There is no resolution function — the most-recent assignment wins.
  • Default value is X. At t = 0, every reg and integer starts at X (unknown) on every bit. real starts at 0.0 (no X representation for floats). The right RTL discipline: reset every reg in synthesisable code; in testbenches, initialise every reg in the initial block before sampling.
  • Held across clock edges and time slots. A variable's value persists from the time it's last assigned until the next assignment. This is what makes it useful for modelling state — and what makes "I forgot to reset this reg" produce X-propagation issues.

The 5.2.1 sub-page covers the blocking-vs-non-blocking distinction in depth; this page introduces it at the framing level.

9. Waveform Analysis

A short waveform showing the same logical behaviour modelled three ways — as a wire, as a clocked reg, and as a combinational reg. The wire and combinational reg track their inputs continuously; the clocked reg samples its input on the clock edge.

wire / clocked reg / comb reg — three modelling styles, two distinct behaviours

12 cycles
wire / clocked reg / comb reg — three modelling styles, two distinct behaviourswire_y and comb_y track inputs continuouslywire_y and comb_y trac…a=1 → both wire_y and comb_y go HIGH; clkd_q does not change yet (no clock edge)a=1 → both wire_y and …posedge clk → clkd_q samples (a|b)=1 from previous cycleposedge clk → clkd_q s…a=b=0 → wire_y and comb_y fall immediately; clkd_q held at 1 until next samplea=b=0 → wire_y and com…clkabwire_ycomb_yclkd_qt0t1t2t3t4t5t6t7t8t9t10t11
wire_y is driven by assign wire_y = a | b; comb_y is driven by always @(*) comb_y = a | b; clkd_q is driven by always @(posedge clk) clkd_q <= a | b. The wire and combinational reg are functionally identical — both produce a | b on every cycle. The clocked reg samples on the posedge clk, so it's delayed by one cycle and held between samples.

The waveform captures the synthesis-interpretation rule visually: the keyword does not matter for the wire-vs-comb-reg comparison (both produce the same output every cycle); the always-block style matters for the wire-vs-clocked-reg comparison (the clocked reg has memory; the wire doesn't).

10. Common Mistakes

Five pitfalls that catch every Verilog beginner.

10.1 "reg means register"

The textbook framing every beginner reads, and the wrong one. reg is a procedural-assignment target. The synthesis tool decides whether it becomes a register, a latch, a wire, or no hardware at all — based on the always block, not the keyword. Replace "reg means register" with "reg means procedurally assigned" in your mental model.

10.2 Mixing = and <= in the same always block

The blocking-vs-non-blocking distinction matters. Inside a clocked always, every assignment should be <= (deferred write, samples-then-updates semantic). Inside a combinational always, every assignment should be = (immediate write, propagates within the block). Mixing produces unpredictable behaviour across simulators and confuses every reader.

10.3 Incomplete combinational coverage → latch

The "I'll add the else branch later" mistake. Every reg assigned in a combinational always @(*) must be assigned in every branch of every if / case statement. Missing any branch produces a latch — usually unintended. The two fixes (explicit else, or default-at-top-of-block) cover every case. The 5.2.1 sub-page treats this as a first-class topic.

10.4 Using = for clocked storage

The = blocking assignment in a clocked block produces simulation that depends on the order of always blocks in the file — unspecified by the language. Different simulators may produce different results. Always use <= for clocked assignment; the deferred-write semantic guarantees correct sample-and-update behaviour across every simulator.

10.5 Forgetting that integer is signed and 32-bit

Verilog's integer is always 32-bit signed — not the platform's int, not a configurable width. Using integer for a value that should be unsigned (e.g., a memory address) produces unexpected sign-extension behaviour when the value reaches 2³¹. Use reg [31:0] (or whatever width is correct) for unsigned values; reserve integer for loop variables and small testbench counters.

11. Industry Use Cases

Three patterns that account for 95% of all variable usage in working RTL.

11.1 reg for every flop in the design

Every RTL block has flops. Every flop is declared reg in the language's eyes. The pattern is universal — Synopsys IP, Apple Verilog, NVIDIA RTL, every ARM core ever shipped. The reg keyword on a clocked always's target is the most common single line of Verilog in any production codebase.

11.2 reg for combinational always blocks

When a combinational expression is too complex for an assign — e.g., a case-statement decoder, a multi-stage mux, a finite-state machine's next-state logic — the working pattern is a combinational always @(*) with reg outputs. Pure decoders, ALU output selection, and FSM next-state logic almost always live in always @(*) blocks. The synthesis tool produces the same gates as the equivalent assign form, but the readability is better for multi-line logic.

11.3 integer for testbench iteration

Testbench initial blocks frequently iterate over a range of values — applying stimulus, sweeping through configuration parameters, walking through a memory. integer i; followed by a for (i = 0; i < N; i = i + 1) is the canonical loop construct. Synthesis-side use of integer in generate blocks for iteration is also common, but genvar (Chapter 14) is preferred for generate because it's purely a compile-time iterator.

12. Debugging Lab

Three register-data-type debug post-mortems

13. Coding Guidelines

  1. Use reg for any signal assigned inside always or initial. The keyword marks "procedurally assigned"; the synthesis tool decides what hardware to build.
  2. Use wire for any signal driven by assign or a module output port. The keyword marks "continuously resolved"; the synthesis tool produces interconnect.
  3. Clocked always blocks use <=. Combinational always blocks use =. Mixing inside the same block produces unpredictable behaviour across simulators.
  4. Every reg in synthesisable RTL is either reset unconditionally or assigned in every branch. Missing reset produces X-propagation; missing branch coverage produces latches.
  5. Use integer only for loop variables and small testbench counters. For unsigned values or widths other than 32, use reg [N-1:0].
  6. real is testbench-only. Synthesis tools reject real declarations; reserve it for analytics, BFM models, and stimulus generation.
  7. output reg for ports driven by an internal clocked always. output wire for ports driven by an internal assign. The port-list discipline tells the next engineer how the signal is driven.
  8. Name reg outputs of clocked alwayses with _q suffix. The convention count_q, state_q, data_q signals "this is a flop output" at a glance — separates the storage from the combinational logic that drives it.

14. Interview Q&A

15. Exercises

Three exercises that turn the variable model into reflex.

Exercise 1 — Identify the synthesis outcome

For each of the following code snippets, predict what the synthesis tool produces: flop, latch, combinational wire, or error.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// (a)
always @(posedge clk) q <= d;
 
// (b)
always @(*) y = a & b;
 
// (c)
always @(*) if (en) y = data;
 
// (d)
always @(*) begin
    y = 1'b0;
    if (en) y = data;
end
 
// (e)
assign q = d;   // where q is declared as reg

Hints. Use the §7 rules. (a) is a clocked block. (b) is a combinational always with full coverage. (c) is combinational with incomplete coverage. (d) has a default at the top. (e) is a syntax mismatch.

Exercise 2 — Convert latch to mux

The following module produces a latch warning during synthesis. Rewrite it so the synthesis tool produces a combinational mux instead. Keep the logical behaviour the same.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module decoder_with_latch (
    input  wire [1:0]  sel,
    input  wire [7:0]  data_a,
    input  wire [7:0]  data_b,
    input  wire [7:0]  data_c,
    output reg  [7:0]  data_out
);
    always @(*) begin
        case (sel)
            2'b00: data_out = data_a;
            2'b01: data_out = data_b;
            2'b10: data_out = data_c;
            // 2'b11: missing case — latch inferred for data_out
        endcase
    end
endmodule

Hints. Either add a default branch to the case, or set data_out at the top of the block before the case. Both fixes produce a mux instead of a latch.

Exercise 3 — Choose the right type

For each of the following signals, recommend whether to declare it as reg [N-1:0], integer, or wire [N-1:0]. Justify each choice.

#Signal description
1An 8-bit counter that increments every clock cycle
2The output of an assign statement implementing a & b
3A loop iteration variable in a testbench for loop
4A 16-bit address generated by a state machine
5A floating-point delay value used in the testbench
6The output of a combinational decoder in an always @(*) block

Hints. Loop variables and small testbench counters → integer. Floating-point → real. Signals driven by procedural code → reg [N-1:0]. Signals driven by assignwire [N-1:0].

16. Summary

Section 5.2 covers Verilog's variable types — the procedural-assignment targets that complement the net family from Section 5.1. The three variable types:

  • reg — general-purpose, configurable-width, 4-state. The workhorse. Synthesises to flop / latch / wire depending on the always block.
  • integer — 32-bit signed, 4-state. Loop variables and small testbench counters.
  • real — 64-bit IEEE 754 floating-point. Simulation-only.

The defining rule of the section — reg is not a register. The synthesis tool decides the hardware based on the always-block structure:

  • Clocked always (@(posedge clk), <=) → flip-flop.
  • Combinational always with full coverage (@(*), =) → wire (no storage).
  • Combinational always with missing coverage (@(*), incomplete if / case) → latch (usually a bug).

The net-vs-variable rules:

  • wire is set by assign; lives in combinational interconnect.
  • reg is set by = / <= inside always / initial; lives in procedural code.
  • The two type families are syntactically distinct — mixing produces compile errors.

The day-to-day discipline:

  • Use reg for any signal assigned inside always or initial. The keyword marks "procedurally assigned."
  • Use <= for clocked assignment, = for combinational. Don't mix in the same block.
  • Every reg is either reset or assigned in every branch. Missing reset → X-propagation. Missing branch coverage → latch.
  • Use integer only for loop variables and small testbench counters. For real RTL, reg [N-1:0] gives explicit control over width.
  • real is testbench-only. Synthesis tools reject it.

The next four sub-pages drill into each type:

  • 5.2.1 reg — the workhorse type, flop / latch / wire synthesis interpretation in depth.
  • 5.2.2 integer — 32-bit signed, testbench / loop usage, synthesis caveats.
  • 5.2.3 real — floating-point modelling for testbench analytics.
  • 5.2.4 Scalar vs Vector vs Arrays — the dimensions every variable can take.

After Section 5.2, Chapter 6 picks up with Constant Variables — the parameter and localparam keywords that anchor every parametrisable RTL block.

  • Variables & Data Types — Chapter 5; the parent overview that motivates this section.
  • Physical Data Types — Chapter 5.1; the sibling section on the net side.
  • wire and tri Nets — Chapter 5.1.1; the canonical net type that contrasts with reg.
  • RTL Designing — Chapter 3; the broader RTL design framing that explains the flop / combinational distinction.
  • Lexical Conventions — Chapter 4; the syntax rules that every variable declaration follows.