Digital hardware modeling using VHDL, Verilog, SystemVerilog, SystemC, HLS (C++, OpenCL)

Directory

introduction

1. Overview of Digital Hardware Modeling

1.1 Hardware Description Language

1.2 System-level modeling language

2. Abstract level hardware model

2.1 Logical Level Model

2.2 Register Transfer Level Model (RTL)

2.3 Transaction Level Model (TLM)

2.4 Behavior/Algorithm Level Model

3. Design and coding practice of hardware model

3.1 Modular design

3.2 Design for reusability

3.3 Coding style

4. Integration and Validation of Hardware Models

4.1 Integration

4.2 Verification

5. Flow from model to hardware

5.1 Specification of Design Constraints

5.2 Logic Synthesis

5.3 Technology Mapping, Placement and Routing

5.4 Timing Analysis and Closure

6. Create reusable and portable hardware models

6.1 Create a modular design

6.2 Using Parametric Design

6.3 Create a configurable interface

7. Build hardware models using best practices

7.1 Unambiguous naming conventions

7.2 Notes and Documentation

7.3 Modular and reusable design

8. Hardware Model Validation via Script-Driven Simulation


Introduction

In today’s world of digital hardware design, choosing an appropriate modeling language is a crucial step. This choice will determine how you describe and verify the design, and may affect the efficiency and throughput of the overall design process. In this post we discuss how to build hardware models in Verilog, SystemVerilog, VHDL, SystemC, HLS (C++, OpenCL) at various levels of abstraction: Logical, RTL, TLM and Behavioral/Algorithmic.

Our goal is to create as generic, reusable and portable hardware models as possible, built using design and coding best practices. Such models can be easily integrated into larger designs through a simple handshaking interface or as memory-mapped master/slave IP on an industry-standard bus interface such as AXI.

project download

1. Overview of Digital Hardware Modeling

Digital hardware modeling is an important part of digital system design. In the system design, the hardware model provides an abstract description of the actual hardware function and performance, so that the designer can design and verify the system without involving the details of the specific hardware implementation.

1.1 Hardware Description Language

Hardware description languages (HDL) such as VHDL, Verilog, and SystemVerilog are widely used in the establishment of hardware models. By using these languages, designers can build and simulate circuit structures and behaviors in high-level programming languages.

  1. VHDL: VHDL is a hardware description language based on the ADA language. It can be used to describe the behavior and structure of digital circuits with strong concurrency and type safety.

  2. Verilog: Verilog is a C-like hardware description language that is easy to learn and widely used in industry.

  3. SystemVerilog: SystemVerilog is a hardware description and hardware verification language based on Verilog, adding advanced features such as classes, random generation, and assertions.

1.2 System-Level Modeling Language

System-level modeling languages such as SystemC and HLS can be used for higher levels of abstraction, such as transaction-level models and algorithm-level models.

  1. SystemC: SystemC is a C++-based hardware description language designed to support system-level design and can be used to describe and simulate the interaction of hardware and software.

  2. HLS (C++/OpenCL): High-level synthesis (HLS) is a method that converts a behavioral description written in C++ or OpenCL into an RTL description. This way, designers can work at a higher level of abstraction, which increases the efficiency and quality of designs.

The choice and use of these languages and tools depends on the needs and constraints of the design, such as the complexity of the design, the expertise of the design team, the timeline of the project, performance requirements, etc.

2. Abstract level hardware model

According to different needs and applications, hardware models can be constructed at various levels of abstraction. These levels of abstraction include logic level, register transfer level (RTL), transaction level model (TLM) and behavioral/algorithmic level.

2.1 Logical Level Model

At the logic level, the hardware model is based on the description of gates, including logic gates such as AND, OR, and NOT. This kind of model can describe the functions of hardware very accurately, but it is not suitable for describing large-scale and complex designs, because it will make the model too large and complex.

In this part, we will use VHDL and Verilog to build logic-level models, including basic logic gates, complex combinational logic and sequential logic circuits, etc.

2.2 Register Transfer Level Model (RTL)

