HardwareTeams.com - The #1 job board and blog for electrical and computer engineers

Introduction to SystemVerilog #

SystemVerilog is an extension of the Verilog hardware description language (HDL) widely used in the design and verification of digital systems. It combines the features of Verilog with new constructs to provide a more powerful and efficient language for designing complex digital systems.

Background #

  • Originally introduced as an extension to Verilog in 2002, SystemVerilog has become the industry standard for hardware design and verification.

  • One of the key features of SystemVerilog is its support for both design and verification. It provides an enhanced set of constructs for specifying the behavior, structure, and timing of digital systems.

  • On the verification side, SystemVerilog offers advanced features for creating testbenches and verifying a design. It provides constructs for specifying test scenarios, checking assertions, and generating random stimuli to thoroughly test the functionality and performance of a design.

  • SystemVerilog also incorporates object-oriented programming (OOP) concepts, allowing for the creation of reusable and modular code. It introduces new data types, such as classes and structures, that enable designers and verification engineers to build more sophisticated and scalable models.

Quickstart #

Modules and Ports #

In SystemVerilog, a module is a fundamental building block used to describe a hardware component. It encapsulates the functionality and behavior of a digital circuit or sub-circuit. Modules can be interconnected to form larger systems.

Here’s an example of a simple module that represents a 2-to-1 multiplexer:

module mux2to1(input wire a, b, sel, output reg y);
    always @(a, b, sel)
        case (sel)
            1'b0: y = a;
            1'b1: y = b;

In this example, the mux2to1 module takes three input wires (a, b, and sel) and one output register (y). The always block describes the behavior of the module using a case statement. Depending on the value of the sel signal, either a or b is selected as the output y.

Data Types #

SystemVerilog provides various data types to represent different types of signals and values. Some commonly used data types include:

  1. wire:

    • Wires are used to represent connections between different modules.
    • They can be used for both input and output signals.
    • Wires are typically used for continuous assignments or connecting modules.
  2. reg:

    • Unlike its name suggests, reg is not limited to sequential storage elements.
    • reg can represent combinational logic or storage elements, depending on the context.
    • It is commonly used for representing state variables or outputs of procedural blocks.
  3. integer:

    • integer is a 32-bit signed data type, used for representing signed or unsigned integer values.
    • It can be used for variables that require mathematical operations or counting.
    • Unlike wire or reg, integer is not directly used for connecting modules but rather for internal computations.
  4. bit:

    • bit is a single-bit data type, allowing only two values: 0 or 1.
    • It is often used for representing control signals or flags.
    • bit data type is useful when precise control is required over a single binary value.
  5. logic:

    • logic is a flexible and versatile data type that supports a wide range of bit-vector operations.
    • It allows the representation of multiple bits or vectors.
    • logic supports a 4-state value system: 0, 1, X (unknown), and Z (high-impedance).
    • It is commonly used for designing complex digital circuits and modeling bus structures.
module data_types_example;
    wire a, b;
    reg [7:0] data;
    integer count;
    bit enable;
    logic [3:0] vector;

Continuous Assignments #

Continuous assignments in SystemVerilog allow you to describe combinational logic. They assign values to wires based on Boolean expressions or connections to other signals.

Here’s an example of a simple AND gate implemented using continuous assignments:

module and_gate(input wire a, b, output wire y);
    assign y = a & b;

In this example, the assign statement assigns the logical AND of input signals a and b to the output signal y.

Behavioral Modeling #

SystemVerilog allows for behavioral modeling using procedural blocks such as always and initial. These blocks describe the behavior of the design based on certain conditions and events.

Here’s an example that demonstrates a basic counter using a procedural always block:

module counter(input wire clk, input wire reset, output reg [3:0] count);
    always @(posedge clk or posedge reset) begin
        if (reset)
            count <= 4'b0;
            count <= count + 1;

In this example, the always block triggers on the positive edge of the clk signal or the positive edge of the reset signal. If the reset signal is asserted, the counter is reset to zero. Otherwise, the counter increments by one on each clock cycle.

More about always #

