diff --git a/.gitignore b/.gitignore
index fdbb3d1d1..725173409 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,4 +30,6 @@ verilator.txt
 verilator_bin*
 verilator_coverage_bin*
 verilator.pc
+verilator-config.cmake
+verilator-config-version.cmake
 **/obj_dir/*
diff --git a/Changes b/Changes
index 781e6d37e..7a00339da 100644
--- a/Changes
+++ b/Changes
@@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
 
 **    Add --protect-lib, bug1490. [Todd Strader]
 
+**    Add cmake support, bug1363. [Patrick Stewart]
+
 ***   Examples have been renamed.
 
 ***   Add --protect-ids to obscure information in objects, bug1521. [Todd Strader]
diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP
index 57338db2e..e14400721 100644
--- a/MANIFEST.SKIP
+++ b/MANIFEST.SKIP
@@ -15,6 +15,7 @@
 .*\.vcd
 .*\.1
 \.travis\.yml
+/build/
 /obj_dir/
 /obj_dbg/
 /obj_nc/
@@ -39,6 +40,8 @@ config.cache$
 config.status$
 verilator\.log
 verilator\.tex
+verilator-config.cmake$
+verilator-config-version.cmake$
 verilator.pc$
 verilator_bin.*
 verilator_coverage_bin.*
diff --git a/Makefile.in b/Makefile.in
index 5ce1c1ab0..e129bd627 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -104,6 +104,11 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
 SHELL = /bin/sh
 
 SUBDIRS = src test_regress \
+	examples/cmake_hello_c \
+	examples/cmake_hello_sc \
+	examples/cmake_tracing_c \
+	examples/cmake_tracing_sc \
+	examples/cmake_protect_lib \
 	examples/make_hello_c \
 	examples/make_hello_sc \
 	examples/make_tracing_c \
@@ -122,6 +127,8 @@ DISTFILES_INC = $(INFOS) .gitignore \
 	Changes \
 	LICENSE \
 	MANIFEST.SKIP \
+	verilator-config.cmake.in \
+	verilator-config-version.cmake.in \
 	bin/verilator \
 	bin/verilator_coverage \
 	bin/verilator_difftree \
@@ -151,8 +158,14 @@ DISTFILES_INC = $(INFOS) .gitignore \
 	src/*.pl src/*.pod \
 	examples/*/.*ignore examples/*/Makefile* \
 	examples/*/*.[chv]* examples/*/*.pl \
+	examples/*/CMakeLists.txt \
 	test_*/.*ignore test_*/Makefile* test_*/*.cpp \
 	test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
+	test_regress/*.pl \
+	test_regress/Makefile \
+	test_regress/Makefile_obj \
+	test_regress/input.vc \
+	test_regress/CMakeLists.txt \
 	test_regress/t/t*/*.sv* \
 	test_regress/t/t*/*.v* \
 	test_regress/t/t*/*/*.sv* \
@@ -302,6 +315,7 @@ VL_INST_INC_SRCDIR_FILES = \
 
 VL_INST_DATA_SRCDIR_FILES = \
 	examples/*/*.[chv]*  examples/*/Makefile* \
+	examples/*/CMakeLists.txt
 
 installbin:
 	$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
@@ -338,12 +352,19 @@ installdata:
 	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_tracing_c
 	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_tracing_sc
 	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_protect_lib
+	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_c
+	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_sc
+	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_c
+	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_sc
+	$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_protect_lib
 	cd $(srcdir) \
 	; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
 	  $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
 	done
 	$(MKINSTALLDIRS) $(DESTDIR)$(pkgconfigdir)
 	$(INSTALL_DATA) verilator.pc $(DESTDIR)$(pkgconfigdir)
+	$(INSTALL_DATA) verilator-config.cmake $(DESTDIR)$(pkgdatadir)
+	$(INSTALL_DATA) verilator-config-version.cmake $(DESTDIR)$(pkgdatadir)
 
 # We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
 uninstall:
@@ -354,6 +375,8 @@ uninstall:
 	-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
 	-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_DATA_SRCDIR_FILES)
 	-rm $(DESTDIR)$(pkgconfigdir)/verilator.pc
+	-rm $(DESTDIR)$(pkgdatadir)/verilator-config.cmake
+	-rm $(DESTDIR)$(pkgdatadir)/verilator-config-version.cmake
 	-rmdir $(DESTDIR)$(pkgdatadir)/bin
 	-rmdir $(DESTDIR)$(pkgdatadir)/include/gtkwave
 	-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
@@ -363,7 +386,13 @@ uninstall:
 	-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_tracing_c
 	-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_tracing_sc
 	-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_protect_lib
+	-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_c
+	-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_sc
+	-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_c
+	-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_sc
+	-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_protect_lib
 	-rmdir $(DESTDIR)$(pkgdatadir)/examples
+	-rmdir $(DESTDIR)$(pkgdatadir)/cmake
 	-rmdir $(DESTDIR)$(pkgdatadir)
 	-rmdir $(DESTDIR)$(pkgconfigdir)
 
diff --git a/README.pod b/README.pod
index 3587f61a7..a0b31384b 100644
--- a/README.pod
+++ b/README.pod
@@ -257,6 +257,11 @@ The directories in the package directory are as follows:
     examples/make_tracing_c     => Example GNU-make Verilog->C++ with tracing
     examples/make_tracing_sc    => Example GNU-make Verilog->SystemC with tracing
     examples/make_protect_lib   => Example using --protect-lib
+    examples/cmake_hello_c      => Example building make_hello_c with CMake
+    examples/cmake_hello_sc     => Example building make_hello_sc with CMake
+    examples/cmake_tracing_c    => Example building make_tracing_c with CMake
+    examples/cmake_tracing_sc   => Example building make_tracing_sc with CMake
+    examples/cmake_protect_lib  => Example building make_protect_lib with CMake
     include/                    => Files that should be in your -I compiler path
     include/verilated*.cpp      => Global routines to link into your simulator
     include/verilated*.h        => Global headers
diff --git a/bin/verilator b/bin/verilator
index fa3ecda1f..06a43c149 100755
--- a/bin/verilator
+++ b/bin/verilator
@@ -283,6 +283,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
     --cc                        Create C++ output
     --cdc                       Clock domain crossing analysis
     --clk <signal-name>         Mark specified signal as clock
+    --make <make-system>        Generate scripts for specified make system
     --compiler <compiler-name>  Tune for specified C++ compiler
     --converge-limit <loops>    Tune convergence settle time
     --coverage                  Enable all coverage
@@ -574,6 +575,13 @@ If clock signals are assigned to vectors and then later used individually,
 Verilator will attempt to decompose the vector and connect the single-bit
 clock signals directly.  This should be transparent to the user.
 
+=item --make I<make-system>
+
+Generates a script for the specified make system.
+
+Supported make systems are gmake and cmake. Both can be specified.
+If no make system is specified, gmake is assumed.
+
 =item --compiler I<compiler-name>
 
 Enables tunings and workarounds for the specified C++ compiler.
@@ -1944,9 +1952,15 @@ All output files are placed in the output directory name specified with the
 
 Verilator creates the following files in the output directory:
 
+For --make gmake, it creates:
+
     {prefix}.mk                         // Make include file for compiling
     {prefix}_classes.mk                 // Make include file with class names
 
+For --make cmake, it creates:
+
+    {prefix}.cmake                      // CMake include script for compiling
+
 For -cc and -sc mode, it also creates:
 
     {prefix}.cpp                        // Top level C++ file
@@ -2406,6 +2420,152 @@ The target system may also require edits to the Makefiles, the simple
 Makefiles produced by Verilator presume the target system is the same type
 as the build system.
 
+=head2 CMake
+
+Verilator can be run using CMake, which takes care of both running
+Verilator and compiling the output. There is a CMake example in the
+examples/ directory. The following is a minimal CMakeLists.txt that
+would build the code listed in "EXAMPLE C++ EXECUTION":
+
+    project(cmake_example)
+    find_package(verilator HINTS $ENV{VERILATOR_ROOT})
+    add_executable(Vour sim_main.cpp)
+    verilate(Vour SOURCES our.v)
+
+find_package will automatically find an installed copy of Verilator, or use
+a local build if VERILATOR_ROOT is set.
+
+It is recommended to use CMake >= 3.12 and the Ninja generator, though
+other combinations should work. To build with CMake, change to the folder
+containing CMakeLists.txt and run:
+
+    mkdir build
+    cd build
+    cmake -GNinja ..
+    ninja
+
+Or to build with your system default generator:
+
+    mkdir build
+    cd build
+    cmake ..
+    cmake --build .
+
+If you're building the example you should have an executable to run:
+
+    ./Vour
+
+The package sets the CMake variables verilator_FOUND, VERILATOR_ROOT and
+VERILATOR_BIN to the appropriate values, and also creates a verilate()
+function. verilate() will automatically create custom commands to run
+Verilator and add the generated C++ sources to the target specified.
+
+    verilate(target SOURCES source ... [TOP_MODULE top] [PREFIX name]
+             [TRACE] [TRACE_FST] [SYSTEMC] [COVERAGE]
+             [INCLUDE_DIRS dir ...] [OPT_SLOW ...] [OPT_FAST ...]
+             [DIRECTORY dir] [VERILATOR_ARGS ...])
+
+Lowercase and ... should be replaced with arguments, the uppercase parts
+delimit the arguments and can be passed in any order, or left out entirely
+if optional.
+
+verilate(target ...) can be called multiple times to add other verilog
+modules to an executable or library target.
+
+When generating Verilated SystemC sources, you should also include the
+SystemC include directories and link to the SystemC libraries.
+
+Verilator's CMake support provides a convenience function to automatically
+find and link to the SystemC library.  It can be used as:
+
+    verilator_link_systemc(target)
+
+where target is the name of your target.
+
+The search paths can be configured by setting some variables:
+
+- The variables SYSTEMC_INCLUDE and SYSTEMC_LIBDIR to give a direct path to
+the SystemC include an library path.
+
+- SYSTEMC_ROOT to set the installation prefix of an installed SystemC
+  library.
+
+- SYSTEMC to set the installation prefix of an installed SystemC library
+  (same as above).
+
+- When using Accellera's SystemC with CMake support, a CMake target is
+available that will easen above steps. This will only work if the SystemC
+installation can be found by CMake. This can be configured by setting the
+CMAKE_PREFIX_PATH variable during CMake configuration.
+
+Don't forget to set the same C++ standard for the Verilated sources as the
+SystemC library. This can be specified using the SYSTEMC_CXX_FLAGS environment
+variable.
+
+=over 4
+
+=item target
+
+Name of a target created by add_executable or add_library.
+
+=item SOURCES
+
+List of verilog files to Verilate. Must have at least one file.
+
+=item PREFIX
+
+Optional. Sets the Verilator output prefix. Defaults to the name of the
+first hdl source with a "V" prepended. Must be unique in each call to
+verilate(), so this is necessary if you build a module multiple times with
+different parameters. Must be a valid C++ identifer, i.e. contains no
+whitespace and only characters A-Z, a-z, 0-9 or _.
+
+=item TOP_MODULE
+
+Optional. Sets the name of the top module. Defaults to the name of the
+first file in the SOURCES array.
+
+=item TRACE
+
+Optional. Enables VCD tracing if present, equivalent to "VERILATOR_ARGS --trace".
+
+=item TRACE_FST
+
+Optional. Enables FST tracing if present, equivalent to "VERILATOR_ARGS --trace-fst".
+
+=item SYSTEMC
+
+Optional. Enables SystemC mode, defaults to C++ if not specified.
+
+=item COVERAGE
+
+Optional. Enables coverage if present, equivalent to "VERILATOR_ARGS --coverage"
+
+=item INCLUDE_DIRS
+
+Optional. Sets directories that Verilator searches (same as -y).
+
+=item OPT_SLOW
+
+Optional. Set compiler flags for the slow path. You may want to reduce the
+optimisation level to improve compile times with large designs.
+
+=item OPT_FAST
+
+Optional. Set compiler flags for the fast path.
+
+=item DIRECTORY
+
+Optional. Set the verilator output directory. It is preferable to use the
+default, which will avoid collisions with other files.
+
+=item VERILATOR_ARGS
+
+Optional. Extra arguments to Verilator. Do not specify --Mdir or --prefix
+here, use DIRECTORY or PREFIX.
+
+=back
+
 =head2 Cadence NC-SystemC Models
 
 Similar to compiling Verilated designs with gcc, Verilated designs may be
