THDL++ tutorial - basics

Next >>

What is THDL++?

THDL++ is a new generation hardware definition language, that provides the flexibility and scalability of C++ while having fully VHDL-compatible semantics. The key elements are, as in VHDL, entities, signals, processes and functions, but you can increase their flexibility exponentially by using inheritance, templates and policy classes. This tutorial covers all supported language features from the very basics up to advanced ones.

Requirements

To understand this tutorial, a basic knowledge of VHDL and C is required. It is also recommended to get familiar with C++ templates and policy classes before experimenting with advanced THDL++ features.

Entities, signals and processes

Let's start with creating a very trivial "divide input clock by 2" entity. Here is a sample VHDL code for that:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Divider_Entity is
Port (
Input_Clock : in std_logic;
Output_Clock : out std_logic
);

end entity Divider_Entity;

architecture Behavioral of Divider_Entity is
signal Temp_Clock : std_logic;

begin
    main : process (Input_Clock) is
    begin
        if rising_edge(Input_Clock) then
            Temp_Clock <= not Temp_Clock;
    end if;
   
    end process main;

Output_Clock <= Temp_Clock;

end architecture Behavioral;

Let's now create an equivalent entity in THDL++. Start VisualHDL, select "New Project", choose "empty project". Finally, choose "File->New Source File", type in "test" as the file name, and enter the following text in the editor:

entity DividerEntity
{
    port
    {
        in logic InputClock;
        out logic OutputClock;
    }

    signal logic TempClock = '0';    //Initial value is 0

    process main (InputClock.rising)
    {
        TempClock = !TempClock;
    }

    OutputClock = TempClock;
}

simulate_entity(DividerEntity);

The simulate_entity statement defines the root entity that is used when generating code for simulation. If you have Xilinx ISE toolchain installed, you can press F7 to build ISIM simulation model, or F5 to build and run it. If you don't have the Xilinx tools, simply press Ctrl+F7 to generate VHDL code and examine the generated .vhd files, that appear in the Project Explorer.

Note that you did not define any clock generation statements here, so, you won't see much in the simulator. To put some life into our example, remove or comment out the simulate_entity statement and add the following code to the end of the file:

entity ClockTest
{
    DividerEntity divider(
        InputClock = auto,
        OutputClock = auto
    );

    process GenerateClock ()
    {
        divider.InputClock = '0';
        wait(10ns);
        divider.InputClock = '1';
        wait(10ns);
    }
}

simulate_entity(ClockTest);

Formalization

Let's define the syntax for THDL++ entities, signals and processes formally. Please note that THDL++ supports both C++-style comments (//) and VHDL-style comments (--). Although no C-style comments (/*) are supported, you can easily comment/uncomment a block of lines by selecting them in VisualHDL editor and pressing the '/' key.

Entities

The general syntax for defining entities is the following:

entity EntityName
{
    //Entity contents
}

Entities can contain everything, that VHDL entities can: ports, signals, processes, implicit processes. Additionally, THDL++ entities can contain classes, functions, constants and typedefs. Unlike VHDL, there is no explicit requirement to list ports before signals; the THDL++ compiler automatically figures out the correct parsing order. Note that every THDL++ entity used in the design will be compiled to a corresponding VHDL entity having the same set of ports, signals and processes.

Signals and ports

Signals and ports can be declared using 2 syntax forms. Blocks:

signal
{
    TypeName SignalName;
    TypeName2 SignalName2[, SignalName3];
}

and independent declarations:

signal TypeName SignalName;

The port declarations are similar, but require explicit direction specification (in, out or inout).

Types

THDL++ supports all main VHDL data types, however, it uses C-style names:

THDL++ type Equivalent VHDL type
int integer
bool boolean
logic std_logic with unsigned operations
ulogic std_logic with unsigned operations
slogic std_logic with signed operations
void N/A
bool boolean

Vectors are defined almost like in C:

signal logic[size] SignalName1;
signal logic[index1 to index2] SignalName2;
signal logic[size1][size2] SignalName3;

Note that logic[N] is equivalent to VHDL std_logic_vector(N - 1 downto 0). Also, there is only one "to" keyword (unlike to/downto in VHDL).

Hint: you can make your code more readable by using typedefs. Here is an example:

entity TestEntity
{
    typedef logic[16] CodeWord;
    typedef CodeWord[8] ArrayType;

    port
    {
        in ArrayType Input;
        out ArrayType Output;
    }
}

Note that ArrayType can now be used from any entity using its full name. Example:

entity OtherEntity
{
    signal TestEntity.ArrayType MyArraySignal;
}

Processes

THDL++ signals and processes inherit the VHDL semantics. Moreover, every processes is compiled to exactly one VHDL process. Here is the syntax:

process ProcessName(SensitivityList)
{
    //Process body
}

The sensitivity list can either simply enumerate some signals, like in VHDL, or use one of special forms:

Sensitivity list syntax VHDL equivalent
SignalName.rising The resulting VHDL process will be sensitive to SignalName and its body will be enclosed into "if rising_edge(SignalName)" block.
SignalName.falling Similar to SignalName.rising
any The resulting VHDL process will be sensitive to ALL signals read from the process. THDL++ compiler will automatically generate the sensitivity list based on process body.

The process body syntax is very similar to C/C++ one. You can declare local variables at random places, you can use ++, +=, &=,^= and similar operators, you can use either single-statement or multiple-statement if and for statements. You can even use the foreach() statement to enumerate components or compile-time lists. The process body syntax is described in the next section.

Implicit processes

The implicit processes should be declared inside entities, exactly like in VHDL. Anything in the form of "signal = expression;" can be treated as an implicit process.

Assignment operators

Unlike VHDL, THDL++ does not enforce different assignment operators for signals and processes. The C-style '=' operator replaces them both. However, you can still use the VHDL-style ':=' and '<=' operators, if you want to enforce the signal/variable checks.

Next >>