feature article
Subscribe Now

How To Implement SystemVerilog for FPGA Design

Introduction

Since its ratification in 2005, the SystemVerilog IEEE-1800 standard has experienced broad adoption in the verification and assertion space but has lagged for design constructs. Engineers may be wary of revamping current design methodologies, or they assume that SystemVerilog for design is not relevant to their projects, or they fear that field-programmable gate array (FPGA) synthesis tools do not fully support the new standard. All three of these concerns are either exaggerated or based on misconceptions. SystemVerilog is fully supported by leading synthesis tools, and the new design constructs are in fact relevant to most register-transfer level (RTL) coding styles and easy to learn and integrate into current methodologies.

The Benefits of SystemVerilog

The touted benefits of the design constructs include coding at higher levels of abstraction, compactness of code, and unification of design and verification environments. While it sounds appealing, in an engineer’s mind, a new language translates into a new learning curve, which translates into time to study, evangelize, and adapt to company standards. Most FPGA designers don’t have time to make their code more efficient because of all the code they have to write and would be better at keeping up with the latest standards if there weren’t so many to keep up with. Overwhelmed by tape-out schedules, designers can’t spend their days studying new languages, attending seminars, and perusing technical articles about the latest and greatest design trends.

The truth is, however, that the more pressure there is on design closure, the more relevant SystemVerilog is for design. Thanks to chip size and complexity, RTL is becoming more and more difficult to manage, re-use, and debug. In writing the new specification, the Accellera committee (an industry standards body) set out to address these problems. Its charter for the new SystemVerilog standard was to “extend Verilog IEEE 2001 to higher abstraction levels for architectural and algorithmic design, and advanced verification.”

The good news is that learning SystemVerilog for design is not difficut nor is it a quantum leap in methodology. It can (and should) be thought of as an extension to the existing Verilog standard, as opposed to a different language altogether.  Leading FPGA synthesis tools provide support for its synthesizable constructs. Designers need only recognize that the new extensions are easy to adopt, integrate, and tape out into real hardware.

While there are a variety of extensions available, the sub-set flow examined here focuses on the higher level of abstractions offered to RTL design. Each construct builds on the other. The degree of abstraction and complexity is up to the designer.

User-defined types

As a starting point, SystemVerilog allows the definition of new data types based on existing types with the typedef keyword, similar to C, as shown below. This is a fundamental building block in ultimately modeling a complex design at abstract levels while still being accurate and synthesizable. Once it is defined, the user-defined type can be used as with any built-in data-type, making data-structures more readable:

typedef  logic [1:0] opcode_t;
opcode_t [1:0] op1;

Note that the above example uses the naming convention of ending a user-defined type with the characters “_t”. This is done as a matter of readability and maintainability, since the user-defined type may have been defined elsewhere in the code or in another file.

In the above example, and the ones to follow, the logic data-type is used frequently so it is worth explaining. This is a replacement to the reg data-type, which is a misleading term since it implies a register is to be inferred, when in fact reg is a variable and may be implemented as sequential or combinational logic, depending on how it is used. The use of logic is recommended so as to avoid confusion. There are other differences between the reg data-type from Verilog-2001 and the logic type, but they will not be examined here.

Enumerated Types

Similar to VHDL’s enumeration data type, enumerated types in SystemVerilog provide the ability to declare a variable with a specific list of valid values, as shown below:

enum {ADD, SUB, MULT} opcode

The variable opcode is given a set of potential user-define names “ADD”, “SUB”, and “MULT” (also known as labels). This can be used in the following case statement (assume a, b, and c have been defined as variables):


 case (opcode)
   ADD:  c = a + b;
   SUB:  c = a – b;
   MULT: c = a * b;
 endcase

