Skip to content

Verilog · Chapter 5.2.3 · Data & Variables

real in Verilog — Floating-Point Variables for Testbench Analytics

Most Verilog variables hold discrete values, since every signal in a synthesisable design is a zero or a one, with the occasional high-impedance or unknown state. But verification, analog mixed-signal modelling, and timing analysis often need values that do not fit that discrete model, such as voltages, currents, decay times, and probability distributions. The real type is Verilog's 64-bit IEEE 754 floating-point variable, the right tool for any computation that needs fractional values, very large or very small numbers, or arithmetic that will not fit in a few bits. The catch is that real is simulation-only, and no synthesis tool can map it to gates. It is reserved for testbench code, analog models, and timing post-processing, and that narrow scope is exactly where it earns its keep.

Foundation17 min readVerilogrealFloating PointTestbenchAnalog Modelling

Chapter 5 · Section 5.2.3 · Data & Variables

1. The Engineering Problem

A verification engineer is writing a testbench for a 12-bit ADC. The DUT produces a 12-bit digital output; the testbench needs to:

  • Generate an analog input voltage that varies as a sine wave over time.
  • Convert the expected voltage to the expected 12-bit code (code = round((V_in - V_ref_neg) / V_step)).
  • Compare the DUT's output against the expected code and report the RMS error across the entire test.
  • Compute statistical metrics (mean, standard deviation, max absolute error) for the test report.

None of these computations fit in reg [N-1:0]. The sine-wave generator needs sin(), which produces values in [-1.0, +1.0]. The voltage-to-code conversion needs division and rounding. The RMS error needs sqrt() and accumulation across thousands of samples. The statistics need mean = sum / N (non-integer division).

The right type for all of these is real:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real v_in, v_in_step;
real code_error, rms_acc;
integer sample_count;
 
initial begin
    v_in_step = 0.001;                                    // 1 mV step
    v_in = -1.0;
    rms_acc = 0.0;
    sample_count = 0;
 
    while (v_in < 1.0) begin
        v_in = v_in + v_in_step;
        // ... apply v_in to DUT, sample DUT output ...
        // Compute expected code:
        integer expected_code = $rtoi((v_in + 1.0) / 2.0 * 4095.0 + 0.5);
        code_error = $itor(dut_output - expected_code);
        rms_acc = rms_acc + code_error * code_error;
        sample_count = sample_count + 1;
    end
 
    $display("RMS error = %f LSB", $sqrt(rms_acc / sample_count));
end

The same testbench using integer or reg would either lose precision (truncating floating-point intermediate results to integers) or require manually-implemented fixed-point arithmetic — slow to write, slow to read, error-prone. The real type is the tool that turns a "complex testbench analytics" task into a "few lines of math."

This page covers real — what it is, what it can do, what it cannot do (the long list), and the canonical patterns where it earns its place in production verification code.

2. Anatomy of a real Declaration

The full real declaration syntax:

real-syntax.v — every legal form
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`default_nettype none
 
// real name [= initial_value] [, name2, ...];
 
real x;                              // scalar real, default 0.0
real volt = 1.8;                     // with initial value
real a, b, c;                        // multiple in one statement
real arr [0:7];                      // array of 8 reals (rare)
 
// realtime — synonym for real, used for time values
realtime t_start, t_end;             // typically nanoseconds (depends on `timescale)

Five properties baked into the keyword:

  • 64-bit IEEE 754 double-precision. Range approximately ±1.7e308 with 15–17 significant decimal digits of precision.
  • 2-state value system. Unlike reg / integer, real does not support X or Z. A real variable always holds a defined floating-point value (or one of the IEEE 754 special values: +0.0, -0.0, +inf, -inf, NaN).
  • Default initial value is 0.0. Different from reg / integer (which default to X). The 2-state representation has no "unknown" — every bit of the 64-bit representation has a defined value.
  • NOT synthesisable. No standard-cell library has floating-point cells; no synthesis tool can map a real to gates.
  • Restricted operator set. Many operators that work on reg / integer are illegal on real — see §4.

