RTL Bench PRO

Write and simulate Verilog in your browser

RTL Bench elaborates Verilog and SystemVerilog with Yosys โ€” the same open-source synthesizer used by every open ASIC flow. Paste a module, click Generate, and you have a schematic, a simulation, and a timing number. No install, no Makefile, no toolchain setup.

The smallest module that does something

A 4-bit counter with an active-low reset. Paste this into the editor and click Generate.

module counter (
    input  logic       clk,
    input  logic       rst_n,
    output logic [3:0] q
);
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) q <= 4'h0;
        else        q <= q + 4'd1;
    end
endmodule
Run this in RTL Bench

The always_ff block is SystemVerilog. If you prefer classic Verilog, always @(posedge clk or negedge rst_n) works too โ€” Yosys parses both without complaint.

What Yosys accepts

Yosys is strict in some places and lenient in others. Here is what actually works in RTL Bench:

FeatureWorksNotes
module / endmoduleโœ…The standard container for everything.
always_ff, always_combโœ…SystemVerilog. Preferred over plain always.
logic typeโœ…SystemVerilog. Replaces wire/reg.
parameter, localparamโœ…Fully supported, including parameterised modules.
generate / for loopsโœ…Elaborated at synthesis time.
Packed / unpacked arraysโœ…Packed works cleanly. Unpacked is supported for memories.
function, taskโœ…Inlined at elaboration. Keep them small.
Structs and typedefsโœ…SystemVerilog packed structs work.
Interfacesโš ๏ธModule ports must be plain signals. Wrap interfaces as structs.
assert / assumeโŒIgnored โ€” Yosys has no assertion layer. Use $display.
Classes and OOPโŒNot supported. Yosys is a synthesizer, not a verifier.
Program blocks / clocking blocksโŒIgnore them โ€” the synthesizable subset doesn't include them.
๐Ÿ’ก If you can synthesise it to silicon with a standard tool, RTL Bench can elaborate it. If it only makes sense in a simulator, you're in the wrong place โ€” use a full Verilog simulator locally.

Verilog vs. SystemVerilog

RTL Bench treats both as the same language. When you click Generate, Yosys is invoked with read_verilog -sv, which accepts the SystemVerilog subset in both .v and .sv files.

That means you can write logic, always_ff, always_comb, and packed structs in a .v file and Yosys will not complain. There is no benefit to using the older Verilog-2001 syntax unless you specifically need compatibility with a local tool that rejects SystemVerilog.

โ„น๏ธ If your team standardises on Verilog-2001 for portability, write Verilog-2001 in RTL Bench. If your team has moved to SystemVerilog, write SystemVerilog. The tool does not care.

Common patterns that work well

Parameterised modules

The parameter keyword makes a module reusable. Yosys elaborates each instantiation with its parameters resolved before drawing the schematic.

module reg_file #(
    parameter WIDTH = 32,
    parameter DEPTH = 16
) (
    input  logic             clk,
    input  logic             we,
    input  logic [3:0]      addr,
    input  logic [WIDTH-1:0] wdata,
    output logic [WIDTH-1:0] rdata
);
    logic [WIDTH-1:0] mem [0:DEPTH-1];

    always_ff @(posedge clk)
        if (we) mem[addr] <= wdata;

    assign rdata = mem[addr];
endmodule

Generate loops for structure

A generate for loop unrolls at elaboration. It is the clean way to write repetitive hardware without copy-paste.

genvar i;
generate
    for (i = 0; i < 8; i = i + 1) begin : gen_adder
        assign sum[i] = a[i] ^ b[i] ^ carry[i];
        assign carry[i+1] = (a[i] & b[i]) | (carry[i] & (a[i] ^ b[i]));
    end
endgenerate

RTL Bench expands this into eight separate adder cells in the schematic โ€” each labelled with the hierarchy path so you can trace it back to the source.

Packed structs for buses

SystemVerilog packed structs are the clean way to group signals that travel together. Yosys treats them as a single wide vector.

typedef struct packed {
    logic [31:0] addr;
    logic [31:0] data;
    logic        valid;
} axi_req_t;

module sink (
    input axi_req_t req
);
    assign done = req.valid;
endmodule

What does not work

The honest limitations:

  • SystemVerilog interfaces. Port lists cannot contain interface instances. Pass the signals you need, or wrap the interface as a struct.
  • Assertions and covergroups. Yosys ignores them. If you want SVA checking, use a real simulator.
  • Classes and OOP. SystemVerilog classes are a verification feature, not a synthesis feature. Yosys will reject them.
  • real arithmetic. Only integer types are synthesizable. If you need a fixed-point multiplier, implement it with integer types.
  • initial blocks that drive hardware. $dumpfile and $dumpvars work in a testbench, but initial assignments to design signals do not synthesise. Use always_ff with a reset.
โš ๏ธ If Yosys rejects your module, the error modal shows the exact line and the surrounding context. Most failures are syntax โ€” unbalanced begin/end, missing semicolons, or a port connection that names a signal that does not exist.

How elaboration works

When you click Generate, RTL Bench runs a short Yosys script:

  1. read_verilog -sv โ€” parse every uploaded Verilog file.
  2. hierarchy -top <name> โ€” pick a top module (or auto-detect).
  3. proc โ€” flatten always blocks into logic and DFFs.
  4. opt โ€” remove dead logic and redundant cells.
  5. write_json โ€” emit the netlist the schematic renderer reads.

The whole thing runs in under two seconds for a small design. If you have many files, upload them all at once โ€” Yosys processes them in the order you provide.

Frequently asked questions

Which version of Verilog / SystemVerilog is supported in RTL Bench?

RTL Bench supports IEEE 1364-2001 and IEEE 1364-2005 Verilog, as well as core synthesizable subsets of IEEE 1800-2012 SystemVerilog (including logic, always_comb, always_ff, packages, and multidimensional arrays).

What is the difference between blocking (`=`) and non-blocking (`<=`) assignments?

Blocking assignments (=) execute sequentially in procedural order and are used exclusively in combinational blocks (always @* or always_comb). Non-blocking assignments (<=) evaluate all right-hand sides concurrently and update left-hand registers simultaneously at the end of the time step, preventing race conditions in clocked sequential blocks (always @(posedge clk)).

How does RTL Bench identify syntax errors in my Verilog code?

As you type, an integrated lint engine runs Yosys and Verilator checks in the background. Syntax errors, undeclared nets, width mismatches, and combinational feedback loops are immediately underlined in the code editor with actionable diagnostic messages.

Next

Try it in the workbench โ†’