The code shown above is readable and intuitive.  One might argue that the same can be achieved in Verilog with use of the `define macroor parameter constants to define a set of names with specific values, such as shown below:

‘define ADD 2’b00
‘define SUB 2’b01
‘define MULT 2’b10

reg [1:0] opcode;

 case (opcode)
   ‘ADD:  c = a + b;
   ‘SUB:  c = a – b;
   ‘MULT: c = a * b;
 endcase

In the Verilog example above, the variables are defined as 2-bit vectors, so they can legally be assigned the value 2’b11—a value not accounted for in the above code. Designers typically have to be aware of this potential error. In addition to being more concise, enumerated types not only define a list of user-defined labels for a variable but also limit the variable to the set of valid values specified. By offering stronger type-checking in the language compiler, the code accurately describes designer intent.

Enumerated types can be used with the typedef keyword to create user-defined types with a set of valid values. This is useful when needing to make declarations in many places:

typedef enum {ADD, SUB, MULT} opcode_t;
opcode_t op1, op2;

Structures

SystemVerilog offers structures as the next level of abstraction. Structures are a means of aggregating variables or data-fields under a common name, usually those conceptually related in some way. With the struct keyword, users can intuitively describe data-structures and mask lower-level complexity as needed. Common applications for this include instruction registers, network packets, and bus packets.

struct {
logic [1:0] opcode;
int a, b;
logic [23:0] addr;
} instruction;

This is similar to C and to VHDL’s record construct. In Verilog, however, the members of a structure have to be defined as separate variables and managed individually, forcing the engineer to track how all the pieces fit together. By aggregating elements, data-structures can be represented in the HDL as they are understood conceptually.

Data elements (or members) within a struct can be accessed and manipulated using the struct and member names.

instruction.opcode = 2’b00

An entire struct can be a user-defined type to be re-used throughout in the code—effectively creating higher-level building blocks for design implementation.

typedef struct {
opcode_t opcode;
int a, b ;
logic [23:0] addr;
} instruction_t;

instruction_t instr1, instr2;

In the above example, note that the user-defined type opcode_t is a member of the user defined type instruction_t. Similarly, structures can also be declared as members of other structures, allowing multiple layers of abstraction.

They can also be passed through tasks, functions, and module ports, allowing abstraction to be maintained through data flow.
Assign instr1 = instr2;

Unions

Unions enhance structs or any data model by allowing multiple definition for a single storage element. Each definition has to occupy the same storage space (e.g., vector length), different data-types can be used. In the following example6, the same storage space is being defined as the  struct data with three members (source_address, destination_address, and data) and in another definition as a two-dimensional array bytes. Both of these definitions represent a 64-bit storage space identified as the union data_reg. Elements of the union are assigned values depending on the definition used (data or bytes).

union packed{
     struct packed {
     bit [15:0] source_address;
     bit [15:0] destination_address;
     bit [31:0] data;
} data;

bit [7:0][7:0] bytes;

} data_reg;

data_reg.data = data_in; //assumes data_in is a 32-bit vector

dest_low_byte = data_reg.bytes[4];

The above example briefly introduces the concept of packed structures and unions. We will not go into detail on the concept of packed arrays, but know that it refers to all elements being represented as contiguous bits, i.e., as a single vector.

Interfaces

While user-defined types, structures, and unions allow abstract data-modeling, they do not provide a complete mechanism for abstraction of data flow. The interface construct solves this problem by encapsulating port connectivity and functionality related to module-to-module communication. More than just abstraction of data-structures, interfaces raise the abstraction of communication protocols within a design.  This can reduce the size of code and improve maintainability.

The figure below shows a system-on-chip (SoC),  maintained by the Open Cores Project, with processor (CPU), UART, and parallel input/output (PIO) interface, all communicating through a bus interface following the wishbone specification.

20080429_mentor_fig1.gif

An interface is defined similarly to a module but with the interface keyword as shown below. The set of signals to be bundled in the interface are declared without input or output direction. Since each block in the SoC will see a port differently (input, output, or bi-directional), the subset of signals and port directions for each design block is defined in modports—each modport having a uniqe name.  Interfaces support parameters, constants, tasks, functions, procedural blocks, program blocks, assertions, as well as any user-defined type.

When declaring a module in the design, an instance of the interface is used as a single module port, using the name of the interface as the port type. Signal details are masked with this single port declaration, as is all functionality embedded in the interface. As shown in the uart module below, individual signals are referenced within the module as needed.

20080429_mentor_fig2.gif

One benefit of interfaces is bundling wires in one location, thereby masking inter-connectivity, reducing lines of code, and improving readability.

The more significant benefit is being able to localize communication logic between design blocks. The protocol details do not need to be duplicated in multiple modules so when the inevitable change of specification is made, modification to multiple areas of the code is minimized. These changes may include the addition or omission of a signal, a correction to a protocol error, or an entire revamp of the bus specification itself.

Conclusion

Beyond the constructs covered here, the standard provides a wide range of other extensions including enhancements to tasks, functions,  loops, procedural blocks, and the addition of new operators, new jump statements, and packages.

SystemVerilog is more of an evolution than revolution in RTL design and does not require an abandonment of existing coding styles.  With minimal effort for adoption, designers can realize its true benefits: coding at higher levels of abstraction and improved productivity by unifying the design and verification environment.

References

[1] April 2007 DeepChip Verification Survey
[2] “SystemVerilog enhancements for all chip designers”, Stuart Sutherland, EE Times, 2/26/2004
[3] DAC 2003 Accellera SystemVerilog Workshop
[4] SystemVerilog for Design: A Guide to Using SystemVerilog for Hardware Design and Modeling, Stuart Sutherland, Kluwer, Academic Publishers, Boston, MA, 2004, 0-4020-7530-8.
[5] IEEE Std. 1800-2005 IEEE Standard for SystemVerilog—Unified Hardware Design, Specification, and Verification Language, IEEE, 3 Park Avenue, NY, 2005.
[6] “Getting Ready for SystemVerilog at DAC [2004]” Presentation, Stuart Sutherland, Sutherland HDL, Inc.
[7] OPENCORES Project, opencores.org

8 thoughts on “How To Implement SystemVerilog for FPGA Design”

  1. Pingback: soccerphysics.co
  2. Pingback: bandar taruhan

Leave a Reply

featured blogs
Jul 28, 2021
The System Analysis Knowledge Bytes blog series will explore the capabilities and potential of the System Analysis tools offered by Cadence®. In addition to providing insight into the useful... [[ Click on the title to access the full blog on the Cadence Community site....
Jul 28, 2021
Here's a sticky problem. What if the entire Earth was instantaneously replaced with an equal volume of closely packed, but uncompressed blueberries?...
Jul 28, 2021
Hyperscale data centers are driving demand for high-bandwidth Ethernet protocols at speeds up to 800G to support HPC, AI, video streaming, and cloud computing. The post What's Driving the Demand for 200G, 400G, and 800G Ethernet? appeared first on From Silicon To Software....
Jul 9, 2021
Do you have questions about using the Linux OS with FPGAs? Intel is holding another 'Ask an Expert' session and the topic is 'Using Linux with Intel® SoC FPGAs.' Come and ask our experts about the various Linux OS options available to use with the integrated Arm Cortex proc...

featured video

Intelligent fall detection using TI mmWave radar sensors

Sponsored by Texas Instruments

Actively sense when a fall has occurred and take action such as sending out an alert in response. Our 60GHz antenna-on-package radar sensor (IWR6843AOP) is ideal for fall detection applications since it’s able to detect falls in large, indoor environments, can distinguish between a person sitting and falling, and utilizes a point cloud vs a person’s identifiable features, which allows the sensor to be used in areas where privacy is vital such as bathrooms and bedrooms.

Click here to explore the AOP evaluation module

featured paper

Configure the backup voltage in a reversible buck/boost regulator

Sponsored by Maxim Integrated

This application note looks at a reference circuit design using Maxim’s MAX38888, which provides a supercapacitor-based power backup in the absence of the system rail by discharging its stored charge. The backup voltage provided by the regulator from the super cap is 12.5% less than the system rail when the system rail is removed. This note explains how to maintain the backup voltage within 5% of the minimum SYS charge voltage.

Click to read more

featured chalk talk

Power over Ethernet - Yesterday, Today, and Tomorrow

Sponsored by Mouser Electronics and Microchip

Power over Ethernet has come a long way since its initial creation way back in 1997. In this episode of Chalk Talk, Amelia Dalton chats with Alan Jay Zwiren from Microchip about the past, present, and future of power over ethernet including details of how a PoE system works, why midspans are crucial for power over ethernet connectivity and why Microchip can be your one stop shop for your next PoE design needs.

Click here for more information about Microchip Technology multi-Power over Ethernet (mPoE)