C⏚ v2.0.0Updated 2026-05-12·Language

Introduction

C⏚ is a programming language that compiles to digital hardware.

You write a sequential program. The compiler emits synthesizable Verilog or VHDL, and the same source also runs in a fast cycle-accurate simulator. There is no hand-rolled FSM, no blocking versus non-blocking assignment, no signal-strength bookkeeping. What you write is what the synthesizer gets.

This chapter gives you the mental model. The Quick tutorial walks you through building a design end to end.

A program that becomes a chip

Here is a complete 9-line C⏚ task, and the Verilog the compiler emits from it:

A 9-line Counter task in C⏚ next to its generated Verilog module

The left column is what you write. The right column is what your FPGA toolchain consumes.

Nothing is hidden. The state variable value becomes a Verilog reg. The count.write(value) call becomes a registered output with a paired count_valid strobe. The cycle break between iterations of loop() becomes a named FSM block in the always process. If you can read RTL, you can audit what the compiler did.

The mental model

Digital hardware is built from two ingredients on a shared clock:

  • Registers capture a value on the clock's rising edge.
  • Combinational logic computes the next value from the current one.

A C⏚ task maps directly onto this picture. Every state variable becomes a register. Every expression between reads and writes becomes combinational logic. One pass through loop() is one clock cycle.

The Counter task as hardware: value register, +1 adder, count output register

Tasks communicate only through ports. State variables are private. A keyword on each port declaration selects the handshake:

  • push - registered output with a valid strobe.
  • stream - push plus ready/valid back-pressure.
  • confirm - push plus consumer acknowledgement.
  • (bare) - combinational wire, no handshake.

See Declarations for the full reference.

Networks compose tasks into hierarchies. They contain no behaviour of their own, only structural wiring. The Intel-8088 reference CPU is a C⏚ network with two top-level instances - ExecutionUnit and BusInterfaceUnit - wired through real push and stream ports.

That is the whole model: tasks, networks, ports, on a clock.

One source, two simulations

The C⏚ compiler emits the same design two ways from the same intermediate representation:

Pipeline: source compiles to IR, then to either JVM bytecode or to Verilog/VHDL

JVM bytecode is the fast path. Every task becomes a Java method, every network becomes a clock-scheduled class. The resulting .class files run cycle-accurately on the JVM. Actual throughput depends on the design shape, host machine, JVM, and whether waveform generation is enabled.

Verilog and VHDL are the synthesis path. The compiler emits RTL designed to be readable and synthesizer-friendly - one module per task, one per network. Exact downstream requirements still depend on the target toolchain and device family.

Both outputs read the same intermediate representation. Behaviour in the fast simulator matches behaviour in synthesis.

For higher-confidence verification, you run the same testbench through both paths. The bytecode trace and the HDL trace should agree cycle for cycle. When they disagree, it is a compiler bug or a design ambiguity worth resolving. Either way, you find it before silicon.

The Intel-8088 reference IP is used internally as a realistic regression target. It exercises both bytecode simulation and HDL cross-checking, and it is a good example of the workflow at non-trivial scale.


Next: the Quick tutorial builds a Counter end to end. The Bytecode simulator chapter explains how the fast simulator is wired up, and Tasks and Networks cover the language constructs in depth.