Skip to content

Your First Circuit

In this tutorial, you’ll build a simple combinational circuit that performs basic logic operations.

A circuit that takes two 1-bit inputs a and b and outputs:

  • and_out - a AND b
  • or_out - a OR b
  • xor_out - a XOR b

First, we define what signals go in and out of our circuit:

module I = struct
type 'a t = { a : 'a; b : 'a }
[@@deriving hardcaml]
end
module O = struct
type 'a t = { and_out : 'a; or_out : 'a; xor_out : 'a }
[@@deriving hardcaml]
end

The [@@deriving hardcaml] attribute generates boilerplate code for us.

Now we write the actual circuit logic:

let create _scope (i : _ I.t) : _ O.t =
{ and_out = i.a &: i.b
; or_out = i.a |: i.b
; xor_out = i.a ^: i.b
}

Hardcaml provides operators for common logic operations:

  • &: - bitwise AND
  • |: - bitwise OR
  • ^: - bitwise XOR
  • ~: - bitwise NOT

Let’s verify our circuit works with all input combinations:

let%expect_test "logic_gates" =
let module Sim = Cyclesim.With_interface (Circuit.I) (Circuit.O) in
let sim = Sim.create (Circuit.hierarchical (Scope.create ())) in
let waves, sim = Waveform.create sim in
let inputs = Cyclesim.inputs sim in
(* Test all combinations *)
let test a b =
inputs.a := Bits.of_int ~width:1 a;
inputs.b := Bits.of_int ~width:1 b;
Cyclesim.cycle sim
in
test 0 0;
test 0 1;
test 1 0;
test 1 1;
Waveform.expect waves;
[%expect {| |}]
  1. Create a simulator from our circuit
  2. Wrap it with Waveform to capture signals
  3. Set inputs using inputs.signal := Bits.of_int ...
  4. Run cycles with Cyclesim.cycle sim
  5. Display results with Waveform.expect waves

Go to the IDE and:

  1. Replace the counter code with the logic gates implementation
  2. Click Run to see the waveform
  3. Verify AND, OR, XOR work correctly for all inputs