The realtime keyword is a synonym for real with the same semantics; the convention is to use realtime for variables that hold simulation time values (typically in nanoseconds or picoseconds, depending on the `timescale directive's time unit).

3. Mental Model

The mental-model has three practical consequences:

  • Real and integer arithmetic are different. Mixing the two in an expression triggers implicit conversion — usually integer-to-real promotion. The result is a real. Use $rtoi() (real-to-integer, truncation) or $itor() (integer-to-real) to make conversions explicit.
  • Don't use real for digital values. A real variable storing a "12-bit code" is a category error — the value is conceptually integer, the type is float. Use integer for codes, reg [11:0] for 12-bit registers, and reserve real for genuinely fractional quantities.
  • Floating-point arithmetic has its own pitfalls. Equality comparisons (a == b) on real values are unreliable due to representation precision — use abs(a - b) < epsilon instead. Accumulated rounding errors can produce surprising results over thousands of operations.

4. What real Cannot Do

The long list of restrictions. real is the most operator-restricted variable type in the language.

4.1 No bit-slicing

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x;
x[7:0]            // ILLEGAL — cannot slice a real
x[0]              // ILLEGAL — cannot index a bit of a real

The real variable is a single 64-bit float; the bit positions of the IEEE 754 representation are not directly accessible via Verilog bit-slice syntax. To access the bit representation, use the system function $realtobits(real_value) which returns a [63:0] reg containing the bits.

4.2 No bitwise operators

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x, y;
x & y             // ILLEGAL — bitwise AND on real
x | y             // ILLEGAL — bitwise OR on real
~x                // ILLEGAL — bitwise NOT on real
x ^ y             // ILLEGAL — bitwise XOR on real

Bitwise operators operate on the bit-level representation of an operand; real's bit representation is the IEEE 754 layout, which doesn't have meaningful bitwise semantics.

4.3 No reduction operators

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x;
|x                // ILLEGAL — reduction OR
&x                // ILLEGAL — reduction AND
^x                // ILLEGAL — reduction XOR

Same reason as bitwise — reduction operators require a bit-vector representation.

4.4 No shift operators

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x;
x << 1            // ILLEGAL — shift left
x >> 1            // ILLEGAL — shift right

For a real, "multiply by 2" is the right primitive (x * 2.0); shift operators have no meaning on floating-point.

4.5 No 4-state values

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x;
x = 1'bx;         // assignment to real with X — typically treated as 0.0
x = 1'bz;         // assignment to real with Z — typically treated as 0.0
 
x === 1.0;        // case-equality === on real is implementation-defined

The IEEE 1364 spec defines === (case equality) and !== (case inequality) only for 4-state types. Using them on real produces simulator-defined behaviour. Use == (logical equality) instead.

4.6 NOT synthesisable

The defining restriction. No synthesis tool can map a real declaration to gates. The synthesis tool errors out or warns and ignores the declaration. Code containing real must be in testbench files, analog models, or non-synthesised portions of the design hierarchy.

4.7 What real CAN do

The complement list — what real does support:

  • Arithmetic operators+, -, *, /, ** (power), % (modulo)
  • Comparison operators<, >, <=, >=, ==, !=
  • Conditional operator? :
  • Assignment= and <= (procedural; assign is not legal on real)
  • Math system functions$sqrt, $sin, $cos, $tan, $asin, $acos, $atan, $log, $ln, $exp, $pow, $floor, $ceil
  • Conversion system functions$rtoi, $itor, $realtobits, $bitstoreal
  • Display formatters%f, %e, %g in $display / $write / $monitor

The arithmetic-and-math vocabulary is exactly the working set for testbench analytics.

5. Type Conversions

Conversion between real and the discrete-integer types is the most common interop pattern. Three mechanisms:

5.1 Implicit conversion

Verilog converts implicitly in mixed expressions:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x;
integer i;
 
x = 1.5;
i = 3;
 
// Mixing real and integer — integer promotes to real
real y = x + i;        // y = 1.5 + 3.0 = 4.5 (i promoted to real)
 
// Assigning real to integer — truncates toward zero
integer j = x + 1.5;   // j = 3 (real 3.0 truncated; or rounded depending on tool)
 
// Assigning real to reg — truncates and width-converts
reg [3:0] r = x;       // r = 4'h1 (real 1.5 truncated to 1)

The implicit-conversion rules are spelled out in IEEE 1364-2005 §6.2.3 but are easy to mess up. The lint warning implicit real-to-integer conversion may lose precision is common.

5.2 Explicit conversion: $rtoi and $itor

The explicit forms make the intent unambiguous:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x = 3.7;
integer i;
 
i = $rtoi(x);          // explicit real-to-integer: i = 3 (truncates toward zero)
i = $rtoi(x + 0.5);    // round-half-up: i = 4
 
x = $itor(i);          // explicit integer-to-real: x = 4.0
x = $itor(i) * 0.5;    // x = 2.0

The $rtoi(x + 0.5) idiom is the canonical "round to nearest" — add 0.5 before truncating. For negative numbers, the truncation direction matters; use $rtoi(x < 0 ? x - 0.5 : x + 0.5) for symmetric round-half-up.

5.3 Bit-pattern conversion: $realtobits and $bitstoreal

For low-level interop — e.g., transmitting a real value across a [63:0] bus:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real         orig_value = 3.14159;
reg [63:0]   bus_value;
real         received_value;
 
bus_value = $realtobits(orig_value);    // get the 64-bit IEEE 754 representation
received_value = $bitstoreal(bus_value); // round-trip back to real

After round-trip, received_value exactly equals orig_value — the IEEE 754 representation is bit-exact. This is the pattern for passing real values through a bus interface in a multi-module testbench.

6. Visual Explanation

Three figures illustrate the real type's place in the language.

6.1 Visual A — type-system position

real sits in the variable family alongside reg and integer, but with a different value space (continuous floating-point) and a different synthesis story (none).

real — the simulation-only floating-point variable

data flow
real — the simulation-only floating-point variable5.2 Variablesprocedural-assignment targetsreg (4-state)synthesisable; flop/wire/latchinteger (4-state)synthesisable; 32-bit signedreal (2-state)NOT synthesisable; testbench only
Three variable types, two distinct value spaces. reg and integer use 4-state digital values (0, 1, X, Z); real uses 2-state IEEE 754 floating-point. The synthesis story splits the same way: reg and integer synthesise; real does not.

6.2 Visual B — IEEE 754 layout

A real variable's 64 bits are laid out per IEEE 754 double-precision. One sign bit, 11 exponent bits, 52 mantissa bits. The bit-level layout is accessible only via $realtobits(); bit-slice syntax is not legal on real directly.

IEEE 754 double-precision bit layoutBit 63sign (1 bit)Bits 62:52exponent (11 bits)Bits 51:0mantissa (52 bits)(-1)^s × 2^(e-1023) ×(1.m)interpreted value12
IEEE 754 double-precision: 1 sign bit + 11 exponent bits + 52 mantissa bits = 64 bits total. Range approximately ±1.7e308 with 15-17 significant decimal digits of precision. Verilog's real keyword stores values in this exact format; $realtobits() exposes the bits as a [63:0] reg, $bitstoreal() converts back.

6.3 Visual C — the synthesis story

A real declaration produces no hardware. Synthesis tools reject real types and either error out or emit a warning and ignore the declaration. The keyword's home is testbench code.

real and the synthesis toolreal x;declarationsynthesis toolrejects real typetestbenchreal lives hereanalog modelAMS/Verilog-A interop12
real declarations in synthesisable RTL produce synthesis errors. The keyword is restricted to non-synthesised contexts — testbench initial / always blocks, analog mixed-signal models, behavioural models that get replaced before synthesis.

7. The Sine-Wave Generator Pattern

The canonical testbench-analytics use case. A testbench needs to generate a sine-wave stimulus voltage that varies smoothly over time.

tb/sine_stimulus.v — sine-wave voltage generator
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`timescale 1ns/1ps
`default_nettype none
 
module tb_adc_sine;
    parameter real PI         = 3.14159265358979;
    parameter real AMPLITUDE  = 1.0;             // ±1 V swing
    parameter real OFFSET     = 1.5;             // 1.5 V DC offset
    parameter real FREQ_HZ    = 1.0e6;            // 1 MHz sine wave
    parameter real T_STEP     = 1.0e-9;           // 1 ns per simulation step
 
    real v_in;                                    // current input voltage
    real t_now;                                   // current simulation time in seconds
    integer t_step;                               // step counter
 
    real expected_code_r;
    integer expected_code_i;
    reg [11:0] dut_output;                        // captured from DUT
 
    initial begin
        t_step = 0;
        t_now = 0.0;
 
        forever begin
            #1;
            t_step = t_step + 1;
            t_now = $itor(t_step) * T_STEP;
 
            // Sine-wave voltage: V = AMPLITUDE * sin(2π * f * t) + OFFSET
            v_in = AMPLITUDE * $sin(2.0 * PI * FREQ_HZ * t_now) + OFFSET;
 
            // Expected 12-bit ADC code (assuming V_ref_neg=0, V_ref_pos=3.3V):
            //   code = round((v_in - V_ref_neg) / V_ref_range * 2^12 - 0.5)
            expected_code_r = (v_in - 0.0) / 3.3 * 4095.0;
            expected_code_i = $rtoi(expected_code_r + 0.5);
 
            // Apply v_in to the DUT (analog modelling — DUT samples on its own clock)
            // ... apply v_in to DUT.v_input, sample dut_output ...
 
            // Compare against expected code
            if ((dut_output > expected_code_i + 2) || (dut_output < expected_code_i - 2))
                $display("ADC error at t=%t: v_in=%f, exp=%0d, got=%h",
                         $realtime, v_in, expected_code_i, dut_output);
        end
    end
endmodule

Five real variables (PI, AMPLITUDE, OFFSET, FREQ_HZ, T_STEP, v_in, t_now, expected_code_r) plus one integer (expected_code_i) plus one reg [11:0] (dut_output). The real types carry the analog-domain values; the integer carries the digital expected-code; the reg carries the DUT output. The boundary between domains uses $itor() and $rtoi() for explicit conversion.

The pattern scales — analog mixed-signal testbenches typically have dozens of real variables (voltage references, gain coefficients, offset trims) and a handful of bridge variables that cross the analog/digital interface.

8. The Statistical Analysis Pattern

The second canonical use. After running thousands of test vectors, compute statistical metrics for the test report.

tb/statistical_analysis.v — RMS error and standard deviation
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`timescale 1ns/1ps
`default_nettype none
 
module tb_dac_stats;
    real    error_sum;          // accumulator for mean computation
    real    error_sq_sum;       // accumulator for variance computation
    real    error_max_abs;      // max absolute error
    real    error_min;          // min (most negative) error
    real    error_max;          // max (most positive) error
    integer sample_count;
 
    real    current_error;
    real    mean_error;
    real    std_dev_error;
    real    rms_error;
 
    initial begin
        error_sum     = 0.0;
        error_sq_sum  = 0.0;
        error_max_abs = 0.0;
        error_min     =  1.0e30;
        error_max     = -1.0e30;
        sample_count  = 0;
    end
 
    task automatic record_error(input real e);
        begin
            current_error = e;
            error_sum     = error_sum + e;
            error_sq_sum  = error_sq_sum + e * e;
            if (e < error_min) error_min = e;
            if (e > error_max) error_max = e;
            if ((e > 0.0 ? e : -e) > error_max_abs)
                error_max_abs = (e > 0.0 ? e : -e);
            sample_count = sample_count + 1;
        end
    endtask
 
    task automatic report_stats;
        begin
            mean_error    = error_sum / $itor(sample_count);
            rms_error     = $sqrt(error_sq_sum / $itor(sample_count));
            std_dev_error = $sqrt(error_sq_sum / $itor(sample_count)
                                   - mean_error * mean_error);
 
            $display("==================== STATS ====================");
            $display("  Samples:        %0d",    sample_count);
            $display("  Mean error:     %f LSB",  mean_error);
            $display("  RMS error:      %f LSB",  rms_error);
            $display("  Std deviation:  %f LSB",  std_dev_error);
            $display("  Max abs error:  %f LSB",  error_max_abs);
            $display("  Min error:      %f LSB",  error_min);
            $display("  Max error:      %f LSB",  error_max);
            $display("================================================");
        end
    endtask
endmodule

The arithmetic uses +, -, *, /, $sqrt, and the comparison operators — all legal on real. The accumulators (error_sum, error_sq_sum) drift as samples accumulate; for hundreds of thousands of samples, the rounding error in error_sq_sum may be measurable. For very-precise statistics, use Welford's online algorithm or Kahan summation — both implementable in pure-Verilog real code.

The task-and-procedure structure here is the canonical scoreboarding pattern for any DUT producing numerical output (ADC, DAC, filter, FFT, equaliser).

9. The Timing Extraction Pattern

The third canonical use — measuring delay between two events in simulation time:

tb/timing_measurement.v — measure clk-to-q delay
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
`timescale 1ns/1ps
 
module tb_clk_to_q;
    realtime t_clk_edge, t_q_change, delay_clkq;
    integer  sample_count;
    real     delay_min, delay_max, delay_sum;
 
    initial begin
        delay_min = 1.0e30;
        delay_max = 0.0;
        delay_sum = 0.0;
        sample_count = 0;
    end
 
    // Record the time at every posedge clk
    always @(posedge dut.clk) t_clk_edge = $realtime;
 
    // Record the time at every change of dut.q, then compute delay
    always @(dut.q) begin
        t_q_change = $realtime;
        delay_clkq = t_q_change - t_clk_edge;       // delay in current time units
        if (delay_clkq > 0.0 && delay_clkq < 100.0) begin
            // Only record if the change is plausibly clock-to-q (within 100 ns)
            if (delay_clkq < delay_min) delay_min = delay_clkq;
            if (delay_clkq > delay_max) delay_max = delay_clkq;
            delay_sum = delay_sum + delay_clkq;
            sample_count = sample_count + 1;
        end
    end
 
    final begin
        if (sample_count > 0)
            $display("Clk-to-Q: min=%f, max=%f, avg=%f (over %0d samples)",
                     delay_min, delay_max, delay_sum / $itor(sample_count), sample_count);
    end
endmodule

$realtime returns the current simulation time as a real (in the timescale's primary unit — ns in the example's `timescale 1ns/1ps). The arithmetic on realtime values is straightforward; the result is a delay in nanoseconds. This pattern is the foundation of every post-silicon-style timing extraction in pure Verilog simulation.

10. Simulation Behavior

A real is stored as 64 bits of IEEE 754 double-precision data. Arithmetic operations use the host platform's floating-point unit (typically x86 SSE or ARM NEON) at native double-precision speed.

11. Waveform Analysis

A waveform showing a real variable's value over time — the sine-wave-stimulus example:

real v_in — sine-wave stimulus voltage over time

12 cycles
real v_in — sine-wave stimulus voltage over timet=0: v_in starts at OFFSET (1.5 V)t=0: v_in starts at OF…Peak: v_in = OFFSET + AMPLITUDE = 2.0Peak: v_in = OFFSET + …Trough: v_in = OFFSET - AMPLITUDE = 1.0Trough: v_in = OFFSET …clkv_in1.51.71.92.01.91.71.51.31.11.01.11.3v_labelOFFSET+0.2+0.4+0.5+0.4+0.2OFFSET-0.2-0.4-0.5-0.4-0.2t0t1t2t3t4t5t6t7t8t9t10t11
The 'real' value of v_in traces a sine wave centered at OFFSET (1.5 V) with amplitude AMPLITUDE (0.5 V swing). Waveform viewers display real values as numeric labels (not 0/1 transitions); each cycle's value is shown explicitly. This is the canonical analog-domain waveform — values are continuous floating-point, not discrete digital.

Real values in waveform viewers are typically displayed as numeric labels next to each transition. Some viewers can plot real values as an analog "filled line" graph, making sine waves and ramps visible as continuous curves; others show only the discrete labels per cycle.

12. Synthesis Behavior

real is not synthesisable. Every modern synthesis tool rejects real declarations with an explicit error:

ToolBehavior
Synopsys Design CompilerError: "Unsupported data type 'real' at variable 'x'." Compilation fails.
Cadence GenusError: "Real type not supported in synthesizable Verilog."
Xilinx VivadoWarning + ignore: "Real-type variable 'x' is not synthesizable; ignoring."
Intel QuartusError: "Floating-point types are not supported in synthesizable Verilog."
Yosys (open-source)Error: "real declaration in synthesizable context."

The narrow exception is parameters declared as real — many synthesis tools accept parameter real PI = 3.14159; because the parameter is a compile-time constant that gets folded into other arithmetic. The value cannot survive as a runtime variable; it must be consumed by another compile-time expression that ultimately produces an integer-typed result.

13. Industry Use Cases

Three patterns where real is the right tool.

13.1 Analog mixed-signal modelling

AMS / Verilog-A testbenches model continuous-time signals (voltages, currents, charge) as real variables. The discrete-time digital DUT is sampled on the testbench clock; the continuous-time analog values drive the DUT's analog inputs through behavioural models. Every analog testbench has dozens of real declarations for voltage references, currents, gain coefficients, offset trims, and time-varying stimulus.

13.2 Statistical analysis in regression testbenches

Production regression testbenches frequently compute pass/fail criteria based on statistical metrics — RMS error, standard deviation, signal-to-noise ratio, total harmonic distortion. The computation uses real arithmetic accumulating over thousands of samples. The $sqrt, $sin, $log system functions cover most statistical math; the rest is +, -, *, /.

13.3 Timing extraction and SDF back-annotation

Post-synthesis gate-level simulations often measure timing properties — setup time, hold time, clock-to-Q delay, propagation delay through critical paths — using realtime variables to capture $realtime at each event. The results feed into SDF (Standard Delay Format) annotation files that drive static timing analysis.

14. Common Mistakes

Five pitfalls that catch engineers using real.

14.1 Using real in synthesisable RTL

The most common mistake. A junior engineer writes real coefficient = 0.5; in an RTL module to scale a signal — and the synthesis tool errors out. The fix is fixed-point: localparam [15:0] COEFF_FP = 16'h8000; (= 0.5 in Q1.15 format), then implement the multiplication as (signal * COEFF_FP) >>> 15.

14.2 Bit-slicing a real

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x = 1.5;
reg [7:0] r = x[7:0];           // ILLEGAL — cannot slice a real

The compiler errors out. The fix is to convert to integer first, then slice: reg [7:0] r = $rtoi(x)[7:0]; (though the typecast may also produce a width-mismatch warning — bit-slice the conversion result through an intermediate integer).

14.3 Equality comparison on real

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real a = 0.1 + 0.2;
real b = 0.3;
if (a == b) ...                  // FALSE — floating-point representation differs

IEEE 754 representation makes exact equality between independently-computed values unreliable. The fix is abs(a - b) < epsilon for some small epsilon (typically 1e-9 for double-precision):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real epsilon = 1e-9;
if ((a - b > 0 ? a - b : b - a) < epsilon) ...      // approximately equal

Or use the convention if ($abs(a - b) < epsilon) if your simulator supports $abs (a 1364-2005 system function).

14.4 Forgetting that real is 2-state

real cannot be X or Z. A real variable assigned from a 4-state expression containing X is typically converted to 0.0, but the behaviour is simulator-defined. For a testbench that needs to track "the DUT output was X" — keep the variable as reg, not real.

14.5 Mixing real and integer without explicit conversion

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real    x = 1.5;
integer i;
i = x;                            // implicit conversion — i = 1 (truncates toward zero)
i = $rtoi(x);                     // explicit, same result
i = $rtoi(x + 0.5);                // explicit, round-half-up: i = 2

The implicit form works but produces a lint warning (implicit real-to-integer conversion may lose precision). The explicit forms with $rtoi() and $itor() are clearer and lint-clean.

15. Debugging Lab

Three real-type debug post-mortems

16. Coding Guidelines

  1. Use real for testbench analytics. Voltage references, gain coefficients, statistical accumulators, RMS error, sine-wave stimulus — anywhere fractional arithmetic is needed.
  2. Never declare real in synthesisable RTL. Synthesis tools reject it. Use fixed-point arithmetic or instantiated floating-point IP for hardware FP.
  3. Use $rtoi() and $itor() for explicit type conversion. Implicit conversion works but produces lint warnings.
  4. Don't compare real values with ==. Use abs(a - b) < epsilon for approximate equality.
  5. Use realtime for time values. Conventionally distinguishes "this is a time in ns/ps" from "this is just any float."
  6. Use %f / %e / %g for display. %d is for integers; %h is for hex; %f shows fixed-point notation, %e shows scientific, %g picks whichever is more readable.
  7. Initialise real variables at declaration. Default 0.0 is usually correct, but explicit initial values document intent.
  8. For long accumulators, use Kahan summation. Especially for sums over millions of iterations where drift matters.

17. Interview Q&A

18. Exercises

Three exercises that turn the real type into a working-engineer reflex.

Exercise 1 — Identify the legality

For each of the following expressions or statements, predict: legal or illegal. If illegal, name the rule violated.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real x = 1.5;
real y = 2.5;
 
(a) x + y               // ?
(b) x & y               // ?
(c) x == y              // ?
(d) x === y             // ?
(e) x[7:0]              // ?
(f) $sin(x)             // ?
(g) x << 1              // ?
(h) x * 2.0             // ?

Hints. Arithmetic / math / comparison legal. Bit-slice / bitwise / shift / case-equality illegal.

Exercise 2 — RMS error calculation

Write a Verilog testbench task that takes a real-valued error array err[0:N-1] and an integer N, and computes/displays the RMS error. Use the standard formula: RMS = sqrt(mean(err^2)).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
task automatic compute_rms(input real err [0:N-1], input integer N);
    // your code here
endtask

Hints. Sum err[i]^2 for i = 0 to N-1 into a real accumulator. Divide by N (cast N to real with $itor()). Take $sqrt(). Print with %f format.

Exercise 3 — Identify synthesizability

For each module, predict whether it will pass synthesis. If not, explain why and propose a synthesis-friendly rewrite.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// (a)
module a (input wire [11:0] in, output reg [11:0] out);
    parameter real GAIN = 1.5;
    real x;
    always @(*) begin
        x = $itor(in) * GAIN;
        out = $rtoi(x);
    end
endmodule
 
// (b)
module b (input wire [11:0] in, output wire [11:0] out);
    assign out = in + (in >> 1);   // multiplies by 1.5 using shift-add
endmodule
 
// (c)
module c (input wire [11:0] in, output wire [11:0] out);
    localparam [11:0] GAIN_X2 = 12'h3;   // gain factor of 3 (2x of 1.5)
    assign out = (in * GAIN_X2) >> 1;     // multiply by 3, divide by 2
endmodule

Hints. (a) uses real and $itor/$rtoi — these are testbench-only. (b) uses shift-add — synthesisable. (c) uses integer multiplication and shift — synthesisable. Compare the area / accuracy trade-offs.

19. Summary

real is Verilog's 64-bit IEEE 754 double-precision floating-point variable — the language's tool for testbench analytics, analog mixed-signal modelling, and timing-extraction post-processing.

The properties:

  • 64-bit double-precision. Range ±1.7e308, 15-17 significant digits.
  • 2-state. No X, no Z. Default initial value is 0.0.
  • NOT synthesisable. Synthesis tools reject real declarations.
  • Restricted operator set. No bit-slice, no bitwise, no reduction, no shift, no case-equality. Arithmetic / comparison / math system functions are legal.
  • realtime is a synonym. Conventionally used for time values.

The canonical use cases:

  • Analog stimulus generation. Sine waves, ramps, voltage references.
  • Statistical analysis. RMS error, standard deviation, accumulator metrics over thousands of samples.
  • Timing extraction. $realtime-based delay measurement.
  • Analog mixed-signal modelling. Voltage and current signals in AMS testbenches.

The cases where real is wrong:

  • Synthesisable RTL. Use fixed-point or vendor floating-point IP instead.
  • Digital code values. Use integer for codes; use reg [N-1:0] for registers.
  • Bit-level manipulation. No bit-slice, no bitwise — use reg or integer for those.

The day-to-day discipline:

  • real for testbench analytics. Period.
  • $rtoi() and $itor() for explicit conversion. Implicit conversion works but produces lint warnings.
  • Don't use == for real equality. Use abs(a - b) < epsilon.
  • Use %f, %e, %g for display. %d is for integers.
  • Initialise at declaration when intent matters. Default 0.0 is correct but explicit values document the testbench setup.
  • For long accumulators, consider Kahan summation. Floating-point drift over millions of operations is a real concern.

The next sub-page is 5.2.4 Scalar vs Vector vs Arrays — the dimensions every variable can take. After 5.2.4, Section 5.2 closes and Chapter 6 picks up with constant variables (parameter / localparam).

  • integer — Chapter 5.2.2; the 32-bit signed sibling that contrasts with real.
  • reg — Chapter 5.2.1; the workhorse variable type that real cannot replace.
  • Register Data Types — Chapter 5.2; the parent overview that frames this sub-topic.
  • Number Representation — Chapter 4.4; literal syntax including real-valued constants.
  • Variables & Data Types — Chapter 5; nets and variables together.