The register transfer level (RTL) model is a higher level abstraction that describes the flow of data between registers and how the data is processed on each clock cycle. RTL model is the mainstream method in hardware design, especially suitable for complex digital system design.

In this part, we will use VHDL, Verilog and SystemVerilog to build RTL models, which include basic registers and counters, complex data paths and control units, etc.

2.3 Transaction Level Model (TLM)

A transaction-level model (TLM) is a higher-level abstraction that focuses on the process of data exchange without caring about the specific implementation of data exchange. The TLM model can be used to quickly verify and evaluate system performance, and is suitable for large-scale system design.

In this part, we will use SystemC and HLS (C++/OpenCL) to build a TLM model, including basic bus transactions, complex system interconnection and high-level algorithm implementation, etc.

2.4 Behavior/Algorithm Level Model

At the highest level of abstraction, the hardware model focuses on the implementation of algorithms without concern for the underlying hardware implementation. This model can be used to verify and optimize the correctness and efficiency of algorithms, and is suitable for algorithm and software development.

In this part, we will use HLS (C++/OpenCL) to build behavioral/algorithmic-level models, including basic algorithmic operations, complex algorithmic processes, and high-performance parallel algorithms.

3. Hardware model design and coding practice

When building hardware models, there are some best practices that should be followed to ensure the quality and reusability of the models.

3.1 Modular Design

Modular design is a design technique that breaks down complex systems into independent sub-modules. Each sub-module can be designed and verified independently, and then connected with other modules through defined interfaces. This design method can greatly improve the efficiency and quality of the design.

3.2 Design Reusability

To improve the reusability of hardware models, some design principles should be followed. First, each module should have a clearly defined function, and the interface between modules should be simple and clear. Second, modules should avoid specific hardware features or technologies in order to be used in different environments and technologies. Finally, modules should be sufficiently parameterizable to be used in different configurations and conditions.

3.3 Coding Style

Good coding style is essential to improve code quality and readability. Consistent naming conventions should be followed, appropriate comments used, and complex statements and structures avoided.

4. Integration and verification of hardware models

After building the hardware model, integration and verification are required to ensure the correctness and performance of the model.

4.1 Integration

The integration of the hardware model includes two aspects: the integration between modules and the integration of the model with a larger system. Integration between modules requires defining and implementing appropriate interfaces so that modules can connect and interact properly. Integration of models into larger systems requires defining and implementing appropriate adapters or bridges so that models can be integrated as memory-mapped master/slave IP onto industry-standard bus interfaces such as AXI.

4.2 Verification

The verification of the hardware model includes functional verification and performance verification. Functional verification is mainly carried out through simulation, and test cases can be generated in a script-driven manner, and the correctness of the model can be checked by comparing the simulated results with the expected results. Performance verification needs to evaluate the performance of the model under actual conditions, including timing, area, power, etc.

Among them, C/RTL co-simulation is an effective verification method, and a test bench can be used for pre-synthesis or RTL functional verification. In addition, post-synthesis or gate-level functional verification using a test bench is also a necessary step to ensure that the model behaves as expected on real hardware.

5. Flow from model to hardware

After building and verifying a hardware model, it is necessary to convert the model to an actual hardware implementation. This process typically includes steps such as design constraint specification, logic synthesis, technology mapping, place and route, timing analysis and closure.

5.1 Design Constraints Specification

The design constraint specification is the first step in hardware implementation, which defines the design goals and constraints, including clock frequency, power consumption budget, area budget, I/O pin constraints, etc. The design constraint specification is an input to synthesis and layout tools and affects the quality and performance of the hardware implementation.

5.2 Logic Synthesis

Logic synthesis is the process of converting an RTL model into a logic gate-level model, which optimizes the design according to the design constraint specification. The result of logic synthesis is a netlist, which describes the logical structure and interconnections of the hardware.

5.3 Technology Mapping, Placement and Routing

Technology mapping is the process of mapping a logical gate-level model to process-specific library cells, which produces a physical-level model. Placement and routing is the process of laying out the physical-level model onto the silicon and connecting the various parts, which results in a fully realized hardware design.

