inline-verilog
: Execute Verilog circuits from
HaskellLike for most of the past 13 years, early June meant attending ZuriHac. The event was as pleasant and well organized as ever.
While talking to Ed Kmett he half-jokingly mentioned that it would be useful to have a Verilog analogue of inline-c
, especially to test Verilog circuits against Haskell functions.
A few hours later I had inline-verilog
, which lets to do just that.
inline-verilog
allows you to embed “nameless” Verilog modules right in your Haskell:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Language.Verilog.Inline as V
import Data.Word
import Foreign.Marshal.Alloc (alloca)
import Foreign.Storable (peek)
V.verilog
adder :: Word16 -> Word16 -> IO (Bool, Word16)
= alloca $ \sum -> alloca $ \carry_out -> do
adder a b |
[V.blockmodule (
15:0] a,
input [15:0] b,
input [15:0] sum,
output [
output carry_out
);sum} = a + b;
assign {carry_out,
endmodule|]
<$> peek carry_out <*> peek sum
(,)
main :: IO ()
= print =<< adder 1 2 main
The example above will print (False,3)
.
Input and output arguments are expected to be present in the Haskell context in which the V.block
is called. The Haskell types for the input and outputs are automatically inferred from the Verilog code. The output arguments are expected to be pointers in which the outputs will be stored.
Verilog code can also be factored out within a Haskell file using V.verbatim
. See tests.hs
for a more complex example.
The way inline-verilog
works is by invoking verilator
to compile each Verilog block to C++, generating C stubs which execute the verilated circuit, and linking everything up with the Haskell executable.
There are some limitations, namely I haven’t implemented or tested:
struct
ports.reg [15:0] foo [3:0][3:0]
.All of the above should be easy, but it did not fit in the couple of hours it took to cook inline-verilog
to its current state.
Also, inline-verilog
does not make much sense for non-combinatorial circuits (i.e. stuff that does IO). But to test functional units, it should do the job.