Cyclicity CDL Language Specification - Details

Gavin J Stark
April 14th 2004

This section contains more focussed points on particular aspects of the language, their semantics, and their purpose and use.


This section discusses issues to do with types in the language

Supported types

The language supports some basic types, and then supports derived types also. The basic types are described in the next section; the derived types are examined here in overview.

The derived types may be one of:

  1. an enumeration of a sized bit vector

  2. a finite state machine (with defined encoding, or unspecified encoding, or specified as one hot, one cold)

  3. a structure consisting of one or more named elements, each of which can be any defined type

  4. an array of types

  5. a type reference

Enumerations require a size of bit vector to be specified, and then items of that enumeration will all have that bit vector size.

Finite state machine types are again sized bit vectors, basically. They are defined as a set of states, whose assignments to bit vector values may be given explicitly. Alternatively they may be assigned bit vector values automatically, and this may be done in a simple incrementing fashion, or one hot or one cold. Furthermore, each state can have documentation with it, which should be used to document the design of the state machine, and each state may also define potential 'predecessor' states and 'successor' states, which the language implementers may check statically or dynamically for correctness.

Structures are very similar to C structures. They contain a number of elements, each of which is assigned a name, and each of which may be of any defined type. Structures are very important inside CDL; they are a very good mechanism for writing code that is clear in intent.

Arrays of types are supported as in C, with one vital exception. Multidimensional arrays are not supported. The basic type of the bit vector is not an array as such, and so arrays of bit vectors are supported. But no array may resolve down to an array of array of bit vectors.

Type references are transparent type references provided for code clarity only; they are not tightly defining. For example, one could define 'short' to be a bit vector of size 16, and declare a combinatorial variable to be of type 'short'. This will actually make that variable a bit vector of size 16 internally; the type reference is just transparent.

Basic types: sized and unsized bit vectors and strings

The language supports three basic types for expressions:

  1. Sized bit vectors; these are effectively arrays of bits of length 1 upwards.

  2. Unsized bit vectors; these are arrays of bits of a compile-defined maximum length, which can be implicity converted to any size of sized bit vector.

  3. Strings.

Strings are hardly used as yet.

The fundamental difference between unsized and sized bit vectors is in casting: sized bit vectors cannot be implicitly cast to be a bit vector of another size, that cast would have to be done explicitly by bundling or bit extraction; unsized bit vectors may be implicitly cast to a bit vector of any size.

As an explicit example: 5+8, 3+4h2, and 6b110011+6h0f are valid expressions, as the types all match or may be implicitly cast. But 4h2+3h5 is not a valid expression, as the types of the two operands are both sized bit vectors, but of different size.


Enumerations are a type, and unlike in C they are only available as a type. This means that a signal may be given an enumeration type, and it may then only be assigned values within that enumeration type.

As an example, if there is an enumeration:

typedef enum [2] { one=1, two=2 } small;

And if there is a combinatorial variable:

comb small my_small;

Then the only two valid assignments to my_small are one and two

my_small = one; or
my_small = two;

To implement this the language imposes type scoping on every expression; see the discussion of expressions below.


This section discusses issues to do with expressions in the language


Implicit casting is performed to convert the type of an expression to that requried by its context. Each expression in the language has a type context which can be determined from the position of the expression in the code.

Explicit casting is not currently possible; it will be, when a syntax for that has been derived.


This section discusses issues to do with lvars in the language


When a bit vector is subscripted in Cyclicity CDL it must produce another bit vector of a compile-time size. This means that when subscripting is used to generate a sized bit vector, the size must be a compile time constant. So the following is valid:

foo <= bar[ 5; jim ]; // This is valid

whereas the following is not

comb bit[2] joe;
foo <= bar[ joe; 0 ]; // This is NEVER valid


Unlike in Verilog, where a bundle may be used as an lvar, lvars in Cyclicity CDL cannot be bundles. Where a bundle would be used in Verilog an additional combinatorial value may be required. For example, in verilog:

reg carry, result[30], a[31], b[31];
{carry, result} = a+b;

would require something like:

comb bit[31] a_b_sum;
a_b_sum = a+b;
carry   = a_b_sum[30];
result  = a_b_sum[30;0];

This makes the language simpler to interpret from a compiler perspective, but it can also improve the comprehensibility of code; in the CDL code it is much easier to see that the signals are of the correct width, and what the code is actually doing.

Main links Logo

Site map