← All guides

Simulating Verilog and VHDL without a testbench

A testbench is a second module that drives a design’s clock and inputs so a simulator can run it. This page simulates Verilog and VHDL without one: what is driven automatically, how inputs are set, and what the result shows. The examples are a counter in Verilog and a sequence detector in VHDL, each with a link that opens it in the simulator with the waveform shown here.

What is driven automatically

The simulator finds each input’s role from the circuit:

Each cycle has two edges. Inputs change on the falling edge, so a value set in a cycle is captured at that cycle’s rising edge. Registers are unknown (x, drawn in red) until a reset or a load gives them a value.

Setting inputs

Every change runs the simulation again. The run length is set beside Simulation, up to 64 cycles.

A counter in Verilog

module counter (
  input  wire       clk,
  input  wire       rst,
  input  wire       en,
  output reg  [3:0] count
);
  always @(posedge clk) begin
    if (rst)
      count <= 4'd0;
    else if (en)
      count <= count + 4'd1;
  end
endmodule

clk is found as the clock and rst as the reset, so both are driven with no setup. Only en was set: high in cycles 2 to 4 and from cycle 6 on, by dragging along its row.

0123456789clkrstencountx0123456
count goes up by one at each rising edge after a cycle with en high, and holds otherwise. Before the reset it is x.

Open the counter in the simulator. The value at the cursor is also written on the schematic’s wires: drag the cursor along the ruler, or use the arrow keys, to step through the run.

A sequence detector in VHDL

A Moore machine that sets found for one cycle after the input has delivered 101. Matches may overlap: 10101 contains two. The state machine guide covers Moore and Mealy machines in more detail.

library ieee;
use ieee.std_logic_1164.all;

entity detect_101 is
  port (
    clk   : in  std_logic;
    rst   : in  std_logic;
    din   : in  std_logic;
    found : out std_logic
  );
end entity;

architecture rtl of detect_101 is
  type state_t is (IDLE, GOT1, GOT10, MATCH);
  signal state : state_t;
begin
  process (clk)
  begin
    if rising_edge(clk) then
      if rst = '1' then
        state <= IDLE;
      else
        case state is
          when IDLE =>
            if din = '1' then state <= GOT1; end if;
          when GOT1 =>
            if din = '0' then state <= GOT10; end if;
          when GOT10 =>
            if din = '1' then state <= MATCH; else state <= IDLE; end if;
          when MATCH =>
            if din = '1' then state <= GOT1; else state <= GOT10; end if;
        end case;
      end if;
    end if;
  end process;

  found <= '1' when state = MATCH else '0';
end architecture;

state is an enumerated type, so the waveform shows it by state name. din was set to 1 0 1 0 1 1 0 1 from cycle 1 by clicking the cycles that are 1.

01234567891011clkrstdinstatexIDLEGOT1GOT10MATCHGOT10MATCHGOT1GOT10MATCHGOT10IDLEfound
found is high in the cycle after each 101. The second match reuses the 1 that ended the first.

Open the detector in the simulator.

What is simulated

The simulator runs the circuit synthesis produced, not the source. Yosys synthesizes the design to the netlist drawn as the schematic, and its sim command steps that netlist one clock edge at a time with the stimulus set in the waveform. Two consequences:

When a testbench is still needed

In the VS Code extension (Pro), the stimulus set in the waveform can be saved as a SystemVerilog or VHDL testbench, so a waveform made by clicking becomes the start of one.