diff --git a/configure.ac b/configure.ac
index 9c81b9ee7..c380a2961 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@ AC_INIT([Verilator],[4.020 devel],
 # and commit using "devel release" or "Version bump" message
 
 AC_CONFIG_HEADER(src/config_build.h)
-AC_CONFIG_FILES(Makefile docs/Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc)
+AC_CONFIG_FILES(Makefile docs/Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc verilator-config.cmake verilator-config-version.cmake)
 
 AC_MSG_RESULT([configuring for $PACKAGE_STRING])
 
@@ -276,24 +276,37 @@ AC_SUBST(CFG_CXXFLAGS_PARSER)
 # For some reason -faligned-new does not work under Travis w/ clang but the
 # configure test doesn't catch this either
 AS_IF([test "x$TRAVIS_COMPILER" != xclang], [_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-faligned-new)])
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-fbracket-depth=4096)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Qunused-arguments)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-bool-operation)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-parentheses-equality)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-sign-compare)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-but-set-variable)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-parameter)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-variable)
-_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-shadow)
+CFG_CXX_FLAGS_CMAKE="-faligned-new"
+m4_foreach([cflag],[
+        [-fbracket-depth=4096],
+        [-Qunused-arguments],
+        [-Wno-bool-operation],
+        [-Wno-parentheses-equality],
+        [-Wno-sign-compare],
+        [-Wno-uninitialized],
+        [-Wno-unused-but-set-variable],
+        [-Wno-unused-parameter],
+        [-Wno-unused-variable],
+        [-Wno-shadow]],[
+    _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,cflag)
+    # CMake will test what flags work itself, so pass all flags through to it
+    CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE cflag"
+    ])
 AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
+AC_SUBST(CFG_CXX_FLAGS_CMAKE)
 
 # Find multithread linker flags
-_MY_LDLIBS_CHECK_OPT(CFG_LDLIBS_THREADS,-mt)
-_MY_LDLIBS_CHECK_OPT(CFG_LDLIBS_THREADS,-pthread)
-_MY_LDLIBS_CHECK_OPT(CFG_LDLIBS_THREADS,-lpthread)
-_MY_LDLIBS_CHECK_OPT(CFG_LDLIBS_THREADS,-latomic)
+m4_foreach([ldflag], [
+        [-mt],
+        [-pthread],
+        [-lpthread],
+        [-latomic]],[
+    _MY_LDLIBS_CHECK_OPT(CFG_LDLIBS_THREADS,ldflag)
+    # CMake will test what flags work itself, so pass all flags through to it
+    CFG_LDFLAGS_THREADS_CMAKE="$CFG_LDFLAGS_THREADS_CMAKE ldflag"
+    ])
 AC_SUBST(CFG_LDLIBS_THREADS)
+AC_SUBST(CFG_LDFLAGS_THREADS_CMAKE)
 
 # Set CFG_WITH_THREADED if can support threading
 AC_MSG_CHECKING(whether $CXX supports Verilated threads)
