Getting started

To try Yodl directly in your browser, visit the playground.

Installation

The simplest way to get yodl is to install the bundled npm package:

$ npm install --global yodl
$ yodl examples/Hello.yodl "write_firrtl Hello.fir"

.fir files can then be converted to SystemVerilog using firtool (tested with version 1.111.1).

Feature support for SystemVerilog/Verilog differs from tool to tool, check this page to customise the output. When using Yosys for instance, specify --lowering-options=disallowPackedArrays,disallowLocalVariables,emitBindComments.

firtool --format=fir --verilog Hello.fir -o Hello.sv

The project can also be compiled to wasm or wasm-gc by installing Moonbit and running:

$ git clone https://github.com/nathsou/yodl
$ cd yodl
$ moon build --target wasm-gc
$ moon run src/main examples/Hello.yodl "write_firrtl Hello.fir"

Editor support

Visual Studio Code

A syntax-highlighting extension is embedded in the repository, to install it, do:

  1. Open the command palette (Ctrl | Cmd + Shift + P)
  2. Select 'Developer: Install Extension from Location'
  3. Open 'extensions/yodl-vscode-syntax'

Your first Yodl design

Create a file called Blink.yodl and insert the following text:

module Top(
  // inputs
  clk: clock,
  rst: bool,
) -> (
  // outputs
  leds: uint<8>,
) {
  let counter = Reg<uint<24>>(clk, rst)
  counter.d = counter.q + 1'd1
  leds = counter.q[23:16]
}

This simple design creates a 24-bit counter and displays the 8 most-significant bits to the output leds port.

To convert this Yodl design to FIRRTL:

moon run src/main Blink.yodl "write_firrtl Blink.fir"

Which should output:

FIRRTL version 4.1.0
circuit Top:
  public module Top:
    input clk: Clock
    input rst: UInt<1>
    output leds: UInt<8>

    wire counter: { flip d: UInt<24>, q: UInt<24> }
    regreset reg_0: UInt<24>, clk, rst, UInt<24>(0)
    connect counter.q, reg_0
    connect reg_0, counter.d
    connect counter.d, counter.q
    node temp_1 = bits(add(counter.q, UInt<1>(1)), 24, 0)
    connect counter.d, temp_1
    node temp_2 = bits(counter.q, 23, 16)
    connect leds, temp_2

Now to generate a SystemVerilog file:

firtool --format=fir -O=release --verilog \
      -disable-all-randomization -strip-debug-info \
      --lowering-options=disallowPackedArrays,disallowLocalVariables \
      Blink.fir -o Blink.sv 

Which should output a file similar to:

// Generated by CIRCT firtool-1.105.0
module Top(
  input        clk,
               rst,
  output [7:0] leds
);

  reg [23:0] reg_0;
  always @(posedge clk) begin
    if (rst)
      reg_0 <= 24'h0;
    else
      reg_0 <= reg_0 + 24'h1;
  end // always @(posedge)
  assign leds = reg_0[23:16];
endmodule