HardCaml, Gates and All!
HardCaml is a recently introduced library by Andy Ray for writing RTL hardware descriptions. For those familiar with hardware development, it serves a similar purpose to VHDL and Verilog but brings some of the benefits of OCaml. HardCaml provides a range of simulation tools to allow you to develop and test your designs -- to explore this a bit further, a recent OCamlLabs intern, Chaitanya Mangla, spent some time with HardCaml "closing the loop" to get a simple circuit, described in HardCaml synthesised and running on a physical FPGA. This post is based on Chaitanya's notes and examples.
The first step is thankfully straightforward -- install HardCaml using OPAM:
$ opam install hardcaml
The basic workflow is then to
- describe your circuit using HardCaml,
- to compile this description using the OCaml compiler, and then
- to run the resulting binary
to produce a Verilog circuit description. To actually put this onto a physical board you then must run it through the Verilog synthesis tools -- this step will vary based on the specific hardware you are using. Chaitanya's example describes how to do this in detail using the Altera Quartus development tools to target the Altera Cyclone V SoC Development Kit (from now on, the SoCkit board). This is a prototyping board, with an ARM processor, memory, an FPGA, peripherals, and comes with development tools and examples.
Of State Machines and Circuits
The SoCkit has four keys and four LEDs -- the simple example used here programs
the FPGA on the board so that pressing `key0` turns on one of the LEDs, and
pressing `key1` turns it off. This also neatly sidesteps the problem of needing
to debounce the keypresses -- it does not matter if a single keypress by the
user actually generates multiple signals as any one of them will turn the LED on
or off (if
More precisely, the state machine described above is:
Which corresponds to the following circuit:
We next describe this circuit directly using HardCaml.
Show Me the Code!
open Core.Std open HardCaml.Signal.Comb open HardCaml.Signal.Seq
the combinatorial logic that handles keypresses of
let leds key0 key1 = let in0 = ~: key0 in let in1 = ~: key1 in reg_fb r_none empty 1 (fun d -> (d &: (~: in1)) |: ((~: d) &: in0) )
finally, tell HardCaml to generate Verilog output
let () = let key0 = input "key0" 1 in let key1 = input "key1" 1 in let circuit = HardCaml.Circuit.make "leds" [ output "q" (leds key0 key1) ] in HardCaml.Rtl.Verilog.write (output_string stdout) circuit
Andy Ray has written an extension to this example that uses some of the fancier features of HardCaml to describe the state machine.
Build this in the usual way, and run the resulting binary to generate the Verilog description:
$ ocamlfind ocamlc -linkpkg -thread -package hardcaml,core \ leds.ml -o leds.native $ ./leds.native > leds.v