5.4 Timing Analysis and Convergence

Timing analysis is the process of evaluating whether a design can meet clock frequency and timing constraints. If the design cannot meet the timing constraints, you need to adjust the design or constraints and repeat the previous steps until the design converges.

The above is the whole process of digital hardware modeling using VHDL, Verilog, SystemVerilog, SystemC, HLS (C++, OpenCL), I hope it will be helpful to you. In the following articles, we will introduce the implementation methods and skills of each step in detail, so stay tuned.

6. Create reusable and portable hardware models

When we start writing a hardware model, the end goal should be to create a module that can be reused across multiple projects. Below are several key steps and strategies for creating reusable and portable hardware models.

6.1 Create a modular design

Breaking down a design into smaller, simpler modules can help us better understand and manage complex hardware systems. Each module should be self-contained and have a single, well-defined task. The result of this is that each module can be tested and verified individually, and all modules can then be combined to build more complex systems.

6.2 Using Parametric Design

With parametric design, we can modify the properties of the hardware model at compile time. This allows us to create multiple versions of hardware models from the same source code without modifying the code. Parametric design increases code reusability and flexibility while reducing the possibility of errors.

6.3 Create a configurable interface

The interface to the hardware model should be flexible so that it can interoperate with a variety of different hardware and software environments. For example, hardware models can be created using a common interface standard such as AXI for use in different systems.

7. Build hardware models using best practices

Whether in VHDL, Verilog, SystemVerilog, SystemC, or HLS (C++, OpenCL) environments, there are some coding and design best practices that can help us build higher quality, more reliable hardware models.

7.1 Unambiguous naming conventions

Naming conventions should be clear, concise, and easy to understand. The names of variables, functions, and modules should all accurately describe what they do. Using such a naming convention makes the code easier to read and understand, reducing the chance of confusion and misinterpretation.

7.2 Comments and Documentation

Good comments and documentation are crucial to any project. Adding detailed comments to your code can help other developers understand what the code does and how it works. Additionally, separate documents should be created to describe a high-level view of the design, design decisions, and any known issues or limitations.

7.3 Modular and reusable design

Modular and reusable designs not only make code easier to manage and understand, but also make it easier to change and add functionality. In addition, this design approach can also increase the stability of the code, because each module can be tested and verified independently.

8. Hardware model verification via script-driven simulation

Verifying the correctness and performance of hardware models is an important part of the hardware design process. At this stage, we use script-driven simulation to generate test cases and verify the behavior of the model.

Example testbench script

Here are some examples of testbench scripts written in Verilog to verify a simple adder module.

First, here’s our adder module (adder.v):

module adder(
    input [31:0] a,
    input [31:0] b,
    output reg [31:0] sum
);
    always @* begin
        sum = a + b;
    end
endmodule

Next is the corresponding testbench script (adder_tb.v):

module adder_tb;
    reg [31:0] a;
    reg [31:0] b;
    wire [31:0] sum;

    // Instantiate the module under test
    adder dut(a, b, sum);

    initial begin
        // Generate test cases and check the results
        a = 32'h00000001; b = 32'h00000001; #10;
        if (sum !== 32'h00000002) begin
            $display("Test failed: %h + %h = %h", a, b, sum);
        end

        a = 32'h00000000; b = 32'h00000000; #10;
        if (sum !== 32'h00000000) begin
            $display("Test failed: %h + %h = %h", a, b, sum);
        end

        a = 32'hFFFFFFFF; b = 32'h00000001; #10;
        if (sum !== 32'h00000000) begin
            $display("Test failed: %h + %h = %h", a, b, sum);
        end

        // The test is complete, exit the simulation
        $finish;
    end
endmodule

In this testbench script, we instantiate an adder module and generate test cases by varying the values of the inputs a and b . Then, we check that the value of the output sum is as expected. If not as expected, we print an error message. After completing all test cases, we end the simulation.

Note that this is just a simple example, and real testbenches may need to handle more complex situations, such as random testing, concurrent testing, and constraint-based verification, etc.