Fixed-Point Fields#

Fixed-point numbers can be used to efficiently represent real numbers using integers. Fixed-point numbers consist of some combination of integer bits and fractional bits. The number of integer/fractional bits is usually implicitly tracked (not stored) for each number, unlike for floating-point numbers.

For this Rust exporter, the number of integer/fractional bits is tracked by the type system using const generics on the FixedPoint type.

Properties#

Fields can be declared as fixed-point numbers using the following two properties:

property intwidth {
    type = longint unsigned;
    component = field;
};

property fracwidth {
    type = longint unsigned;
    component = field;
};

The is_signed property can be used in conjunction with these properties to declare signed fixed-point fields.

These UDP definitions, along with others supported by PeakRDL-regblock, can be enabled by compiling the following file along with your design: udps.rdl.

intwidth
  • The intwidth property defines the number of integer bits in the fixed-point representation (including the sign bit, if present).

fracwidth
  • The fracwidth property defines the number of fractional bits in the fixed-point representation.

Representable Numbers#

The range of representable real numbers is summarized in the table below.

Representable Numbers#

Signedness

Minimum Value

Maximum Value

Step Size

Unsigned

\(0\)

\(2^{\mathrm{intwidth}} - 2^{-\mathrm{fracwidth}}\)

\(2^{-\mathrm{fracwidth}}\)

Signed

\(-2^{\mathrm{intwidth}-1}\)

\(2^{\mathrm{intwidth}-1} - 2^{-\mathrm{fracwidth}}\)

\(2^{-\mathrm{fracwidth}}\)

Rust Types#

The exporter generates a FixedPoint type with const generics for the number of integer bits and fractional bits. This type is returned/accepted by the field’s getter and setter methods. The purpose of this type is to enforce type safety (i.e., not accidentally setting the field to a normal integer value) and provide convenient conversion functions between float types and fixed-point numbers.

The fixed crate is not used because it has two limitations with respect to SystemRDL:

  • The bit width of the fixed-point type is limited to the widths of Rust integer primitives.

  • A negative number of integer or fractional bits is not allowed.

Conversion functions between FixedPoint and the types provided by the fixed crate may be implemented in the future.

Other Rules#

  • Only one of intwidth or fracwidth need be defined. The other is inferred from the field bit width.

  • The bit width of the field shall be equal to intwidth + fracwidth.

  • If both intwidth and fracwidth are defined for a field, it is an error if their sum does not equal the bit width of the field.

  • Either fracwidth or intwidth can be a negative integer. Because SystemRDL does not have a signed integer type, the only way to achieve this is to define one of the widths as larger than the bit width of the component so that the other width is inferred as a negative number.

  • The properties defined above are mutually exclusive with the counter property.

  • The properties defined above are mutually exclusive with the encode property.

Examples#

A 12-bit signed fixed-point field with 4 integer bits and 8 fractional bits can be declared with

field {
    sw=rw; hw=r;
    intwidth = 4;
    is_signed;
} fixedpoint_num[11:0] = 0;

This field can represent values from -8.0 to 7.99609375 in steps of 0.00390625.