Simulation-based verification using Icarus: Designing and Simulating a 4-Bit Synchronous Counter
In digital design, counters are foundational components used across a variety of applications, from simple timers to complex state machines. A counter is essentially a sequential circuit that counts pulses and progresses through a defined sequence of states. In this blog post, we’ll explore how to design a 4-bit synchronous counter using Verilog. We will then create a testbench to verify our design through simulation, utilizing popular open-source tools like Icarus Verilog and GTKWave.
Designing the 4-bit Synchronous Counter
A synchronous counter is where all flip-flops are triggered by the same clock signal, ensuring that all bits change state simultaneously. Here’s how you can implement a 4-bit synchronous counter in Verilog:
/*
* 4 bit synchronous counter
*/
module Mycounter (CLK, RST, OUT);
input CLK, RST;
output [3:0] OUT;
reg [3:0] OUT;
always @(posedge CLK)
begin
if (RST == 1'b1)
OUT <= 4'b0000;
else
OUT <= OUT + 1;
end
endmodule
Code Breakdown
- Module Declaration: We define a module named Mycounter that takes three inputs: CLK (clock), RST(reset), and OUT(output).
- Registers: The output OUT is a 4-bit register to store the current count value.
- Always Block: The always block is triggered on the positive edge of the clock. If the reset (RST) is high, the counter resets to 0. Otherwise, it increments by 1 on each clock pulse.
This design is simple yet powerful, demonstrating the basic principles of synchronous counters in digital systems.
Building the Testbench
To verify our counter design, we need a testbench. The testbench provides the necessary inputs to the counter and checks the outputs to ensure the design works as intended. Below is the Verilog testbench code:
/*
* Testbench for a 4 bit synchronous counter
*/
module Testbench();
reg Clock, Reset;
wire [3:0] Count;
// instantiate the DUT and make connections
Mycounter I1(.CLK(Clock), .RST(Reset), .OUT(Count));
// initialize the Testbench
initial begin
$display("Starting simulation...");
Clock = 1'b0;
Reset = 1'b1; // reset the counter at t=0
#100 Reset = 1'b0; // remove reset at t=100
#2000 Reset = 1'b1; // reapply reset at t=2100
#500 $finish; // end the simulation after t=2500
end
// generate stimulus (in this case clock signal)
always #50 Clock = ~Clock; // clock period=100
// monitor the response and save it in a file
initial begin
$dumpfile("count.vcd"); // specifies the VCD file
$dumpvars; // dump all the variables
end
$monitor("%4d %b %b %4b", $time, Clock, Reset, Count);
endmodule
Understanding the Testbench
- Module Declaration: The testbench is defined in a module named Testbench. It uses reg for inputs (Clock and Reset) and wire for the output (Count).
- Instantiation: The counter module (Mycounter) is instantiated and connected to the testbench signals.
- Initialization Block: This block initializes the clock and reset signals. The reset signal is initially high to reset the counter; then, it is deactivated to allow the counter to increment. After some time, the reset is reactivated to observe the reset behavior again.
- Clock Generation: The always block toggles the clock signal every 50-time units, creating a clock period of 100 units.
- Simulation Monitoring: The testbench monitors the signals and dumps them into a .vcd file for waveform analysis using GTKWave.
Installing Icarus Verilog and GTKWave
Before diving into Verilog simulations, you must set up the necessary tools. In this guide, we’ll walk you through installing Icarus Verilog, an open-source Verilog simulation tool, and GTKWave, a waveform viewer, on your Linux system.
Step 1: Install Icarus Verilog
Icarus Verilog is a popular tool for Verilog synthesis and simulation. Follow these steps to install it:
- Update Your Package Lists:
Start by updating your system’s package lists to ensure you have the latest information on available packages.
sudo apt-get update
2. Install Icarus Verilog:
Now, install Icarus Verilog using the package manager.
sudo apt-get install iverilog
3. Verify the Installation:
After installation, verify that Icarus Verilog is installed correctly by checking the version.
iverilog -V
Step 2: Install GTKWave
GTKWave is a waveform viewer that helps you visualize the simulation results. Here’s how to install it:
- Install GTKWave:
Install GTKWave using the package manager.
sudo apt-get install gtkwave
2. Verify the Installation:
Check if GTKWave is installed by launching it from the terminal.
gtkwave
If installed correctly, GTKWave will open, and you’ll see its interface.
Step 3: Setting Up Your Project
Now that you have the necessary tools installed, you can set up your Verilog project:
- Create a Directory for Your Project:
Organize your files by creating a directory for your Verilog project
mkdir ~/verilog_projects
cd ~/verilog_projects
2. Write Your Verilog Code:
Create and edit your Verilog files (e.g., Mycounter.v
and Testbench.v
) using your preferred text editor.
gedit Mycounter.v Testbench.v
3. Compile and Run the Simulation:
Once your files are ready, compile and simulate your design using Icarus Verilog.
iverilog -o Mycounter Mycounter.v Testbench.v
vvp Mycounter
4. View the Waveform with GTKWave:
After running the simulation, open the generated waveform file with GTKWave for analysis.
gtkwave count.vcd
With Icarus Verilog and GTKWave installed, you can simulate and analyze your Verilog designs. These tools are indispensable for anyone in digital design, providing a robust platform for verifying and debugging your circuits before moving to hardware implementation.
Code Coverage
To install the code coverage tool Covered, you can follow these steps:
- Clone the GitHub repository:
Open your terminal and clone the repository using the following command:
git clone https://github.com/chiphackers/covered.git
Navigate to the Covered directory:
Change into the directory where Covered was cloned:
cd covered
Configure the build:
Run the configuration script to set up the build environment:
./configure
Install dependencies:
If any dependencies are missing, install them using the following commands:
sudo apt-get update
sudo apt-get install zlib1g-dev
git clone https://git.savannah.gnu.org/git/libiconv.git
sudo apt-get install tcl8.6 tcl8.6-dev tk8.6 tk8.6-dev
sudo apt-get install doxygen
Compile the source code:
Once all dependencies are installed, compile the source code:
make
Install Covered:
Finally, install Covered using the following command:
sudo make install
This will complete the installation process for Covered. You can now use it for code coverage analysis, as described below.
Commands to check the code coverage report:
covered score -t Testbench -v Testbench.v -v Mycounter.v -vcd count.vcd -o Mycounter.cdd
covered report -d v Mycounter .cdd
In this blog post, we walked through the design and simulation of a 4-bit synchronous counter using Verilog. We discussed the implementation of the counter, created a testbench to verify its functionality, and simulated the design using Icarus Verilog, GTKWave, and Code Coverage. This process highlights the importance of simulation in digital design, ensuring that our circuits behave as expected before moving on to physical implementation.