Last modified: Feb 14, 2026
Well… I had to learn SystemVerilog. And this is something that I made while trying to learn it.
The original code was from Prof. Marano’s website
I just spammed some comments, but I thought some might find it helpful.
module my_module (
input logic clk, // single bit signal
input logic rst,
input logic [3:0] data_in, // 4 bit signal MSB:3 , LSB: 0
output logic [3:0] data_out
);
// here we define internal signals, parameters and types before using them
logic [3:0] internal_signal;
localparam WIDTH = 4;
// this just decalres local varisable called WIDTH and making it 4.
// though it is not used in here anyways.
// Dataflow: continuous assignment
assign internal_signal = ~data_in; // ~ is bitwise not
// this is making sequential logic here
always_ff @(posedge clk) begin
if (rst)
data_out <= 4'b0; // alway_ff you use <= but alwasy_comb you use =
else
data_out <= internal_signal;
end
endmodule
// to test this logic, we need testbench.
// --> let's go to tb_my_module.sv
Think this code as your “device.” To test your device, you need some other stuff to test it out, and we call thie test bench. The following is an example test bench for the code that was presented above.
`timescale 1ns/1ps // this defines timeunit / precision
// time unit defines what #1 means, in this case 1ns
// time precision is the smalleset unit that simulator can
// represent
module tb_my_module; // components that you want to test should be declared here
// DUT signals, *dut meaning design under test (DUT: Device Undet Test)
// here you are declaring variables to connect to DUT.
// don't do input logic clk or output logic ... because that is not the module
logic clk;
logic rst;
logic [3:0] data_in;
logic [3:0] data_out;
// Instantiate DUT
// This is like wiring things together
my_module dut(
.clk(clk), // testbench clk --> DUT clk, * inside_the_module(testbench_variable)
.rst(rst),
.data_in(data_in),
.data_out(data_out)
);
initial clk = 0; // initialize clk to be 0
always #5 clk = ~clk; // you made a clock nice
// dump waves (for GTKwave)
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, tb_my_module);
end
// ------------------------------------
// Nice job, now you have initilized your testbench
// ------------------------------------
initial begin
$display("time | rst | clk | data_in | data_out |");
$monitor("t=%0t| rst=%b | clk=%b | data_in=%h | data_out=%h", $time, clk, rst, data_in, data_out);
// think display and monitor as a printf of c.
// display only prints out the test, and monitor is how you print variables with printf.
// t for time
// b for bindary
// h for hex
rst = 1;
data_in = 4'h0; //4 bits, hexadecimal base, A is the number
repeat (2) @(posedge clk);
rst = 0;
// it holds rst = 0 for 2 pos edge clock
// let's test some values
data_in = 4'hA; @(posedge clk);
data_in = 4'h0; @(posedge clk);
data_in = 4'hB; @(posedge clk);
$finish; //you need this to finish it
end
endmodule
Another useful thing that I wanted to mention is that when you have several input variables, you can make something that is really similar to the truth table:
initial a = 0;
always #5 a = ~a;
initial b = 0;
always #10 b = ~b;
initial c = 0;
always #20 c = ~b;
//and so on...