Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Modules

Modules are the current top-level unit in Ted. Hardware modeling uses ports and event handlers, but core code can live inside modules without any timing.

Module Declaration

mod module_name {
    // ports
    // internal signals
    // logic
}

Ports

Ports define the module’s interface for hardware modeling:

mod example {
    in  clock: bit,           // input port
    out data: u8,             // output port
    inout bus: u32,           // bidirectional port
}

Port Directions

DirectionDescription
inInput - read only inside module
outOutput - write only inside module
inoutBidirectional - read and write

Port Types

Ports must have explicit types:

in single_bit: bit,
in byte_value: u8,
in wide_bus: u64,

Ports are convenience syntax for temporal values; they can be modeled as library types like Signal<Bit, Out>.

Internal Signals

Signals declared without direction are internal:

mod counter {
    in  clk: bit,
    out count: u8,

    // Internal signal
    let overflow: bit = 0;

    on rising(clk) {
        if count == 255 {
            overflow = 1;
        }
        count = count + 1;
    }
}

Timed Contexts

on handlers and module-level loop blocks are timed contexts. @ is only legal inside them; helper code outside remains ordinary core Ted.

TODO: Add explicit timed task declarations and timed fn for timed code outside modules.

Module Instantiation

Instantiate modules within other modules:

mod top {
    in  clk: bit,
    out led: bit,

    // Instantiate a counter
    counter my_counter {
        clk: clk,
        count: _, // unconnected
    };

    // Use counter output
    led = my_counter.overflow;
}

TODO: Define the exact semantics of module-level assignments (for example, continuous assignment vs event-driven evaluation).

Connection Syntax

module_type instance_name {
    port_name: signal,
    another_port: another_signal,
};

Use _ for unconnected ports.

Parameterized Modules

Modules can have parameters:

mod counter<WIDTH: u32 = 8> {
    in  clk: bit,
    out count: uint<WIDTH>,

    on rising(clk) {
        count = count + 1;
    }
}

// Instantiate with custom width
counter<16> wide_counter { ... };

Module Hierarchy

Modules can contain other modules:

mod system {
    in clk: bit,

    // Connect them
    let bus: u32;
    cpu processor { clk: clk, data_out: bus };
    memory ram { clk: clk, data_in: bus };
}

Visibility

By default, all ports are visible. Use _ prefix for internal implementation details:

mod example {
    out result: u8,      // Public
    let _temp: u8,       // Private (convention)
}