diff --git a/examples/cmake_hello_c/.gitignore b/examples/cmake_hello_c/.gitignore
new file mode 100644
index 000000000..1b2211df0
--- /dev/null
+++ b/examples/cmake_hello_c/.gitignore
@@ -0,0 +1 @@
+build*
diff --git a/examples/cmake_hello_c/CMakeLists.txt b/examples/cmake_hello_c/CMakeLists.txt
new file mode 100644
index 000000000..a3b45036c
--- /dev/null
+++ b/examples/cmake_hello_c/CMakeLists.txt
@@ -0,0 +1,37 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake Example: Small CMakeLists.txt
+#
+# This is an example cmake script to build a verilog to systemc project
+# using cmake and verilator.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+# This example builds the tracing_c example using CMake
+# To use it, run the following:
+
+# cd /path/to/verilator/examples/cmake_c
+# rm -rf build && mkdir build && cd build
+# cmake ..
+# cmake --build .
+
+cmake_minimum_required(VERSION 3.8)
+project(cmake_hello_c)
+
+find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT})
+if (NOT verilator_FOUND)
+  message(FATAL_ERROR "Verilator was not found. Either install it, or set the VERILATOR_ROOT environment variable")
+endif()
+
+# Create a new executable target that will contain all your sources
+add_executable(example ../make_hello_c/sim_main.cpp)
+
+# Add the Verilated circuit to the target
+verilate(example
+  INCLUDE_DIRS "../make_hello_c"
+  SOURCES ../make_hello_c/top.v)
diff --git a/examples/cmake_hello_c/Makefile b/examples/cmake_hello_c/Makefile
new file mode 100644
index 000000000..8c0b5ed24
--- /dev/null
+++ b/examples/cmake_hello_c/Makefile
@@ -0,0 +1,79 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake example usage
+#
+# This file shows usage of the CMake script.
+# This makefile is here for testing the examples and should
+# generally not be added to a CMake project.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+######################################################################
+# Set up variables
+
+# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
+# package install, and verilator is in your path. Otherwise find the
+# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
+
+ifeq ($(VERILATOR_ROOT),)
+VERILATOR_COVERAGE = verilator_coverage
+else
+export VERILATOR_ROOT
+VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
+endif
+######################################################################
+
+# Check if CMake is installed and of correct version
+ifeq ($(shell which cmake),)
+TARGET := nocmake
+else
+CMAKE_VERSION := $(shell cmake --version | grep -Po '(\d[\.\d]+)')
+CMAKE_MAJOR := $(shell echo $(CMAKE_VERSION) | cut -f1 -d.)
+CMAKE_MINOR := $(shell echo $(CMAKE_VERSION) | cut -f2 -d.)
+CMAKE_GT_3_8 := $(shell [ $(CMAKE_MAJOR) -gt 3 -o \( $(CMAKE_MAJOR) -eq 3 -a $(CMAKE_MINOR) -ge 8 \) ] && echo true)
+ifeq ($(CMAKE_GT_3_8),true)
+TARGET := run
+else
+TARGET := oldcmake
+endif
+endif
+
+default: $(TARGET)
+
+run:
+	@echo
+	@echo "-- Verilator CMake hello world example"
+
+	@echo
+	@echo "-- CMake ----------------"
+	mkdir -p build && cd build && cmake ..
+
+	@echo
+	@echo "-- COMPILE -----------------"
+	cmake --build build
+
+	@echo
+	@echo "-- RUN ---------------------"
+	build/example
+
+	@echo
+	@echo "-- DONE --------------------"
+	@echo
+
+clean mostlyclean distclean maintainer-clean:
+	@rm -rf build logs
+
+nocmake:
+	@echo
+	@echo "%Skip: CMake has not been found"
+	@echo
+
+oldcmake:
+	@echo
+	@echo "%Skip: CMake version is too old (need at least 3.8)"
+	@echo
diff --git a/examples/cmake_hello_sc/.gitignore b/examples/cmake_hello_sc/.gitignore
new file mode 100644
index 000000000..1b2211df0
--- /dev/null
+++ b/examples/cmake_hello_sc/.gitignore
@@ -0,0 +1 @@
+build*
diff --git a/examples/cmake_hello_sc/CMakeLists.txt b/examples/cmake_hello_sc/CMakeLists.txt
new file mode 100644
index 000000000..3aa7d6714
--- /dev/null
+++ b/examples/cmake_hello_sc/CMakeLists.txt
@@ -0,0 +1,46 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake Example: Small CMakeLists.txt with SystemC
+#
+# This is an example cmake script to build a verilog to SystemC project
+# using CMake and Verilator.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+# This example builds the tracing_sc example using CMake
+# To use it, run the following:
+
+# cd /path/to/verilator/examples/cmake_sc
+# rm -rf build && mkdir build && cd build
+# cmake ..
+# cmake --build .
+
+cmake_minimum_required(VERSION 3.8)
+project(cmake_hello_sc)
+
+find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT})
+if (NOT verilator_FOUND)
+  message(FATAL_ERROR "Verilator was not found. Either install it, or set the VERILATOR_ROOT environment variable")
+endif()
+
+# SystemC dependencies
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads REQUIRED)
+
+# Find SystemC using SystemC's CMake integration
+find_package(SystemCLanguage QUIET)
+
+# Create a new executable target that will contain all your sources
+add_executable(example ../make_hello_sc/sc_main.cpp)
+
+# Add the Verilated circuit to the target
+verilate(example SYSTEMC
+  INCLUDE_DIRS "../make_hello_sc"
+  SOURCES ../make_hello_sc/top.v)
+
+verilator_link_systemc(example)
diff --git a/examples/cmake_hello_sc/Makefile b/examples/cmake_hello_sc/Makefile
new file mode 100644
index 000000000..3e5cb375b
--- /dev/null
+++ b/examples/cmake_hello_sc/Makefile
@@ -0,0 +1,129 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake example usage
+#
+# This file shows usage of the CMake script.
+# This makefile is here for testing the examples and should
+# generally not be added to a CMake project.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+######################################################################
+# Set up variables
+
+# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
+# package install, and verilator is in your path. Otherwise find the
+# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
+
+ifeq ($(VERILATOR_ROOT),)
+VERILATOR_COVERAGE = verilator_coverage
+else
+export VERILATOR_ROOT
+VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
+endif
+######################################################################
+
+# Check if CMake is installed and of correct version
+ifeq ($(shell which cmake),)
+	TARGET := nocmake
+else
+CMAKE_VERSION := $(shell cmake --version | grep -Po '(\d[\.\d]+)')
+CMAKE_MAJOR := $(shell echo $(CMAKE_VERSION) | cut -f1 -d.)
+CMAKE_MINOR := $(shell echo $(CMAKE_VERSION) | cut -f2 -d.)
+CMAKE_GT_3_8 := $(shell [ $(CMAKE_MAJOR) -gt 3 -o \( $(CMAKE_MAJOR) -eq 3 -a $(CMAKE_MINOR) -ge 8 \) ] && echo true)
+ifneq ($(CMAKE_GT_3_8),true)
+TARGET := oldcmake
+else
+
+# Test existence of SYSTEMC_INCLUDE and SYSTEMC_LIBDIR environment variabless
+ifneq (,$(SYSTEMC_INCLUDE))
+ifneq (,${SYSTEMC_LIBDIR})
+SYSTEMC_SET := true
+endif
+endif
+
+# Test existence of SYSTEMC_ROOT environment variable
+ifneq (SYSTEMC_SET, true)
+ifneq (,${SYSTEMC_ROOT})
+SYSTEMC_SET := true
+endif
+endif
+
+# Test existence of SYSTEMC environment variable
+ifneq (SYSTEMC_SET, true)
+ifneq (,${SYSTEMC})
+SYSTEMC_SET := true
+endif
+endif
+
+# Test whether SystemC is installed with CMake support
+# This will print a CMake error about processing arguments that can (currently) be ignored.
+ifneq (SYSTEMC_SET, true)
+FINDSC := $(shell mkdir -p build && cd build && cmake --find-package -DNAME=SystemCLanguage -DCMAKE_USE_PTHREADS_INIT=ON -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST -DThreads_FOUND=ON)
+ifneq (,$(findstring SystemCLanguage found,$(FINDSC)))
+SYSTEMC_SET := true
+endif
+endif
+
+ifeq ($(SYSTEMC_SET), true)
+TARGET := run
+else
+TARGET := nosc
+endif
+
+endif
+endif
+
+default: $(TARGET)
+
+run:
+	@echo
+	@echo "-- Verilator CMake SystemC hello-world simple example"
+
+	@echo
+	@echo "-- CMake ----------------"
+	mkdir -p build && cd build && cmake ..
+
+	@echo
+	@echo "-- COMPILE -----------------"
+	cmake --build build
+
+	@echo
+	@echo "-- RUN ---------------------"
+	@mkdir -p logs
+	build/example
+
+	@echo "-- DONE --------------------"
+	@echo "Note: Once this example is understood, see examples/cmake_tracing_sc."
+	@echo "Note: Also see the EXAMPLE section in the verilator manpage/document."
+
+clean mostlyclean distclean maintainer-clean:
+	@rm -rf build logs
+
+nocmake:
+	@echo
+	@echo "%Skip: CMake has not been found"
+	@echo
+
+oldcmake:
+	@echo
+	@echo "%Skip: CMake version is too old (need at least 3.8)"
+	@echo
+
+nosc:
+	@echo
+	@echo "%Skip: CMake could not find SystemC."
+	@echo "% Make sure that either:"
+	@echo "% - The environment variables SYSTEMC_INCLUDE and SYSTEMC_LIBDIR are exported."
+	@echo "% - Or, the environment variable SYSTEMC_ROOT is exported."
+	@echo "% - Or, The environment variable SYSTEMC is exported."
+	@echo "% - Or, if the SystemC installation provides CMake support,"
+	@echo "%   that its installation prefix is in CMAKE_PREFIX_PATH."
+	@echo "% Also that the C++ standard of the SystemC library is the same as this example."
+	@echo "% Please see the Verilator documentation's CMake section for more information."
+	@echo
diff --git a/examples/cmake_protect_lib/.gitignore b/examples/cmake_protect_lib/.gitignore
new file mode 100644
index 000000000..1b2211df0
--- /dev/null
+++ b/examples/cmake_protect_lib/.gitignore
@@ -0,0 +1 @@
+build*
diff --git a/examples/cmake_protect_lib/CMakeLists.txt b/examples/cmake_protect_lib/CMakeLists.txt
new file mode 100644
index 000000000..7031eb1c7
--- /dev/null
+++ b/examples/cmake_protect_lib/CMakeLists.txt
@@ -0,0 +1,60 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake Example: Small CMakeLists.txt
+#
+# This is an example cmake script to build a verilog to systemc project
+# using cmake and verilator.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+# This example builds the tracing_c example using CMake
+# To use it, run the following:
+
+# cd /path/to/verilator/examples/cmake_c
+# rm -rf build && mkdir build && cd build
+# cmake ..
+# cmake --build .
+
+cmake_minimum_required(VERSION 3.8)
+project(cmake_protect_lib)
+
+find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT})
+if (NOT verilator_FOUND)
+  message(FATAL_ERROR "Verilator was not found. Either install it, or set the VERILATOR_ROOT environment variable")
+endif()
+
+# Create the main executable target
+add_executable(example ../make_protect_lib/sim_main.cpp)
+
+# Create a secret library
+add_library(verilated_secret STATIC) # or SHARED for a shared library
+target_link_libraries(example PRIVATE verilated_secret)
+# To create both libraries on CMake >= 3.12 replace the above 2 lines with the following:
+# add_library(verilated_secret OBJECT)
+# set_property(TARGET verilated_secret PROPERTY POSITION_INDEPENDENT_CODE 1)
+# add_library(verilated_secret_static STATIC  $<TARGET_OBJECTS:verilated_secret>)
+# set_target_properties(verilated_secret_static PROPERTIES OUTPUT_NAME verilated_secret)
+# add_library(verilated_secret_shared SHARED  $<TARGET_OBJECTS:verilated_secret>)
+# set_target_properties(verilated_secret_shared PROPERTIES OUTPUT_NAME verilated_secret)
+# target_link_libraries(example PRIVATE verilated_secret_static)
+
+# Setup random seed
+verilator_generate_key(KEY_INIT)
+set(PROTECT_KEY ${KEY_INIT} CACHE STRING "Random seed for protection")
+
+# Add the Verilated modules to the targets
+verilate(verilated_secret
+  VERILATOR_ARGS --protect-lib verilated_secret
+                 --protect-key ${PROTECT_KEY}
+  DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/verilated_secret
+  SOURCES ../make_protect_lib/secret_impl.v)
+
+# Include location of verilated_secret.sv wrapper
+verilate(example
+  VERILATOR_ARGS "-I${CMAKE_CURRENT_BINARY_DIR}/verilated_secret"
+  SOURCES ../make_protect_lib/top.v)
diff --git a/examples/cmake_protect_lib/Makefile b/examples/cmake_protect_lib/Makefile
new file mode 100644
index 000000000..a3d3575a6
--- /dev/null
+++ b/examples/cmake_protect_lib/Makefile
@@ -0,0 +1,79 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake example usage
+#
+# This file shows usage of the CMake script.
+# This makefile is here for testing the examples and should
+# generally not be added to a CMake project.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+######################################################################
+# Set up variables
+
+# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
+# package install, and verilator is in your path. Otherwise find the
+# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
+
+ifeq ($(VERILATOR_ROOT),)
+VERILATOR_COVERAGE = verilator_coverage
+else
+export VERILATOR_ROOT
+VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
+endif
+######################################################################
+
+# Check if CMake is installed and of correct version
+ifeq ($(shell which cmake),)
+TARGET := nocmake
+else
+CMAKE_VERSION := $(shell cmake --version | grep -Po '(\d[\.\d]+)')
+CMAKE_MAJOR := $(shell echo $(CMAKE_VERSION) | cut -f1 -d.)
+CMAKE_MINOR := $(shell echo $(CMAKE_VERSION) | cut -f2 -d.)
+CMAKE_GT_3_8 := $(shell [ $(CMAKE_MAJOR) -gt 3 -o \( $(CMAKE_MAJOR) -eq 3 -a $(CMAKE_MINOR) -ge 8 \) ] && echo true)
+ifeq ($(CMAKE_GT_3_8),true)
+TARGET := run
+else
+TARGET := oldcmake
+endif
+endif
+
+default: $(TARGET)
+
+run:
+	@echo
+	@echo "-- Verilator CMake protect_lib example"
+
+	@echo
+	@echo "-- CMake ----------------"
+	mkdir -p build && cd build && cmake ..
+
+	@echo
+	@echo "-- COMPILE -----------------"
+	cmake --build build
+
+	@echo
+	@echo "-- RUN ---------------------"
+	build/example
+
+	@echo
+	@echo "-- DONE --------------------"
+	@echo
+
+clean mostlyclean distclean maintainer-clean:
+	@rm -rf build logs
+
+nocmake:
+	@echo
+	@echo "%Skip: CMake has not been found"
+	@echo
+
+oldcmake:
+	@echo
+	@echo "%Skip: CMake version is too old (need at least 3.8)"
+	@echo
diff --git a/examples/cmake_tracing_c/.gitignore b/examples/cmake_tracing_c/.gitignore
new file mode 100644
index 000000000..c0b051137
--- /dev/null
+++ b/examples/cmake_tracing_c/.gitignore
@@ -0,0 +1,2 @@
+build*
+logs
diff --git a/examples/cmake_tracing_c/CMakeLists.txt b/examples/cmake_tracing_c/CMakeLists.txt
new file mode 100644
index 000000000..d0275e9f6
--- /dev/null
+++ b/examples/cmake_tracing_c/CMakeLists.txt
@@ -0,0 +1,38 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake Example: Small CMakeLists.txt with tracing
+#
+# This is an example cmake script to build a verilog to systemc project
+# using cmake and verilator.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+# This example builds the make_tracing_c example using CMake
+# To use it, run the following:
+
+# cd /path/to/verilator/examples/cmake_tracing_c
+# rm -rf build && mkdir build && cd build
+# cmake ..
+# cmake --build .
+
+cmake_minimum_required(VERSION 3.8)
+project(cmake_tracing_c)
+
+find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT})
+if (NOT verilator_FOUND)
+  message(FATAL_ERROR "Verilator was not found. Either install it, or set the VERILATOR_ROOT environment variable")
+endif()
+
+# Create a new executable target that will contain all your sources
+add_executable(example ../make_tracing_c/sim_main.cpp)
+
+# Add the Verilated circuit to the target
+verilate(example COVERAGE TRACE
+  INCLUDE_DIRS "../make_tracing_c"
+  VERILATOR_ARGS -f ../make_tracing_c/input.vc -O2 -x-assign 0
+  SOURCES ../make_tracing_c/top.v)
diff --git a/examples/cmake_tracing_c/Makefile b/examples/cmake_tracing_c/Makefile
new file mode 100644
index 000000000..a6490a328
--- /dev/null
+++ b/examples/cmake_tracing_c/Makefile
@@ -0,0 +1,85 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake example usage
+#
+# This file shows usage of the CMake script.
+# This makefile is here for testing the examples and should
+# generally not be added to a CMake project.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+######################################################################
+# Set up variables
+
+# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
+# package install, and verilator is in your path. Otherwise find the
+# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
+
+ifeq ($(VERILATOR_ROOT),)
+VERILATOR_COVERAGE = verilator_coverage
+else
+export VERILATOR_ROOT
+VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
+endif
+######################################################################
+
+# Check if CMake is installed and of correct version
+ifeq ($(shell which cmake),)
+TARGET := nocmake
+else
+CMAKE_VERSION := $(shell cmake --version | grep -Po '(\d[\.\d]+)')
+CMAKE_MAJOR := $(shell echo $(CMAKE_VERSION) | cut -f1 -d.)
+CMAKE_MINOR := $(shell echo $(CMAKE_VERSION) | cut -f2 -d.)
+CMAKE_GT_3_8 := $(shell [ $(CMAKE_MAJOR) -gt 3 -o \( $(CMAKE_MAJOR) -eq 3 -a $(CMAKE_MINOR) -ge 8 \) ] && echo true)
+ifeq ($(CMAKE_GT_3_8),true)
+TARGET := run
+else
+TARGET := oldcmake
+endif
+endif
+
+default: $(TARGET)
+
+run:
+	@echo
+	@echo "-- Verilator CMake tracing example"
+
+	@echo
+	@echo "-- CMake ----------------"
+	mkdir -p build && cd build && cmake ..
+
+	@echo
+	@echo "-- COMPILE -----------------"
+	cmake --build build
+
+	@echo
+	@echo "-- RUN ---------------------"
+	@mkdir -p logs
+	build/example +trace
+
+	@echo
+	@echo "-- COVERAGE ----------------"
+	$(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat
+
+	@echo
+	@echo "-- DONE --------------------"
+	@echo "To see waveforms, open vlt_dump.vcd in a waveform viewer"
+	@echo
+
+clean mostlyclean distclean maintainer-clean:
+	@rm -rf build logs
+
+nocmake:
+	@echo
+	@echo "%Skip: CMake has not been found"
+	@echo
+
+oldcmake:
+	@echo
+	@echo "%Skip: CMake version is too old (need at least 3.8)"
+	@echo
diff --git a/examples/cmake_tracing_sc/.gitignore b/examples/cmake_tracing_sc/.gitignore
new file mode 100644
index 000000000..284951c31
--- /dev/null
+++ b/examples/cmake_tracing_sc/.gitignore
@@ -0,0 +1,7 @@
+*.dmp
+*.log
+*.csrc
+*.vcd
+obj_*
+logs
+build*
diff --git a/examples/cmake_tracing_sc/CMakeLists.txt b/examples/cmake_tracing_sc/CMakeLists.txt
new file mode 100644
index 000000000..927d11b8f
--- /dev/null
+++ b/examples/cmake_tracing_sc/CMakeLists.txt
@@ -0,0 +1,47 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake Example: Small CMakeLists.txt with SystemC tracing
+#
+# This is an example cmake script to build a verilog to SystemC project
+# using CMake and Verilator.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+# This example builds the tracing_sc example using CMake
+# To use it, run the following:
+
+# cd /path/to/verilator/examples/cmake_tracing_sc
+# rm -rf build && mkdir build && cd build
+# cmake ..
+# cmake --build .
+
+cmake_minimum_required(VERSION 3.8)
+project(cmake_tracing_sc_example)
+
+find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT})
+if (NOT verilator_FOUND)
+  message(FATAL_ERROR "Verilator was not found. Either install it, or set the VERILATOR_ROOT environment variable")
+endif()
+
+# SystemC dependencies
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads REQUIRED)
+
+# Find SystemC using SystemC's CMake integration
+find_package(SystemCLanguage QUIET)
+
+# Create a new executable target that will contain all your sources
+add_executable(example ../make_tracing_sc/sc_main.cpp)
+
+# Add the Verilated circuit to the target
+verilate(example SYSTEMC COVERAGE TRACE
+  INCLUDE_DIRS "../make_tracing_sc"
+  VERILATOR_ARGS -f ../make_tracing_sc/input.vc -O2 -x-assign 0
+  SOURCES ../make_tracing_sc/top.v)
+
+verilator_link_systemc(example)
diff --git a/examples/cmake_tracing_sc/Makefile b/examples/cmake_tracing_sc/Makefile
new file mode 100644
index 000000000..392cf53b4
--- /dev/null
+++ b/examples/cmake_tracing_sc/Makefile
@@ -0,0 +1,134 @@
+######################################################################
+#
+# DESCRIPTION: Verilator CMake example usage
+#
+# This file shows usage of the CMake script.
+# This makefile is here for testing the examples and should
+# generally not be added to a CMake project.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+######################################################################
+# Set up variables
+
+# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
+# package install, and verilator is in your path. Otherwise find the
+# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
+
+ifeq ($(VERILATOR_ROOT),)
+VERILATOR_COVERAGE = verilator_coverage
+else
+export VERILATOR_ROOT
+VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
+endif
+######################################################################
+
+# Check if CMake is installed and of correct version
+ifeq ($(shell which cmake),)
+	TARGET := nocmake
+else
+CMAKE_VERSION := $(shell cmake --version | grep -Po '(\d[\.\d]+)')
+CMAKE_MAJOR := $(shell echo $(CMAKE_VERSION) | cut -f1 -d.)
+CMAKE_MINOR := $(shell echo $(CMAKE_VERSION) | cut -f2 -d.)
+CMAKE_GT_3_8 := $(shell [ $(CMAKE_MAJOR) -gt 3 -o \( $(CMAKE_MAJOR) -eq 3 -a $(CMAKE_MINOR) -ge 8 \) ] && echo true)
+ifneq ($(CMAKE_GT_3_8),true)
+TARGET := oldcmake
+else
+
+# Test existence of SYSTEMC_INCLUDE and SYSTEMC_LIBDIR environment variabless
+ifneq (,$(SYSTEMC_INCLUDE))
+ifneq (,${SYSTEMC_LIBDIR})
+SYSTEMC_SET := true
+endif
+endif
+
+# Test existence of SYSTEMC_ROOT environment variable
+ifneq (SYSTEMC_SET, true)
+ifneq (,${SYSTEMC_ROOT})
+SYSTEMC_SET := true
+endif
+endif
+
+# Test existence of SYSTEMC environment variable
+ifneq (SYSTEMC_SET, true)
+ifneq (,${SYSTEMC})
+SYSTEMC_SET := true
+endif
+endif
+
+# Test whether SystemC is installed with CMake support
+# This will print a CMake error about processing arguments that can (currently) be ignored.
+ifneq (SYSTEMC_SET, true)
+FINDSC := $(shell mkdir -p build && cd build && cmake --find-package -DNAME=SystemCLanguage -DCMAKE_USE_PTHREADS_INIT=ON -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST -DThreads_FOUND=ON)
+ifneq (,$(findstring SystemCLanguage found,$(FINDSC)))
+SYSTEMC_SET := true
+endif
+endif
+
+ifeq ($(SYSTEMC_SET), true)
+TARGET := run
+else
+TARGET := nosc
+endif
+
+endif
+endif
+
+default: $(TARGET)
+
+run:
+	@echo
+	@echo "-- Verilator CMake SystemC tracing example"
+
+	@echo
+	@echo "-- CMake ----------------"
+	mkdir -p build && cd build && cmake ..
+
+	@echo
+	@echo "-- COMPILE -----------------"
+	cmake --build build
+
+	@echo
+	@echo "-- RUN ---------------------"
+	@mkdir -p logs
+	build/example +trace
+
+	@echo
+	@echo "-- COVERAGE ----------------"
+	$(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat
+
+	@echo
+	@echo "-- DONE --------------------"
+	@echo "To see waveforms, open vlt_dump.vcd in a waveform viewer"
+	@echo
+
+clean mostlyclean distclean maintainer-clean:
+	@rm -rf build logs
+
+nocmake:
+	@echo
+	@echo "%Skip: CMake has not been found"
+	@echo
+
+oldcmake:
+	@echo
+	@echo "%Skip: CMake version is too old (need at least 3.8)"
+	@echo
+
+nosc:
+	@echo
+	@echo "%Skip: CMake could not find SystemC."
+	@echo "% Make sure that either:"
+	@echo "% - The environment variables SYSTEMC_INCLUDE and SYSTEMC_LIBDIR are exported."
+	@echo "% - Or, the environment variable SYSTEMC_ROOT is exported."
+	@echo "% - Or, The environment variable SYSTEMC is exported."
+	@echo "% - Or, if the SystemC installation provides CMake support,"
+	@echo "%   that its installation prefix is in CMAKE_PREFIX_PATH."
+	@echo "% Also that the C++ standard of the SystemC library is the same as this example."
+	@echo "% Please see the Verilator documentation's CMake section for more information."
+	@echo
diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in
index 74a3b0173..859af6403 100644
--- a/src/Makefile_obj.in
+++ b/src/Makefile_obj.in
@@ -183,6 +183,7 @@ RAW_OBJS = \
 	V3EmitC.o \
 	V3EmitCInlines.o \
 	V3EmitCSyms.o \
+	V3EmitCMake.o \
 	V3EmitMk.o \
 	V3EmitV.o \
 	V3EmitXml.o \
diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp
new file mode 100644
index 000000000..bd254bd4f
--- /dev/null
+++ b/src/V3EmitCMake.cpp
@@ -0,0 +1,206 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//*************************************************************************
+// DESCRIPTION: Verilator: Emit CMake file list
+//
+// Code available from: http://www.veripool.org/verilator
+//
+//*************************************************************************
+//
+// Copyright 2004-2019 by Wilson Snyder.  This program is free software; you can
+// redistribute it and/or modify it under the terms of either the GNU
+// Lesser General Public License Version 3 or the Perl Artistic License
+// Version 2.0.
+//
+// Verilator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//*************************************************************************
+
+#include "config_build.h"
+#include "verilatedos.h"
+
+#include "V3Global.h"
+#include "V3Os.h"
+#include "V3EmitCMake.h"
+#include "V3EmitCBase.h"
+
+#include <memory>
+
+//######################################################################
+// Emit statements
+
+class CMakeEmitter {
+
+    // METHODS
+    VL_DEBUG_FUNC;  // Declare debug()
+
+    // STATIC FUNCTIONS
+
+    // Concatenate all strings in 'strs' with ' ' between them.
+    template<typename List>
+    static string cmake_list(const List& strs) {
+        string s;
+        if (strs.begin() != strs.end()) {
+            s.append("\"");
+            s.append(*strs.begin());
+            s.append("\"");
+            for (typename List::const_iterator it = ++strs.begin(); it != strs.end(); ++it) {
+                s.append(" \"");
+                s.append(*it);
+                s.append("\"");
+            }
+        }
+        return s;
+    }
+
+    // Print CMake variable set command: output raw_value unmodified
+    // cache_type should be empty for a normal variable
+    // "BOOL", "FILEPATH", "PATH", "STRING" or "INTERNAL" for a CACHE variable
+    // See https://cmake.org/cmake/help/latest/command/set.html
+    static void cmake_set_raw(std::ofstream& of, const string& name, const string& raw_value,
+                            const string& cache_type = "", const string& docstring = "") {
+        of << "set(" << name << " " << raw_value;
+        if (!cache_type.empty()) {
+            of << " CACHE " << cache_type << " \"" << docstring << "\"";
+        }
+        of << ")\n";
+    }
+
+    static void cmake_set(std::ofstream& of, const string& name, const string& value,
+                            const string& cache_type = "", const string& docstring = "") {
+        string raw_value = "\"" + value + "\"";
+        cmake_set_raw(of, name, raw_value, cache_type, docstring);
+    }
+
+    //Swap all backslashes for forward slashes, because of Windows
+    static string deslash(const string& s) {
+        std::string res = s;
+        for (string::iterator it = res.begin(); it != res.end(); ++it) {
+            if (*it == '\\')
+                *it = '/';
+        }
+        return res;
+    }
+
+    static void emitOverallCMake() {
+        const vl_unique_ptr<std::ofstream>
+            of (V3File::new_ofstream(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+".cmake"));
+        string name = v3Global.opt.prefix();
+
+        *of << "# Verilated -*- CMake -*-\n";
+        *of << "# DESCR" "IPTION: Verilator output: CMake include script with class lists\n";
+        *of << "#\n";
+        *of << "# This CMake script lists generated Verilated files, for including in higher level CMake scripts.\n";
+        *of << "# This file is meant to be consumed by the verilate() function,\n";
+        *of << "# which becomes available after executing `find_package(verilator).\n";
+
+        *of << "\n### Constants...\n";
+        cmake_set(*of, "PERL", deslash(V3Options::getenvPERL()),
+                  "FILEPATH", "Perl executable (from $PERL)");
+        cmake_set(*of, "VERILATOR_ROOT", deslash(V3Options::getenvVERILATOR_ROOT()),
+                  "PATH", "Path to Verilator kit (from $VERILATOR_ROOT)");
+
+        *of << "\n### Compiler flags...\n";
+
+        *of << "# User CFLAGS (from -CFLAGS on Verilator command line)\n";
+        cmake_set_raw(*of, name + "_USER_CFLAGS", cmake_list(v3Global.opt.cFlags()));
+
+        *of << "# User LDLIBS (from -LDFLAGS on Verilator command line)\n";
+        cmake_set_raw(*of, name + "_USER_LDLIBS", cmake_list(v3Global.opt.ldLibs()));
+
+        *of << "\n### Switches...\n";
+
+        *of << "# SystemC output mode?  0/1 (from --sc)\n";
+        cmake_set_raw(*of, name + "_SC", v3Global.opt.systemC() ? "1" : "0");
+        *of << "# Coverage output mode?  0/1 (from --coverage)\n";
+        cmake_set_raw(*of, name + "_COVERAGE", v3Global.opt.coverage()?"1":"0");
+        *of << "# Threaded output mode?  0/1/N threads (from --threads)\n";
+        cmake_set_raw(*of, name + "_THREADS", cvtToStr(v3Global.opt.threads()));
+        *of << "# VCD Tracing output mode?  0/1 (from --trace)\n";
+        cmake_set_raw(*of, name + "_TRACE_VCD", (v3Global.opt.trace() && (v3Global.opt.traceFormat() == TraceFormat::VCD))?"1":"0");
+        *of << "# FST Tracing output mode? 0/1 (from --fst-trace)\n";
+        cmake_set_raw(*of, name + "_TRACE_FST", (v3Global.opt.trace() && (v3Global.opt.traceFormat() != TraceFormat::VCD)) ? "1":"0");
+
+        *of << "\n### Sources...\n";
+        std::vector<string> classes_fast, classes_slow, support_fast, support_slow, global;
+        for (AstFile* nodep = v3Global.rootp()->filesp(); nodep;
+             nodep = VN_CAST(nodep->nextp(), File)) {
+            AstCFile* cfilep = VN_CAST(nodep, CFile);
+            if (cfilep && cfilep->source()) {
+                if (cfilep->support()) {
+                    if (cfilep->slow()) {
+                        support_slow.push_back(cfilep->name());
+                    } else {
+                        support_fast.push_back(cfilep->name());
+                    }
+                } else {
+                    if (cfilep->slow()) {
+                        classes_slow.push_back(cfilep->name());
+                    } else {
+                        classes_fast.push_back(cfilep->name());
+                    }
+                }
+            }
+        }
+
+        global.push_back("${VERILATOR_ROOT}/include/verilated.cpp");
+        if (v3Global.dpi()) {
+            global.push_back("${VERILATOR_ROOT}/include/verilated_dpi.cpp");
+        }
+        if (v3Global.opt.vpi()) {
+            global.push_back("${VERILATOR_ROOT}/include/verilated_vpi.cpp");
+        }
+        if (v3Global.opt.savable()) {
+            global.push_back("${VERILATOR_ROOT}/include/verilated_save.cpp");
+        }
+        if (v3Global.opt.coverage()) {
+            global.push_back("${VERILATOR_ROOT}/include/verilated_cov.cpp");
+        }
+        if (v3Global.opt.trace()) {
+            global.push_back("${VERILATOR_ROOT}/include/"
+                             + v3Global.opt.traceSourceName()+"_c.cpp");
+            if (v3Global.opt.systemC()) {
+                if (v3Global.opt.traceFormat() != TraceFormat::VCD) {
+                    v3error("Unsupported: This trace format is not supported in SystemC, use VCD format.");
+                }
+                global.push_back("${VERILATOR_ROOT}/include/"
+                                    + v3Global.opt.traceSourceName()+"_sc.cpp");
+            }
+        }
+        if (v3Global.opt.mtasks()) {
+            global.push_back("${VERILATOR_ROOT}/include/verilated_threads.cpp");
+        }
+        if (!v3Global.opt.protectLib().empty()) {
+            global.push_back(v3Global.opt.makeDir()+"/"+v3Global.opt.protectLib()+".cpp");
+        }
+
+        *of << "# Global classes, need linked once per executable\n";
+        cmake_set_raw(*of, name + "_GLOBAL", deslash(cmake_list(global)));
+        *of << "# Generated module classes, non-fast-path, compile with low/medium optimization\n";
+        cmake_set_raw(*of, name + "_CLASSES_SLOW", deslash(cmake_list(classes_slow)));
+        *of << "# Generated module classes, fast-path, compile with highest optimization\n";
+        cmake_set_raw(*of, name + "_CLASSES_FAST", deslash(cmake_list(classes_fast)));
+        *of << "# Generated support classes, non-fast-path, compile with low/medium optimization\n";
+        cmake_set_raw(*of, name + "_SUPPORT_SLOW", deslash(cmake_list(support_slow)));
+        *of << "# Generated support classes, fast-path, compile with highest optimization\n";
+        cmake_set_raw(*of, name + "_SUPPORT_FAST", deslash(cmake_list(support_fast)));
+
+        *of << "# All dependencies\n";
+        cmake_set_raw(*of, name + "_DEPS", deslash(cmake_list(V3File::getAllDeps())));
+
+        *of << "# User .cpp files (from .cpp's on Verilator command line)\n";
+        cmake_set_raw(*of, name + "_USER_CLASSES", deslash(cmake_list(v3Global.opt.cppFiles())));
+    }
+public:
+    explicit CMakeEmitter() {
+        emitOverallCMake();
+    }
+    virtual ~CMakeEmitter() {}
+};
+
+void V3EmitCMake::emit() {
+    UINFO(2,__FUNCTION__<<": "<<endl);
+    CMakeEmitter emitter;
+}
diff --git a/src/V3EmitCMake.h b/src/V3EmitCMake.h
new file mode 100644
index 000000000..9f90bb2e6
--- /dev/null
+++ b/src/V3EmitCMake.h
@@ -0,0 +1,34 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//*************************************************************************
+// DESCRIPTION: Verilator: Emit CMake file list
+//
+// Code available from: http://www.veripool.org/verilator
+//
+//*************************************************************************
+//
+// Copyright 2003-2019 by Wilson Snyder.  This program is free software; you can
+// redistribute it and/or modify it under the terms of either the GNU
+// Lesser General Public License Version 3 or the Perl Artistic License
+// Version 2.0.
+//
+// Verilator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//*************************************************************************
+
+#ifndef _V3EMITCMAKE_H_
+#define _V3EMITCMAKE_H_ 1
+
+#include "config_build.h"
+#include "verilatedos.h"
+
+//============================================================================
+
+class V3EmitCMake {
+public:
+    static void emit();
+};
+
+#endif  // Guard
diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp
index 6fe968e53..7666da49f 100644
--- a/src/V3EmitMk.cpp
+++ b/src/V3EmitMk.cpp
@@ -26,16 +26,10 @@
 #include "V3EmitMk.h"
 #include "V3EmitCBase.h"
 
-#include <algorithm>
-#include <cmath>
-#include <cstdarg>
-#include <map>
-#include <vector>
-
 //######################################################################
 // Emit statements and math operators
 
-class EmitMkVisitor : public EmitCBaseVisitor {
+class EmitMk {
 public:
 
     // METHODS
@@ -252,23 +246,18 @@ public:
         of.putsHeader();
     }
 
-    //--------------------
-    virtual void visit(AstNode* nodep) {  // LCOV_EXCL_LINE
-        nodep->v3fatalSrc("No visitors implemented.");
-    }
-
 public:
-    explicit EmitMkVisitor(AstNetlist*) {
+    explicit EmitMk() {
         emitClassMake();
         emitOverallMake();
     }
-    virtual ~EmitMkVisitor() {}
+    virtual ~EmitMk() {}
 };
 
 //######################################################################
 // Gate class functions
 
-void V3EmitMk::emitmk(AstNetlist* nodep) {
+void V3EmitMk::emitmk() {
     UINFO(2,__FUNCTION__<<": "<<endl);
-    EmitMkVisitor visitor (nodep);
+    EmitMk emitter;
 }
diff --git a/src/V3EmitMk.h b/src/V3EmitMk.h
index 29bcb4113..1653af5ec 100644
--- a/src/V3EmitMk.h
+++ b/src/V3EmitMk.h
@@ -24,14 +24,11 @@
 #include "config_build.h"
 #include "verilatedos.h"
 
-#include "V3Error.h"
-#include "V3Ast.h"
-
 //============================================================================
 
 class V3EmitMk {
 public:
-    static void emitmk(AstNetlist* nodep);
+    static void emitmk();
 };
 
 #endif  // Guard
diff --git a/src/V3File.cpp b/src/V3File.cpp
index 3c4f1da9f..65c2f617e 100644
--- a/src/V3File.cpp
+++ b/src/V3File.cpp
@@ -65,17 +65,19 @@ class V3FileDependImp {
     class DependFile {
         // A single file
         bool            m_target;       // True if write, else read
+        bool            m_exists;
         string          m_filename;     // Filename
         struct stat     m_stat;         // Stat information
     public:
         DependFile(const string& filename, bool target)
-            : m_target(target), m_filename(filename) {
+            : m_target(target), m_exists(true), m_filename(filename) {
             m_stat.st_ctime = 0;
             m_stat.st_mtime = 0;
         }
         ~DependFile() {}
         const string& filename() const { return m_filename; }
         bool target() const { return m_target; }
+        bool exists() const { return m_exists; }
         off_t size() const { return m_stat.st_size; }
         ino_t ino() const { return m_stat.st_ino; }
         time_t cstime() const { return m_stat.st_ctime; }  // Seconds
@@ -89,6 +91,7 @@ class V3FileDependImp {
                 if (err!=0) {
                     memset(&m_stat, 0, sizeof(m_stat));
                     m_stat.st_mtime = 1;
+                    m_exists = false;
                     // Not an error... This can occur due to `line directives in the .vpp files
                     UINFO(1,"-Info: File not statable: "<<filename()<<endl);
                 }
@@ -125,6 +128,7 @@ public:
         }
     }
     void writeDepend(const string& filename);
+    std::vector<string> getAllDeps() const;
     void writeTimes(const string& filename, const string& cmdlineIn);
     bool checkTimes(const string& filename, const string& cmdlineIn);
 };
@@ -168,6 +172,17 @@ inline void V3FileDependImp::writeDepend(const string& filename) {
     }
 }
 
+inline std::vector<string> V3FileDependImp::getAllDeps() const {
+    std::vector<string> r;
+    for (std::set<DependFile>::const_iterator iter=m_filenameList.begin();
+         iter!=m_filenameList.end(); ++iter) {
+        if (!iter->target() && iter->exists()) {
+            r.push_back(iter->filename());
+        }
+    }
+    return r;
+}
+
 inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) {
     const vl_unique_ptr<std::ofstream> ofp (V3File::new_ofstream(filename));
     if (ofp->fail()) v3fatal("Can't write "<<filename);
@@ -283,6 +298,9 @@ void V3File::addTgtDepend(const string& filename) {
 void V3File::writeDepend(const string& filename) {
     dependImp.writeDepend(filename);
 }
+std::vector<string> V3File::getAllDeps() {
+    return dependImp.getAllDeps();
+}
 void V3File::writeTimes(const string& filename, const string& cmdlineIn) {
     dependImp.writeTimes(filename, cmdlineIn);
 }
diff --git a/src/V3File.h b/src/V3File.h
index 3659ad0a0..05ec77ee8 100644
--- a/src/V3File.h
+++ b/src/V3File.h
@@ -29,6 +29,7 @@
 #include <stack>
 #include <set>
 #include <list>
+#include <vector>
 #include <fstream>
 
 //============================================================================
@@ -65,6 +66,7 @@ public:
     static void addSrcDepend(const string& filename);
     static void addTgtDepend(const string& filename);
     static void writeDepend(const string& filename);
+    static std::vector<string> getAllDeps();
     static void writeTimes(const string& filename, const string& cmdlineIn);
     static bool checkTimes(const string& filename, const string& cmdlineIn);
 
diff --git a/src/V3Options.cpp b/src/V3Options.cpp
index 1b8431cc4..fc4903091 100644
--- a/src/V3Options.cpp
+++ b/src/V3Options.cpp
@@ -534,6 +534,12 @@ void V3Options::notify() {
         && !cdc()) {
         v3fatal("verilator: Need --cc, --sc, --cdc, --lint-only, --xml_only or --E option");
     }
+
+    // Make sure at least one make system is enabled
+    if (!m_gmake && !m_cmake) {
+        m_gmake = true;
+    }
+
     if (protectIds()) {
         FileLine* cmdfl = new FileLine(FileLine::commandLineFilename());
         if (allPublic()) {
@@ -889,6 +895,16 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
             else if (!strcmp(sw, "-l2name")) {  // Historical and undocumented
                 m_l2Name = "v";
             }
+            else if (!strcmp(sw, "-make")) {
+                shift;
+                if (!strcmp(argv[i], "cmake")) {
+                    m_cmake = true;
+                } else if (!strcmp(argv[i], "gmake")) {
+                    m_gmake = true;
+                } else {
+                    fl->v3fatal("Unknown --make system specified: '"<<argv[i]<<"'");
+                }
+            }
             else if (!strcmp(sw, "-no-l2name")) {  // Historical and undocumented
                 m_l2Name = "";
             }
@@ -1323,6 +1339,7 @@ V3Options::V3Options() {
     m_bboxSys = false;
     m_bboxUnsup = false;
     m_cdc = false;
+    m_cmake = false;
     m_coverageLine = false;
     m_coverageToggle = false;
     m_coverageUnderscore = false;
@@ -1341,6 +1358,7 @@ V3Options::V3Options() {
     m_ignc = false;
     m_inhibitSim = false;
     m_lintOnly = false;
+    m_gmake = false;
     m_makeDepend = true;
     m_makePhony = false;
     m_orderClockDly = true;
diff --git a/src/V3Options.h b/src/V3Options.h
index a88a40edf..de71e864f 100644
--- a/src/V3Options.h
+++ b/src/V3Options.h
@@ -109,6 +109,7 @@ class V3Options {
     bool        m_bboxSys;      // main switch: --bbox-sys
     bool        m_bboxUnsup;    // main switch: --bbox-unsup
     bool        m_cdc;          // main switch: --cdc
+    bool        m_cmake;        // main switch: --make cmake
     bool        m_coverageLine; // main switch: --coverage-block
     bool        m_coverageToggle;// main switch: --coverage-toggle
     bool        m_coverageUnderscore;// main switch: --coverage-underscore
@@ -127,6 +128,7 @@ class V3Options {
     bool        m_ignc;         // main switch: --ignc
     bool        m_inhibitSim;   // main switch: --inhibit-sim
     bool        m_lintOnly;     // main switch: --lint-only
+    bool        m_gmake;        // main switch: --make gmake
     bool        m_orderClockDly;// main switch: --order-clock-delay
     bool        m_outFormatOk;  // main switch: --cc, --sc or --sp was specified
     bool        m_pinsScUint;   // main switch: --pins-sc-uint
@@ -282,6 +284,7 @@ class V3Options {
     bool bboxSys() const { return m_bboxSys; }
     bool bboxUnsup() const { return m_bboxUnsup; }
     bool cdc() const { return m_cdc; }
+    bool cmake() const { return m_cmake; }
     bool coverage() const { return m_coverageLine || m_coverageToggle || m_coverageUser; }
     bool coverageLine() const { return m_coverageLine; }
     bool coverageToggle() const { return m_coverageToggle; }
@@ -298,6 +301,7 @@ class V3Options {
     bool dpiHdrOnly() const { return m_dpiHdrOnly; }
     bool dumpDefines() const { return m_dumpDefines; }
     bool exe() const { return m_exe; }
+    bool gmake() const { return m_gmake; }
     bool threadsDpiPure() const { return m_threadsDpiPure; }
     bool threadsDpiUnpure() const { return m_threadsDpiUnpure; }
     bool threadsCoarsen() const { return m_threadsCoarsen; }
diff --git a/src/Verilator.cpp b/src/Verilator.cpp
index 54e5b34b2..99efc6830 100644
--- a/src/Verilator.cpp
+++ b/src/Verilator.cpp
@@ -43,6 +43,7 @@
 #include "V3DepthBlock.h"
 #include "V3Descope.h"
 #include "V3EmitC.h"
+#include "V3EmitCMake.h"
 #include "V3EmitMk.h"
 #include "V3EmitV.h"
 #include "V3EmitXml.h"
@@ -565,7 +566,12 @@ void process() {
         && !v3Global.opt.xmlOnly()
         && !v3Global.opt.dpiHdrOnly()) {
         // Makefile must be after all other emitters
-        V3EmitMk::emitmk(v3Global.rootp());
+        if (v3Global.opt.cmake()) {
+            V3EmitCMake::emit();
+        }
+        if (v3Global.opt.gmake()) {
+            V3EmitMk::emitmk();
+        }
     }
 
     // Note early return above when opt.cdc()
@@ -596,6 +602,7 @@ int main(int argc, char** argv, char** env) {
 
     // Validate settings (aka Boost.Program_options)
     v3Global.opt.notify();
+
     V3Error::abortIfErrors();
 
     // Can we skip doing everything if times are ok?
diff --git a/test_regress/CMakeLists.txt b/test_regress/CMakeLists.txt
new file mode 100644
index 000000000..db053f6dd
--- /dev/null
+++ b/test_regress/CMakeLists.txt
@@ -0,0 +1,105 @@
+######################################################################
+#
+# DESCRIPTION: CMake script for regression tests
+#
+# This CMake file is meant to be consumed by regression tests.
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+cmake_minimum_required(VERSION 3.8)
+set(TEST_REQUIRED_VARS NAME CSOURCES OPT_FAST VERILATOR_ROOT VERILATOR_ARGS
+                            VERILATOR_SOURCES SYSTEMC VERBOSE VERILATION)
+foreach(var ${TEST_REQUIRED_VARS})
+  if (NOT DEFINED TEST_${var})
+    message(FATAL_ERROR "TEST_${var} not defined. This CMakeLists.txt file is meant to be run by driver.pl.")
+  endif()
+endforeach()
+
+project("${TEST_NAME}")
+
+if(TEST_VERBOSE)
+  add_definitions(-DTEST_VERBOSE=1)
+endif()
+
+separate_arguments(TEST_VERILATOR_ARGS UNIX_COMMAND "${TEST_VERILATOR_ARGS}")
+
+# filter out empty arguments
+list(FILTER TEST_VERILATOR_ARGS EXCLUDE REGEX "$^")
+
+set(TEST_PREFIX ${TEST_NAME})
+
+# If --ARG <val> is present, set OUT = <val>
+function(getarg LST ARG OUT)
+  list(FIND ${LST} ${ARG} _INDEX)
+  if(NOT _INDEX EQUAL -1)
+    list(REMOVE_AT ${LST} ${_INDEX})
+    list(GET ${LST} ${_INDEX} VAL)
+    set(${OUT} ${VAL} PARENT_SCOPE)
+  endif()
+endfunction()
+
+# Normalise -- to -
+string(REGEX REPLACE "(^|;)--" "\\1-"
+       TEST_VERILATOR_ARGS_NORM
+       "${TEST_VERILATOR_ARGS}")
+
+getarg(TEST_VERILATOR_ARGS_NORM "-prefix" TEST_PREFIX)
+getarg(TEST_VERILATOR_ARGS_NORM "-threads" TEST_THREADS)
+
+# Strip unwanted args with 1 parameter
+string(REGEX REPLACE "(^|;)--?(Mdir|make|prefix|threads);[^;]*" ""
+       TEST_VERILATOR_ARGS
+       "${TEST_VERILATOR_ARGS}")
+# Strip unwanted args
+string(REGEX REPLACE "(^|;)--?(sc|cc)" ""
+       TEST_VERILATOR_ARGS
+       "${TEST_VERILATOR_ARGS}")
+
+separate_arguments(TEST_VERILATOR_SOURCES UNIX_COMMAND "${TEST_VERILATOR_SOURCES}")
+# filter out empty sources
+list(FILTER TEST_VERILATOR_SOURCES EXCLUDE REGEX "$^")
+
+find_package(verilator REQUIRED HINTS ${TEST_VERILATOR_ROOT})
+
+set(verilate_ARGS MAIN)
+if(TEST_PREFIX)
+  list(APPEND verilate_ARGS PREFIX ${TEST_PREFIX})
+endif()
+if(TEST_OPT_FAST)
+  list(APPEND verilate_ARGS OPT_FAST ${TEST_OPT_FAST})
+endif()
+if(TEST_THREADS)
+  list(APPEND verilate_ARGS THREADS ${TEST_THREADS})
+endif()
+if(TEST_SYSTEMC)
+  list(APPEND verilate_ARGS SYSTEMC)
+endif()
+
+set(TARGET_NAME "V${TEST_NAME}")
+
+add_executable(${TARGET_NAME} ${TEST_CSOURCES})
+
+if(TEST_VERILATION)
+  verilate(${TARGET_NAME} ${verilate_ARGS}
+           VERILATOR_ARGS ${TEST_VERILATOR_ARGS}
+           DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+           SOURCES ${TEST_VERILATOR_SOURCES})
+endif()
+
+if(TEST_SYSTEMC)
+  verilator_link_systemc("${TARGET_NAME}")
+endif()
+
+string(TOUPPER "${TEST_NAME}" TEST_NAME_UC)
+
+target_compile_definitions(${TARGET_NAME} PRIVATE
+  "TEST_OBJ_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+  "VM_PREFIX=${TEST_PREFIX}"
+  "VM_PREFIX_INCLUDE=<${TEST_PREFIX}.h>"
+  "${TEST_NAME_UC}"
+)
diff --git a/test_regress/driver.pl b/test_regress/driver.pl
index cb23b4e6f..3b62cf01a 100755
--- a/test_regress/driver.pl
+++ b/test_regress/driver.pl
@@ -19,6 +19,7 @@ use Data::Dumper; $Data::Dumper::Sortkeys=1;
 use FindBin qw($RealBin);
 use strict;
 use vars qw($Debug %Vars $Driver $Fork);
+use version;
 use POSIX qw(strftime);
 use lib ".";
 use Time::HiRes qw(usleep);
@@ -601,6 +602,7 @@ sub new {
         verilator_flags2 => [],
         verilator_flags3 => ["--clk clk"],
         verilator_make_gmake => 1,
+        verilator_make_cmake => 0,
         verilated_debug => $Opt_Verilated_Debug,
         stdout_filename => undef,  # Redirect stdout
         %$self};
@@ -768,6 +770,21 @@ sub _read_status {
 #----------------------------------------------------------------------
 # Methods invoked by tests
 
+sub compile_vlt_cmd {
+    my $self = (ref $_[0]? shift : $Self);
+    my %param = (%{$self}, @_);  # Default arguments are from $self
+    return 1 if $self->errors || $self->skips || $self->unsupporteds;
+
+    my @vlt_cmd = (
+        "perl", "$ENV{VERILATOR_ROOT}/bin/verilator",
+        $self->compile_vlt_flags(%param),
+        $param{top_filename},
+        @{$param{v_other_filenames}},
+        $param{stdout_filename}?"> ".$param{stdout_filename}:""
+    );
+    return @vlt_cmd;
+}
+
 sub compile_vlt_flags {
     my $self = (ref $_[0]? shift : $Self);
     my %param = (%{$self}, @_);  # Default arguments are from $self
@@ -798,6 +815,8 @@ sub compile_vlt_flags {
     unshift @verilator_flags, "--threads $threads" if $param{vltmt} && $checkflags !~ /-threads /;
     unshift @verilator_flags, "--trace-fst-thread" if $param{vltmt} && $checkflags =~ /-trace-fst/;
     unshift @verilator_flags, "--debug-partition" if $param{vltmt};
+    unshift @verilator_flags, "--make gmake" if $param{verilator_make_gmake};
+    unshift @verilator_flags, "--make cmake" if $param{verilator_make_cmake};
     if (defined $opt_optimize) {
         my $letters = "";
         if ($opt_optimize =~ /[a-zA-Z]/) {
@@ -812,7 +831,7 @@ sub compile_vlt_flags {
         unshift @verilator_flags, "--O".$letters;
     }
 
-    my @cmdargs = ("perl", "$ENV{VERILATOR_ROOT}/bin/verilator",
+    my @cmdargs = (
                    "--prefix ".$param{VM_PREFIX},
                    @verilator_flags,
                    @{$param{verilator_flags2}},
@@ -822,9 +841,6 @@ sub compile_vlt_flags {
                    # Flags from driver cmdline override default flags and
                    # flags from the test itself
                    @Opt_Driver_Verilator_Flags,
-                   $param{top_filename},
-                   @{$param{v_other_filenames}},
-                   ($param{stdout_filename}?"> ".$param{stdout_filename}:""),
         );
     return @cmdargs;
 }
@@ -849,7 +865,7 @@ sub compile {
     return 1 if $self->errors || $self->skips || $self->unsupporteds;
     $self->oprint("Compile\n") if $self->{verbose};
 
-    compile_vlt_flags(%param);
+    compile_vlt_cmd(%param);
 
     if (!$self->{make_top_shell}) {
         $param{top_shell_filename}
@@ -972,7 +988,6 @@ sub compile {
                           ]);
     }
     elsif ($param{vlt_all}) {
-        my @cmdargs = $self->compile_vlt_flags(%param);
 
         if ($self->sc && !$self->have_sc) {
             $self->skip("Test requires SystemC; ignore error since not installed\n");
@@ -984,33 +999,79 @@ sub compile {
             return 1;
         }
 
+        if ($param{verilator_make_cmake} && !$self->have_cmake) {
+            $self->skip("Test requires CMake; ignore error since not available or version too old\n");
+            return 1;
+        }
+
         if (!$param{fails} && $param{make_main}) {
             $self->_make_main();
         }
 
-        $self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log",
-                    fails=>$param{fails},
-                    tee=>$param{tee},
-                    expect=>$param{expect},
-                    expect_filename=>$param{expect_filename},
-                    cmd=>\@cmdargs) if $::Opt_Verilation;
-        return 1 if $self->errors || $self->skips || $self->unsupporteds;
+        if ($param{verilator_make_gmake}
+            || (!$param{verilator_make_gmake} && !$param{verilator_make_cmake})) {
+            my @vlt_cmd = $self->compile_vlt_cmd(%param);
+            $self->oprint("Running Verilator (gmake)\n") if $self->{verbose};
+            $self->_run(logfile => "$self->{obj_dir}/vlt_compile.log",
+                        fails => $param{fails},
+                        tee => $param{tee},
+                        expect => $param{expect},
+                        expect_filename => $param{expect_filename},
+                        cmd => \@vlt_cmd) if $::Opt_Verilation;
+            return 1 if $self->errors || $self->skips || $self->unsupporteds;
+        }
+
+        if ($param{verilator_make_cmake}) {
+            my @vlt_args = $self->compile_vlt_flags(%param);
+            $self->oprint("Running cmake\n") if $self->{verbose};
+            mkdir $self->{obj_dir};
+            my @csources = ();
+            unshift @csources, $self->{main_filename} if $param{make_main};
+            $self->_run(logfile => "$self->{obj_dir}/vlt_cmake.log",
+                        fails => $param{fails},
+                        tee => $param{tee},
+                        expect => $param{expect},
+                        expect_filename => $param{expect_filename},
+                        cmd => ["cd \"".$self->{obj_dir}."\" && cmake",
+                                "\"".$self->{t_dir}."/..\"",
+                                "-DTEST_VERILATOR_ROOT=$ENV{VERILATOR_ROOT}",
+                                "-DTEST_NAME=$self->{name}",
+                                "-DTEST_CSOURCES=\"@csources\"",
+                                "-DTEST_VERILATOR_ARGS=\"@vlt_args\"",
+                                "-DTEST_VERILATOR_SOURCES=\"$param{top_filename} @{$param{v_other_filenames}}\"",
+                                "-DTEST_VERBOSE=\"".($self->{verbose} ? 1 : 0)."\"",
+                                "-DTEST_SYSTEMC=\"" .($self->sc ? 1 : 0). "\"",
+                                "-DCMAKE_PREFIX_PATH=\"".(($ENV{SYSTEMC_INCLUDE}||$ENV{SYSTEMC}||'')."/..\""),
+                                "-DTEST_OPT_FAST=\"" . ($param{benchmark}?"-O2":"") . "\"",
+                                "-DTEST_VERILATION=\"" . $::Opt_Verilation . "\"",
+                        ]);
+            return 1 if $self->errors || $self->skips || $self->unsupporteds;
+        }
 
         if (!$param{fails} && $param{verilator_make_gmake}) {
-            $self->oprint("GCC\n") if $self->{verbose};
-            $self->_run(logfile=>"$self->{obj_dir}/vlt_gcc.log",
-                        cmd=>["make",
-                              "-C ".$self->{obj_dir},
-                              "-f ".$::RealBin."/Makefile_obj",
-                              ($self->{verbose} ? "" : "--no-print-directory"),
-                              "VM_PREFIX=$self->{VM_PREFIX}",
-                              "TEST_OBJ_DIR=$self->{obj_dir}",
-                              "CPPFLAGS_DRIVER=-D".uc($self->{name}),
-                              ($opt_verbose ? "CPPFLAGS_DRIVER2=-DTEST_VERBOSE=1":""),
-                              ($param{make_main}?"":"MAKE_MAIN=0"),
-                              ($param{benchmark}?"OPT_FAST=-O2":""),
-                              "$self->{VM_PREFIX}",  # bypass default rule, as we don't need archive
-                              ($param{make_flags}||""),
+            $self->oprint("Running make (gmake)\n") if $self->{verbose};
+            $self->_run(logfile => "$self->{obj_dir}/vlt_gcc.log",
+                        cmd => ["make",
+                                "-C ".$self->{obj_dir},
+                                "-f ".$::RealBin."/Makefile_obj",
+                                ($self->{verbose} ? "" : "--no-print-directory"),
+                                "VM_PREFIX=$self->{VM_PREFIX}",
+                                "TEST_OBJ_DIR=$self->{obj_dir}",
+                                "CPPFLAGS_DRIVER=-D".uc($self->{name}),
+                                ($opt_verbose ? "CPPFLAGS_DRIVER2=-DTEST_VERBOSE=1":""),
+                                ($param{make_main}?"":"MAKE_MAIN=0"),
+                                ($param{benchmark}?"OPT_FAST=-O2":""),
+                                "$self->{VM_PREFIX}",  # bypass default rule, as we don't need archive
+                                ($param{make_flags}||""),
+                        ]);
+        }
+
+        if (!$param{fails} && $param{verilator_make_cmake}) {
+            $self->oprint("Running cmake --build\n") if $self->{verbose};
+            $self->_run(logfile => "$self->{obj_dir}/vlt_cmake_build.log",
+                        cmd => ["cmake",
+                                "--build", $self->{obj_dir},
+                                ($self->{verbose}?"--verbose":""),
                         ]);
         }
     }
@@ -1273,6 +1334,23 @@ sub have_sc {
     return 0;
 }
 
+sub have_cmake {
+    return cmake_version() >= version->declare("3.8");
+}
+
+sub cmake_version {
+    chomp(my $cmake_bin = `which cmake`);
+    if (!$cmake_bin) {
+        return undef;
+    }
+    my $cmake_version = `cmake --version`;
+    if ($cmake_version !~ /cmake version (\d+)\.(\d+)/) {
+        return undef;
+    }
+    $cmake_version = "$1.$2";
+    return version->declare($cmake_version);
+}
+
 sub trace_filename {
     my $self = shift;
     return "$self->{obj_dir}/simx.fst" if $self->{trace_format} =~ /^fst/;
diff --git a/test_regress/t/t_embed1.pl b/test_regress/t/t_embed1.pl
index 9bdb42848..ee7ec7bc5 100755
--- a/test_regress/t/t_embed1.pl
+++ b/test_regress/t/t_embed1.pl
@@ -17,7 +17,7 @@ mkdir $child_dir;
 
 # Compile the child
 {
-    my @cmdargs = $Self->compile_vlt_flags
+    my @cmdargs = $Self->compile_vlt_cmd
         (VM_PREFIX => "$Self->{VM_PREFIX}_child",
          top_filename => "$Self->{name}_child.v",
          verilator_flags => ["-cc", "-Mdir", "${child_dir}", "--debug-check"],
diff --git a/test_regress/t/t_flag_make_cmake.pl b/test_regress/t/t_flag_make_cmake.pl
new file mode 100755
index 000000000..be0628665
--- /dev/null
+++ b/test_regress/t/t_flag_make_cmake.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2008 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+
+scenarios(simulator => 1);
+
+compile(
+    verilator_make_gmake => 0,
+    verilator_make_cmake => 1,
+    );
+
+
+my $cmakecache = $Self->{obj_dir}."/CMakeCache.txt";
+if (! -e $cmakecache) {
+    error("$cmakecache does not exist")
+}
+
+execute(
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_flag_make_cmake.v b/test_regress/t/t_flag_make_cmake.v
new file mode 100644
index 000000000..51d5f55fe
--- /dev/null
+++ b/test_regress/t/t_flag_make_cmake.v
@@ -0,0 +1,16 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2019 by Wilson Snyder.
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   always @ (posedge clk) begin
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_flag_make_cmake_sc.pl b/test_regress/t/t_flag_make_cmake_sc.pl
new file mode 100755
index 000000000..1ece57841
--- /dev/null
+++ b/test_regress/t/t_flag_make_cmake_sc.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+
+# This test tests CMake support for SystemC
+
+scenarios(simulator => 1);
+
+compile(
+    verilator_make_gmake => 0,
+    verilator_make_cmake => 1,
+    verilator_flags2 => ["-sc"],
+    );
+
+execute(
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_flag_make_cmake_sc.v b/test_regress/t/t_flag_make_cmake_sc.v
new file mode 100644
index 000000000..51d5f55fe
--- /dev/null
+++ b/test_regress/t/t_flag_make_cmake_sc.v
@@ -0,0 +1,16 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2019 by Wilson Snyder.
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   always @ (posedge clk) begin
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/verilator-config-version.cmake.in b/verilator-config-version.cmake.in
new file mode 100644
index 000000000..89862189a
--- /dev/null
+++ b/verilator-config-version.cmake.in
@@ -0,0 +1,26 @@
+######################################################################
+#
+# DESCRIPTION: CMake version configuration file for Verilator
+#
+# This allows specifying a minimum Verilator version.
+# Include it in your CMakeLists.txt using:
+#
+#     find_package(verilate 4.0)
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+set(PACKAGE_VERSION "@PACKAGE_VERSION@")
+
+if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
+  set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+  set(PACKAGE_VERSION_COMPATIBLE TRUE)
+  if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
+    set(PACKAGE_VERSION_EXACT TRUE)
+  endif()
+endif()
diff --git a/verilator-config.cmake.in b/verilator-config.cmake.in
new file mode 100644
index 000000000..0f25e3195
--- /dev/null
+++ b/verilator-config.cmake.in
@@ -0,0 +1,392 @@
+######################################################################
+#
+# DESCRIPTION: CMake configuration file for Verilator
+#
+# Include it in your CMakeLists.txt using:
+#
+#     find_package(verilate)
+#
+#  This script adds a verilate function.
+#
+#     add_executable(simulator <your-c-sources>)
+#     verilate(simulator SOURCES <your-hdl-sources>)
+#
+# Copyright 2003-2019 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+#
+######################################################################
+
+cmake_minimum_required(VERSION 3.8)
+
+# Prefer VERILATOR_ROOT from environment
+if (DEFINED ENV{VERILATOR_ROOT})
+  set(VERILATOR_ROOT "$ENV{VERILATOR_ROOT}" CACHE PATH "VERILATOR_ROOT")
+endif()
+
+set(VERILATOR_ROOT "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "VERILATOR_ROOT")
+
+find_program(VERILATOR_BIN NAMES verilator_bin verilator_bin.exe
+  HINTS ${VERILATOR_ROOT}/bin ENV VERILATOR_ROOT
+  NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
+
+if (NOT VERILATOR_ROOT)
+  message(FATAL_ERROR "VERILATOR_ROOT cannot be detected. Set it to the appropriate directory (e.g. /usr/share/verilator) as an environment variable or CMake define.")
+endif()
+
+if (NOT VERILATOR_BIN)
+  message(FATAL_ERROR "Cannot find verilator_bin excecutable.")
+endif()
+
+set(verilator_FOUND 1)
+
+include(CheckCXXSourceCompiles)
+function(_verilator_check_cxx_libraries LIBRARIES RESVAR)
+  # Check whether a particular link option creates a valid executable
+  set(_VERILATOR_CHECK_CXX_LINK_OPTIONS_SRC "int main() {return 0;}\n")
+  set(CMAKE_REQUIRED_FLAGS)
+  set(CMAKE_REQUIRED_DEFINITIONS)
+  set(CMAKE_REQUIRED_INCLUDES)
+  set(CMAKE_REQUIRED_LINK_OPTIONS)
+  set(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES})
+  set(CMAKE_REQUIRED_QUIET)
+  check_cxx_source_compiles("${_VERILATOR_CHECK_CXX_LINK_OPTIONS_SRC}" "${RESVAR}")
+  set("${RESVAR}" "${${RESVAR}}" PARENT_SCOPE)
+endfunction()
+
+# Check compiler flag support. Skip on MSVC, these are all GCC flags.
+if (NOT CMAKE_CXX_COMPILER_ID MATCHES MSVC)
+  if (NOT DEFINED VERILATOR_CFLAGS OR NOT DEFINED VERILATOR_MT_CFLAGS)
+    include(CheckCXXCompilerFlag)
+    foreach (FLAG @CFG_CXX_FLAGS_CMAKE@)
+      string(MAKE_C_IDENTIFIER ${FLAG} FLAGNAME)
+      check_cxx_compiler_flag(${FLAG} ${FLAGNAME})
+      if (${FLAGNAME})
+        list(APPEND VERILATOR_CFLAGS ${FLAG})
+      endif()
+    endforeach()
+    foreach (FLAG @CFG_LDFLAGS_THREADS_CMAKE@)
+      string(MAKE_C_IDENTIFIER ${FLAG} FLAGNAME)
+      _verilator_check_cxx_libraries("${FLAG}" ${FLAGNAME})
+      if (${FLAGNAME})
+        list(APPEND VERILATOR_MT_CFLAGS ${FLAG})
+      endif()
+    endforeach()
+  endif()
+endif()
+
+define_property(TARGET
+  PROPERTY VERILATOR_THREADED
+  BRIEF_DOCS "Verilator multithreading enabled"
+  FULL_DOCS "Verilator multithreading enabled"
+)
+
+define_property(TARGET
+  PROPERTY VERILATOR_COVERAGE
+  BRIEF_DOCS "Verilator coverage enabled"
+  FULL_DOCS "Verilator coverage enabled"
+)
+
+define_property(TARGET
+  PROPERTY VERILATOR_TRACE
+  BRIEF_DOCS "Verilator trace enabled"
+  FULL_DOCS "Verilator trace enabled"
+)
+
+define_property(TARGET
+  PROPERTY VERILATOR_TRACE_VCD
+  BRIEF_DOCS "Verilator VCD trace enabled"
+  FULL_DOCS "Verilator VCD trace enabled"
+)
+
+define_property(TARGET
+  PROPERTY VERILATOR_TRACE_FST
+  BRIEF_DOCS "Verilator FST trace enabled"
+  FULL_DOCS "Verilator FST trace enabled"
+)
+
+define_property(TARGET
+  PROPERTY VERILATOR_SYSTEMC
+  BRIEF_DOCS "Verilator SystemC enabled"
+  FULL_DOCS "Verilator SystemC enabled"
+)
+
+function(verilate TARGET)
+  cmake_parse_arguments(VERILATE "COVERAGE;TRACE;TRACE_FST;SYSTEMC"
+                                 "PREFIX;TOP_MODULE;THREADS;DIRECTORY"
+                                 "SOURCES;VERILATOR_ARGS;INCLUDE_DIRS;OPT_SLOW;OPT_FAST"
+                                 ${ARGN})
+  if (NOT VERILATE_SOURCES)
+    message(FATAL_ERROR "Need at least one source")
+  endif()
+
+  if (NOT VERILATE_PREFIX)
+    list(GET VERILATE_SOURCES 0 TOPSRC)
+    get_filename_component(_SRC_NAME ${TOPSRC} NAME_WE)
+    set(VERILATE_PREFIX V${_SRC_NAME})
+  endif()
+
+  if (VERILATE_TOP_MODULE)
+    list(APPEND VERILATOR_ARGS --top-module ${VERILATE_TOP_MODULE})
+  endif()
+
+  if (VERILATE_THREADS)
+    list(APPEND VERILATOR_ARGS --threads ${VERILATE_THREADS})
+  endif()
+
+  if (VERILATE_COVERAGE)
+    list(APPEND VERILATOR_ARGS --coverage)
+  endif()
+
+  if (VERILATE_TRACE AND VERILATE_TRACE_FST)
+    message(FATAL_ERROR "Cannot have both TRACE and TRACE_FST")
+  endif()
+
+  if (VERILATE_TRACE)
+    list(APPEND VERILATOR_ARGS --trace)
+  endif()
+
+  if (VERILATE_TRACE_FST)
+    list(APPEND VERILATOR_ARGS --trace-fst)
+  endif()
+
+  if (VERILATE_SYSTEMC)
+    list(APPEND VERILATOR_ARGS --sc)
+  else()
+    list(APPEND VERILATOR_ARGS --cc)
+  endif()
+
+  foreach(INC ${VERILATE_INCLUDE_DIRS})
+    list(APPEND VERILATOR_ARGS -y "${INC}")
+  endforeach()
+
+  string(TOLOWER ${CMAKE_CXX_COMPILER_ID} COMPILER)
+  if (NOT COMPILER MATCHES "msvc|clang")
+    set(COMPILER gcc)
+  endif()
+
+  get_target_property(BINARY_DIR "${TARGET}" BINARY_DIR)
+  get_target_property(TARGET_NAME "${TARGET}" NAME)
+  set(VDIR "${BINARY_DIR}/CMakeFiles/${TARGET_NAME}.dir/${VERILATE_PREFIX}.dir")
+
+  if (VERILATE_DIRECTORY)
+    set(VDIR "${VERILATE_DIRECTORY}")
+  endif()
+
+  file(MAKE_DIRECTORY ${VDIR})
+
+  set(VERILATOR_COMMAND "${VERILATOR_BIN}" --compiler ${COMPILER}
+                        --prefix ${VERILATE_PREFIX} --Mdir ${VDIR} --make cmake
+                        ${VERILATOR_ARGS} ${VERILATE_VERILATOR_ARGS}
+                        ${VERILATE_SOURCES})
+
+  set(VARGS_FILE "${VDIR}/verilator_args.txt")
+  set(VCMAKE "${VDIR}/${VERILATE_PREFIX}.cmake")
+  set(VCMAKE_COPY "${VDIR}/${VERILATE_PREFIX}_copy.cmake")
+
+  if (NOT EXISTS "${VARGS_FILE}" OR NOT EXISTS "${VCMAKE_COPY}")
+    set(VERILATOR_OUTDATED ON)
+  else()
+    file(READ "${VARGS_FILE}" PREVIOUS_VERILATOR_COMMAND)
+    if(NOT VERILATOR_COMMAND STREQUAL PREVIOUS_VERILATOR_COMMAND)
+      set(VERILATOR_OUTDATED ON)
+    endif()
+  endif()
+
+  if (VERILATOR_OUTDATED)
+    message(STATUS "Executing Verilator...")
+    execute_process(
+      COMMAND ${VERILATOR_COMMAND}
+      WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+      RESULT_VARIABLE _VERILATOR_RC
+      OUTPUT_VARIABLE _VERILATOR_OUTPUT
+      ERROR_VARIABLE _VERILATOR_OUTPUT)
+    if (_VERILATOR_RC)
+      string(REPLACE ";" " " VERILATOR_COMMAND_READABLE "${VERILATOR_COMMAND}")
+      message("Verilator command: \"${VERILATOR_COMMAND_READABLE}\"")
+      message("Output:\n${_VERILATOR_OUTPUT}")
+      message(FATAL_ERROR "Verilator command failed (return code=${_VERILATOR_RC})")
+    endif()
+    execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${VCMAKE}" "${VCMAKE_COPY}")
+  endif()
+  file(WRITE "${VARGS_FILE}" "${VERILATOR_COMMAND}")
+
+  include("${VCMAKE_COPY}")
+
+  set(GENERATED_C_SOURCES ${${VERILATE_PREFIX}_CLASSES_FAST}
+                          ${${VERILATE_PREFIX}_CLASSES_SLOW}
+                          ${${VERILATE_PREFIX}_SUPPORT_FAST}
+                          ${${VERILATE_PREFIX}_SUPPORT_SLOW})
+  foreach(GENERATED_C_SOURCE ${GENERATED_C_SOURCES})
+    get_filename_component(C_OUTPUT_NAME_WE "${GENERATED_C_SOURCE}" NAME_WE)
+    if(C_OUTPUT_NAME_WE MATCHES ".*Trace.*")
+      continue()
+    endif()
+    list(APPEND GENERATED_H_SOURCES "${VDIR}/${C_OUTPUT_NAME_WE}.h")
+  endforeach()
+  set(GENERATED_SOURCES ${GENERATED_C_SOURCES} ${GENERATED_H_SOURCES})
+
+  add_custom_command(OUTPUT ${GENERATED_SOURCES} "${VCMAKE}"
+                     COMMAND ${VERILATOR_COMMAND}
+                     WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+                     DEPENDS "${VERILATOR_BIN}" ${${VERILATE_PREFIX}_DEPS} VERBATIM)
+  # Reconfigure if file list has changed
+  # (check contents rather than modified time to avoid unnecessary reconfiguration)
+  add_custom_command(OUTPUT "${VCMAKE_COPY}"
+                     COMMAND "${CMAKE_COMMAND}" -E copy_if_different
+                     "${VCMAKE}" "${VCMAKE_COPY}"
+                     DEPENDS "${VCMAKE}" VERBATIM)
+
+  if (${VERILATE_PREFIX}_THREADS)
+    # If any verilate() call specifies THREADS, define VL_THREADED in the final build
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_THREADED ON)
+  endif()
+
+  if (${VERILATE_PREFIX}_COVERAGE)
+    # If any verilate() call specifies COVERAGE, define VM_COVERAGE in the final build
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_COVERAGE ON)
+  endif()
+
+  if (${VERILATE_PREFIX}_TRACE_VCD)
+    # If any verilate() call specifies TRACE, define VM_TRACE in the final build
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON)
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_VCD ON)
+  endif()
+
+  if (${VERILATE_PREFIX}_TRACE_FST)
+    # If any verilate() call specifies TRACE_FST, define VM_TRACE_FST in the final build
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE ON)
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_TRACE_FST ON)
+  endif()
+
+  if (${VERILATE_PREFIX}_SC)
+    # If any verilate() call specifies SYSTEMC, define VM_SC in the final build
+    set_property(TARGET ${TARGET} PROPERTY VERILATOR_SYSTEMC ON)
+  endif()
+
+    # Add the compile flags only on Verilated sources
+  target_include_directories(${TARGET} PUBLIC ${VDIR})
+  target_sources(${TARGET} PRIVATE ${GENERATED_SOURCES} "${VCMAKE_COPY}"
+                                   ${${VERILATE_PREFIX}_GLOBAL}
+                                   ${${VERILATE_PREFIX}_USER_CLASSES})
+  foreach(_VSOURCE ${VERILATE_SOURCES} ${${VERILATE_PREFIX}_DEPS})
+    get_filename_component(_VSOURCE "${_VSOURCE}" ABSOLUTE BASE_DIR)
+    list(APPEND VHD_SOURCES "${_VSOURCE}")
+  endforeach()
+  target_sources(${TARGET} PRIVATE ${VHD_SOURCES})
+
+  # Add the compile flags only on Verilated sources
+  foreach(VSLOW ${${VERILATE_PREFIX}_CLASSES_SLOW} ${${VERILATE_PREFIX}_SUPPORT_SLOW})
+    foreach(OPT_SLOW ${VERILATE_OPT_SLOW} ${${VERILATE_PREFIX}_USER_CFLAGS})
+      set_property(SOURCE "${VSLOW}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_SLOW}")
+    endforeach()
+  endforeach()
+  foreach(VFAST ${${VERILATE_PREFIX}_CLASSES_FAST} ${${VERILATE_PREFIX}_SUPPORT_FAST})
+    foreach(OPT_FAST ${VERILATE_OPT_FAST} ${${VERILATE_PREFIX}_USER_CFLAGS})
+      set_property(SOURCE "${VFAST}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${OPT_FAST}")
+    endforeach()
+  endforeach()
+
+  target_include_directories(${TARGET} PUBLIC "${VERILATOR_ROOT}/include"
+                                               "${VERILATOR_ROOT}/include/vltstd")
+  target_compile_definitions(${TARGET} PRIVATE
+    VM_COVERAGE=$<BOOL:$<TARGET_PROPERTY:VERILATOR_COVERAGE>>
+    VM_SC=$<BOOL:$<TARGET_PROPERTY:VERILATOR_SYSTEMC>>
+    $<$<BOOL:$<TARGET_PROPERTY:VERILATOR_THREADED>>:VL_THREADED>
+    VM_TRACE=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE>>
+    VM_TRACE_VCD=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE_VCD>>
+    VM_TRACE_FST=$<BOOL:$<TARGET_PROPERTY:VERILATOR_TRACE_FST>>
+  )
+
+  target_link_libraries(${TARGET} PUBLIC
+    ${${VERILATE_PREFIX}_USER_LDLIBS}
+    "$<$<BOOL:$<TARGET_PROPERTY:VERILATOR_THREADED>>:${VERILATOR_MT_CFLAGS}>"
+  )
+
+  # SystemC requires the C++ version to match the library version, avoid setting anything here
+  set(GEN_THREADED $<BOOL:$<TARGET_PROPERTY:VERILATOR_THREADED>>)
+  set(GEN_SYSTEMC $<BOOL:$<TARGET_PROPERTY:VERILATOR_SYSTEMC>>)
+  target_compile_features(${TARGET} PRIVATE
+    $<$<AND:${GEN_THREADED},$<NOT:${GEN_SYSTEMC}>>:cxx_std_11>
+  )
+endfunction()
+
+function(_verilator_find_systemc)
+  if (NOT TARGET Verilator::systemc)
+    # Find SystemC include file "systemc.h" in the following order:
+    # 1. SYSTEMC_INCLUDE (environment) variable
+    # 2. SYSTEMC_ROOT (environment) variable
+    # 3. SYSTEMC (environment) variable
+    # 4. Use CMake module provided by SystemC installation
+    #    (eventually requires CMAKE_PREFIX_PATH set)
+
+    find_path(SYSTEMC_INCLUDEDIR NAMES systemc.h
+      HINTS "${SYSTEMC_INCLUDE}   " ENV SYSTEMC_INCLUDE)
+    find_path(SYSTEMC_INCLUDEDIR NAMES systemc.h
+      HINTS "${SYSTEMC_ROOT}" ENV SYSTEMC_ROOT
+      PATH_SUFFIXES include)
+    find_path(SYSTEMC_INCLUDEDIR NAMES systemc.h
+      HINTS "${SYSTEMC}" ENV SYSTEMC
+      PATH_SUFFIXES include)
+
+    # Find SystemC library in the following order:
+    # 1. SYSTEMC_LIBDIR (environment) variable
+    # 2. SYSTEMC_ROOT (environment) variable
+    # 3. SYSTEMC (environment) variable
+    # 4. Use CMake module provided by SystemC installation
+    #    (eventually requires CMAKE_PREFIX_PATH set)
+
+    # Find SystemC using include and library paths
+    find_library(SYSTEMC_LIBRARY NAMES systemc
+      HINTS "${SYSTEMC_LIBDIR}" ENV SYSTEMC_LIBDIR)
+    find_library(SYSTEMC_LIBRARY NAMES systemc
+      HINTS "${SYSTEMC_ROOT}" ENV SYSTEMC_ROOT
+      PATH_SUFFIXES lib)
+    find_library(SYSTEMC_LIBRARY NAMES systemc
+      HINTS "${SYSTEMC}" ENV SYSTEMC
+      PATH_SUFFIXES lib)
+
+    if (SYSTEMC_INCLUDEDIR AND SYSTEMC_LIBRARY)
+      add_library(Verilator::systemc INTERFACE IMPORTED)
+      set_target_properties(Verilator::systemc
+        PROPERTIES
+          INTERFACE_INCLUDE_DIRECTORIES "${SYSTEMC_INCLUDEDIR}"
+          INTERFACE_LINK_LIBRARIES "${SYSTEMC_LIBRARY}")
+      return()
+    endif()
+
+    find_package(SystemCLanguage QUIET)
+    if (SystemCLanguage_FOUND)
+      add_library(Verilator::systemc INTERFACE IMPORTED)
+      set_target_properties(Verilator::systemc
+        PROPERTIES
+          INTERFACE_LINK_LIBRARIES "SystemC::systemc")
+      return()
+    endif()
+
+    message("SystemC not found. This can be fixed by doing either of the following steps:")
+    message("- set the SYSTEMC_INCLUDE and SYSTEMC_LIBDIR (environment) variables; or")
+    message("- set SYSTEMC_ROOT (environment) variable; or")
+    message("- set SYSTEMC (environment) variable; or")
+    message("- use the CMake module of your SystemC installation (may require CMAKE_PREFIX_PATH)")
+    message(FATAL_ERROR "SystemC not found")
+  endif()
+endfunction()
+
+function(verilator_link_systemc TARGET)
+  _verilator_find_systemc()
+  target_link_libraries("${TARGET}" PUBLIC Verilator::systemc)
+  target_compile_options(${TARGET} PRIVATE $ENV{SYSTEMC_CXX_FLAGS} ${SYSTEMC_CXX_FLAGS})
+endfunction()
+
+function(verilator_generate_key OUTPUT_VARIABLE)
+  execute_process(COMMAND ${VERILATOR_BIN} --generate-key
+                  OUTPUT_VARIABLE KEY_VAL
+                  RESULT_VARIABLE KEY_RET)
+  if (KEY_RET)
+    message(FATAL_ERROR "verilator --generate-key failed")
+  endif()
+  string(STRIP ${KEY_VAL} KEY_VAL)
+  set(${OUTPUT_VARIABLE} ${KEY_VAL} PARENT_SCOPE)
+endfunction()