Your first testbench
-
Make a folder and save this as
counter.vhd:library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity counter is port (clk, rst : in std_logic; q : out unsigned(3 downto 0)); end entity; architecture rtl of counter is signal n : unsigned(3 downto 0) := (others => '0'); begin process (clk) begin if rising_edge(clk) then n <= (others => '0') when rst = '1' else n + 1; end if; end process; q <= n; end architecture; -
And this as
counter_tb.vhd:library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity counter_tb is end entity; architecture sim of counter_tb is signal clk, rst : std_logic := '1'; signal q : unsigned(3 downto 0); begin clk <= not clk after 5 ns; dut : entity work.counter port map (clk, rst, q); process begin wait for 12 ns; rst <= '0'; wait for 100 ns; assert q = 10 report "q is " & to_string(to_integer(q)) severity error; report "done: q = " & to_string(to_integer(q)); std.env.finish; end process; end architecture; -
Run it:
jhdl counter.vhd counter_tb.vhd --top counter_tbJanusHDL analyzes the files in the order given, elaborates
counter_tband runs it. It prints the report with its time and place, and a summary line:112 ns (delta 0) counter_tb.vhd:18:12: note: done: q = 10 simulation of counter_tb ended at 112 ns (stopped); analysis 28 ms, elaboration 1 ms, run 0 msThe exit code is 0, or 1 if a report or assertion of severity
errororfailurecame up, so scripts and CI can rely on it. -
Record the waveforms and open them:
jhdl counter.vhd counter_tb.vhd --top counter_tb --wave run.jhw jhdlw run.jhwPick signals from the hierarchy on the left.
--vcd run.vcdwrites a VCD file instead, for other viewers. -
A project file lists the files of a bigger design once, with their libraries, in analysis order:
# project.f library work counter.vhd counter_tb.vhdjhdl -f project.f --top counter_tb --cache project.cache--cachekeeps the analysis and reuses it while no file changes.
Next: the UVVM demo projects.