The always block is a fundamental construct in SystemVerilog, allowing designers to specify the behavior of digital circuits.

  1. Sensitivity List: The sensitivity list determines when the always block is triggered. It specifies the signals or events that the block depends on. SystemVerilog provides several options for specifying the sensitivity list:
    • always @(*): This sensitivity list includes all signals in the block and triggers whenever any of those signals change.
    • always @(posedge clk): This sensitivity list triggers the block on the positive edge of the clock signal.
    • always @(a, b): This sensitivity list triggers when the signals a or b change.

It is important to select an appropriate sensitivity list to ensure accurate modeling of the circuit’s behavior.

  1. Blocking vs. Non-Blocking Assignments: SystemVerilog provides two types of assignments within the always block: blocking (=) and non-blocking (<=). It is crucial to understand the difference between them to ensure proper modeling of sequential logic.
  • Blocking assignments: A blocking assignment (=) executes immediately, blocking the execution of subsequent statements until it completes. It is used for combinational logic or when the order of execution matters.
  • Non-blocking assignments: A non-blocking assignment (<=) schedules the assignment to occur at the end of the time step, allowing all other assignments in the always block to occur concurrently. It is typically used for modeling sequential elements, such as flip-flops or registers.

Understanding the distinction between blocking and non-blocking assignments is essential for accurately modeling sequential behavior.

example below demonstrates the usage of the always block for modeling a D flip-flop:

module d_flip_flop(input wire d, clk, reset, output reg q);

    always @(posedge clk or posedge reset) begin
        if (reset)
            q <= 1'b0; // Reset the output to 0 when reset signal is asserted
            q <= d; // Assign the input to the output on the positive edge of the clock


Conditional Statements, Loops, and Initial Blocks #

These constructs are essential for controlling the flow of execution and initializing variables in hardware description languages.

If-Else Statements #

The if-else statement allows you to make decisions based on conditions. Here’s the syntax:

if (condition1) begin
  // code block executed when condition1 is true
else if (condition2) begin
  // code block executed when condition2 is true
else begin
  // code block executed when none of the conditions are true

While Loops #

The while loop allows you to repeat a set of statements while a condition is true. Here’s the syntax:

while (condition) begin
  // code block to be repeated while condition is true

For Loops #

The for loop allows you to repeat a set of statements for a specified range. Here’s the syntax:

for (initialization; condition; increment) begin
  // code block to be repeated

Case Statements #

The case statement allows you to perform different actions based on the value of a variable. Here’s the syntax:

case (variable)
  value1: begin
    // code block executed when variable matches value1
  value2: begin
    // code block executed when variable matches value2
  default: begin
    // code block executed when none of the values match

Repeat Loops #

The repeat loop allows you to repeat a set of statements a specific number of times. Here’s the syntax:

repeat (n) begin
  // code block to be repeated n times

Initial Blocks #

The initial block is used to initialize variables at the beginning of simulation. Here’s the syntax:

initial begin
  // code block containing initialization statements

Notes on what is Synthesizable #

initial blocks are not synthesizable in SystemVerilog. Initial blocks are used for simulation purposes and are not meant to be synthesized into hardware. They are typically used to initialize variables and perform testbench-related tasks during simulation.

The repeat statement is also not synthesizable in SystemVerilog. The repeat statement is used for specifying a fixed number of iterations in a simulation loop. It is not intended to be used for describing hardware behavior.

During synthesis, the synthesizer converts the hardware description written in RTL (Register Transfer Level) into a gate-level representation. The purpose of synthesis is to generate the actual hardware implementation of the design.

Operators #

Operator Description
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulo (Remainder)
** Exponentiation
+ 1 Increment by 1
- 1 Decrement by 1
++ Pre-increment
+= Addition assignment
-= Subtraction assignment
*= Multiplication assignment
/= Division assignment
%= Modulo assignment
~ Bitwise NOT
& Bitwise AND
| Bitwise OR
^ Bitwise XOR
~^ Bitwise XNOR
<< Bitwise left shift
>> Bitwise right shift
<<< Logical left shift
>>> Logical right shift
&~ Bitwise AND NOT
~& Bitwise NAND
|~ Bitwise OR NOT
~| Bitwise NOR
=== Case equality
!== Case inequality
HardwareTeams.com Copyright © 2024
comments powered by Disqus