This compiles and runs on linux it also compiles and runs on windows, you need verilator and iverilog
Last active
August 8, 2024 17:42
-
-
Save Kreijstal/ac8dff5de2b771fc6ccde9db433d73d1 to your computer and use it in GitHub Desktop.
verilator windows bug iverilog cosimulation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module and_gate ( | |
input wire a, | |
input wire b, | |
output wire y | |
); | |
assign y = a & b; | |
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`timescale 1ns / 1ps | |
module and_gate( | |
input wire a, | |
input wire b, | |
output wire y | |
); | |
// Use the external VPI function for the AND gate | |
// If you want to use a Verilog-based AND gate instead, uncomment the assign statement below | |
assign y = $and_gate(a, b); | |
// assign y = a & b; | |
endmodule | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`timescale 1ns / 1ps | |
module and_gate_tb; | |
// Inputs | |
reg a; | |
reg b; | |
// Outputs | |
wire y; | |
// Instantiate the Unit Under Test (UUT) | |
and_gate uut ( | |
.a(a), | |
.b(b), | |
.y(y) | |
); | |
// Task for checking the AND gate output | |
task check_and_gate; | |
input a_in, b_in, expected_y; | |
begin | |
a = a_in; | |
b = b_in; | |
#1; // Allow some time for the output to settle | |
if (y !== expected_y) begin | |
$display("ERROR: a=%b, b=%b, y=%b (expected %b)", a, b, y, expected_y); | |
$finish; | |
end else begin | |
$display("PASS: a=%b, b=%b, y=%b", a, b, y); | |
end | |
end | |
endtask | |
initial begin | |
// Initialize Inputs | |
a = 0; | |
b = 0; | |
// Wait 100 ns for global reset to finish | |
#100; | |
// Stimulus and assertions | |
check_and_gate(0, 0, 0); | |
check_and_gate(0, 1, 0); | |
check_and_gate(1, 0, 0); | |
check_and_gate(1, 1, 1); | |
// Add some delay before finishing simulation | |
#10; | |
$display("All tests passed!"); | |
$finish; | |
end | |
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <vpi_user.h> | |
#include <stdint.h> | |
#include "and_gate_vpi_wrapper.h" | |
static void* and_gate_model = NULL; | |
static PLI_INT32 and_gate_vpi_calltf(PLI_BYTE8* user_data) { | |
(void)user_data; // Suppress unused parameter warning | |
vpiHandle systf_handle, args_iter, arg_handle; | |
s_vpi_value value; | |
int32_t a, b, y; | |
if (!and_gate_model) { | |
and_gate_model = create_and_gate_model(); | |
} | |
systf_handle = vpi_handle(vpiSysTfCall, NULL); | |
args_iter = vpi_iterate(vpiArgument, systf_handle); | |
// Get first argument (a) | |
arg_handle = vpi_scan(args_iter); | |
value.format = vpiIntVal; | |
vpi_get_value(arg_handle, &value); | |
a = value.value.integer; | |
// Get second argument (b) | |
arg_handle = vpi_scan(args_iter); | |
value.format = vpiIntVal; | |
vpi_get_value(arg_handle, &value); | |
b = value.value.integer; | |
// Set inputs and evaluate the model | |
set_and_gate_inputs(and_gate_model, a, b); | |
// Get the output | |
y = get_and_gate_output(and_gate_model); | |
// Set the output value | |
value.format = vpiIntVal; | |
value.value.integer = y; | |
vpi_put_value(systf_handle, &value, NULL, vpiNoDelay); | |
vpi_free_object(args_iter); | |
return 0; | |
} | |
static PLI_INT32 and_gate_vpi_register(void) { | |
s_vpi_systf_data tf_data; | |
tf_data.type = vpiSysFunc; | |
tf_data.sysfunctype = vpiIntFunc; | |
tf_data.tfname = "$and_gate"; | |
tf_data.calltf = and_gate_vpi_calltf; | |
tf_data.compiletf = NULL; | |
tf_data.sizetf = NULL; | |
tf_data.user_data = NULL; | |
vpi_register_systf(&tf_data); | |
return 0; | |
} | |
void (*vlog_startup_routines[])(void) = { | |
(void (*)(void))and_gate_vpi_register, | |
0 | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <verilated.h> | |
#include "Vand_gate.h" | |
#include <vpi_user.h> | |
static Vand_gate* and_gate_model = nullptr; | |
static int and_gate_vpi_calltf(PLI_BYTE8* user_data) { | |
vpiHandle systf_handle, args_iter, arg_handle; | |
s_vpi_value value; | |
if (!and_gate_model) { | |
and_gate_model = new Vand_gate; | |
} | |
systf_handle = vpi_handle(vpiSysTfCall, NULL); | |
args_iter = vpi_iterate(vpiArgument, systf_handle); | |
// Get first argument (a) | |
arg_handle = vpi_scan(args_iter); | |
vpi_get_value(arg_handle, &value); | |
and_gate_model->a = value.value.integer; | |
// Get second argument (b) | |
arg_handle = vpi_scan(args_iter); | |
vpi_get_value(arg_handle, &value); | |
and_gate_model->b = value.value.integer; | |
// Evaluate the model | |
and_gate_model->eval(); | |
// Set the output value | |
value.format = vpiIntVal; | |
value.value.integer = and_gate_model->y; | |
vpi_put_value(systf_handle, &value, NULL, vpiNoDelay); | |
vpi_free_object(args_iter); | |
return 0; | |
} | |
void and_gate_vpi_register() { | |
s_vpi_systf_data tf_data; | |
tf_data.type = vpiSysFunc; | |
tf_data.sysfunctype = vpiIntFunc; | |
tf_data.tfname = "$and_gate"; | |
tf_data.calltf = and_gate_vpi_calltf; | |
tf_data.compiletf = NULL; | |
tf_data.sizetf = NULL; | |
tf_data.user_data = NULL; | |
vpi_register_systf(&tf_data); | |
} | |
void (*vlog_startup_routines[])(void) = { | |
and_gate_vpi_register, | |
0 | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "and_gate_vpi_wrapper.h" | |
#include "Vand_gate.h" | |
#include <verilated.h> | |
extern "C" { | |
void* create_and_gate_model() { | |
return new Vand_gate; | |
} | |
void destroy_and_gate_model(void* model) { | |
delete static_cast<Vand_gate*>(model); | |
} | |
void set_and_gate_inputs(void* model, int32_t a, int32_t b) { | |
Vand_gate* and_gate = static_cast<Vand_gate*>(model); | |
and_gate->a = a; | |
and_gate->b = b; | |
and_gate->eval(); | |
} | |
int32_t get_and_gate_output(void* model) { | |
Vand_gate* and_gate = static_cast<Vand_gate*>(model); | |
return and_gate->y; | |
} | |
} | |
// Initialize Verilated modules | |
static struct VerilatedInitialize { | |
VerilatedInitialize() { | |
Verilated::traceEverOn(true); | |
} | |
} verilated_initialize; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "and_gate_vpi_wrapper.h" | |
#include "Vand_gate.h" | |
#include <verilated.h> | |
extern "C" { | |
void* create_and_gate_model() { | |
return new Vand_gate; | |
} | |
void destroy_and_gate_model(void* model) { | |
delete static_cast<Vand_gate*>(model); | |
} | |
void set_and_gate_inputs(void* model, int a, int b) { | |
Vand_gate* and_gate = static_cast<Vand_gate*>(model); | |
and_gate->a = a; | |
and_gate->b = b; | |
and_gate->eval(); | |
} | |
int get_and_gate_output(void* model) { | |
Vand_gate* and_gate = static_cast<Vand_gate*>(model); | |
return and_gate->y; | |
} | |
} | |
// Initialize Verilated modules | |
static struct VerilatedInitialize { | |
VerilatedInitialize() { | |
Verilated::traceEverOn(true); | |
} | |
} verilated_initialize; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef AND_GATE_VPI_WRAPPER_H | |
#define AND_GATE_VPI_WRAPPER_H | |
#include <stdint.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
void* create_and_gate_model(); | |
void destroy_and_gate_model(void* model); | |
void set_and_gate_inputs(void* model, int32_t a, int32_t b); | |
int32_t get_and_gate_output(void* model); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // AND_GATE_VPI_WRAPPER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "and_gate_vpi_wrapper.h" | |
#include "Vand_gate.h" | |
#include <verilated.h> | |
extern "C" { | |
void* create_and_gate_model() { | |
return new Vand_gate; | |
} | |
void destroy_and_gate_model(void* model) { | |
delete static_cast<Vand_gate*>(model); | |
} | |
void set_and_gate_inputs(void* model, vpi_int32 a, vpi_int32 b) { | |
Vand_gate* and_gate = static_cast<Vand_gate*>(model); | |
and_gate->a = a; | |
and_gate->b = b; | |
and_gate->eval(); | |
} | |
vpi_int32 get_and_gate_output(void* model) { | |
Vand_gate* and_gate = static_cast<Vand_gate*>(model); | |
return and_gate->y; | |
} | |
} | |
// Initialize Verilated modules | |
static struct VerilatedInitialize { | |
VerilatedInitialize() { | |
Verilated::traceEverOn(true); | |
} | |
} verilated_initialize; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef AND_GATE_VPI_WRAPPER_H | |
#define AND_GATE_VPI_WRAPPER_H | |
#include <vpi_user.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
void* create_and_gate_model(); | |
void destroy_and_gate_model(void* model); | |
void set_and_gate_inputs(void* model, vpi_int32 a, vpi_int32 b); | |
vpi_int32 get_and_gate_output(void* model); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // AND_GATE_VPI_WRAPPER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
VERILATOR = verilator | |
IVERILOG = iverilog | |
VVP = vvp | |
# Detect operating system | |
ifeq ($(OS),Windows_NT) | |
DETECTED_OS := Windows | |
else | |
DETECTED_OS := $(shell uname -s) | |
endif | |
# Set Verilator root based on OS | |
ifeq ($(DETECTED_OS),Windows) | |
POSSIBLE_VERILATOR_ROOTS = $(MSYSTEM_PREFIX)/local/share/verilator $(MSYSTEM_PREFIX)/share/verilator | |
MINGW_DIR = $(MSYSTEM_PREFIX) | |
IVERILOG_DIR = $(MINGW_DIR) | |
VPI_INCLUDE_DIR = $(MINGW_DIR)/include/iverilog | |
else | |
POSSIBLE_VERILATOR_ROOTS = /usr/local/share/verilator /usr/share/verilator | |
POSSIBLE_IVERILOG_DIRS = /usr /usr/local | |
IVERILOG_DIR = $(firstword $(foreach dir,$(POSSIBLE_IVERILOG_DIRS),$(wildcard $(dir)/include/iverilog))) | |
VPI_INCLUDE_DIR = $(IVERILOG_DIR) | |
endif | |
# Find the first existing Verilator root | |
VERILATOR_ROOT = $(firstword $(foreach dir,$(POSSIBLE_VERILATOR_ROOTS),$(wildcard $(dir)))) | |
ifeq ($(VERILATOR_ROOT),) | |
$(error Verilator root directory not found. Please install Verilator or set VERILATOR_ROOT manually.) | |
endif | |
ifeq ($(DETECTED_OS),Linux) | |
ifeq ($(IVERILOG_DIR),) | |
$(error Icarus Verilog directory not found. Please install Icarus Verilog or set IVERILOG_DIR manually.) | |
endif | |
endif | |
VERILATOR_FLAGS = -Wall --cc -CFLAGS -fPIC -CFLAGS -DVL_TIME_CONTEXT | |
CFLAGS = -Wall -g -I$(VERILATOR_ROOT)/include -I$(VPI_INCLUDE_DIR) -Iobj_dir -fPIC -DVL_TIME_CONTEXT | |
CXXFLAGS = $(CFLAGS) -std=c++14 -faligned-new | |
LDFLAGS = -L$(VERILATOR_ROOT)/include -L$(IVERILOG_DIR)/../lib -L./obj_dir | |
VPI_SRC = and_gate_vpi.c | |
WRAPPER_SRC = and_gate_vpi_wrapper.cpp | |
VPI_OUT = and_gate_vpi.vpi | |
VERILOG_SRC = and_gate.v | |
VERILOG_PROXY = and_gate_proxy.v | |
VERILOG_TB = and_gate_tb.v | |
VVP_EXEC = and_gate_tb.vvp | |
# Adjust commands for Windows | |
ifeq ($(DETECTED_OS),Windows) | |
MKDIR = mkdir | |
RM = rm -rf | |
COPY = cp | |
CC = gcc | |
CXX = g++ | |
SHARED = -shared | |
VPI_CFLAGS = -I$(VPI_INCLUDE_DIR) | |
VPI_LDFLAGS = -L$(MINGW_DIR)/lib -lvpi -lveriuser | |
else | |
MKDIR = mkdir -p | |
RM = rm -rf | |
COPY = cp | |
CC = gcc | |
CXX = g++ | |
SHARED = -shared | |
VPI_CFLAGS = -I$(VPI_INCLUDE_DIR) -fPIC | |
VPI_LDFLAGS = -L$(IVERILOG_DIR)/../lib -lvpi -lveriuser | |
endif | |
# Debug prints | |
$(info IVERILOG_DIR = $(IVERILOG_DIR)) | |
$(info VPI_INCLUDE_DIR = $(VPI_INCLUDE_DIR)) | |
.PHONY: all clean run | |
all: run | |
build: $(VVP_EXEC) | |
obj_dir: | |
$(MKDIR) obj_dir | |
obj_dir/Vand_gate.cpp: $(VERILOG_SRC) | obj_dir | |
$(VERILATOR) $(VERILATOR_FLAGS) $< --Mdir obj_dir | |
obj_dir/Vand_gate__ALL.o: obj_dir/Vand_gate.cpp | |
$(MAKE) -C obj_dir -f Vand_gate.mk | |
obj_dir/libverilated.a: obj_dir/Vand_gate.cpp | |
$(MAKE) -C obj_dir -f Vand_gate.mk | |
obj_dir/and_gate_vpi_wrapper.o: $(WRAPPER_SRC) and_gate_vpi_wrapper.h obj_dir/Vand_gate.cpp | obj_dir | |
$(CXX) $(CXXFLAGS) -c $< -o $@ | |
obj_dir/and_gate_vpi.o: $(VPI_SRC) and_gate_vpi_wrapper.h | obj_dir | |
$(CC) $(CFLAGS) $(VPI_CFLAGS) -c $< -o $@ | |
$(VPI_OUT): obj_dir/and_gate_vpi.o obj_dir/and_gate_vpi_wrapper.o obj_dir/Vand_gate__ALL.o obj_dir/libverilated.a | |
$(CXX) $(SHARED) -o $@ $^ $(LDFLAGS) $(VPI_LDFLAGS) -lverilated -lpthread -lvpi | |
$(VVP_EXEC): $(VERILOG_PROXY) $(VERILOG_TB) $(VPI_OUT) | |
$(IVERILOG) -o $@ -m./$(VPI_OUT) $(VERILOG_PROXY) $(VERILOG_TB) | |
run: $(VVP_EXEC) | |
$(VVP) -M. -m$(basename $(VPI_OUT)) $< | |
clean: | |
$(RM) obj_dir *.o *.vpi $(VVP_EXEC) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment