Easy Tutorial
❮ Google Python Styleguide Android Tutorial Intent Base ❯

8.2 Verilog TF Subprograms

Classification Verilog Tutorial Advanced Chapter

Functional Features

TF (task/function) subprograms are primarily used for data transfer in both directions at the boundary between Verilog and user C programs.

TF subprograms always start with the prefix tf_ and are defined in the header file veriuser.h. Therefore, when writing system tasks or functions in C, it is necessary to add #include "veriuser.h" in the C file.

The uses of TF subprograms can be divided into:

For a complete list of TF subprograms and their simple usage instructions, please refer to the next section "8.3 List of TF Subprograms".

Example of TF Subprograms

There are numerous PLI subprogram library functions, and explaining each one would require a lot of space to summarize. Therefore, it is recommended to study individual subprograms carefully only when needed. The following examples only illustrate some of the subprograms in TF, mainly to explain the basic process of using TF subprograms to design Verilog system tasks.

Design Requirements

Sometimes, to reduce the size of the object file compiled from the C language file, or to output debugging information in a certain format, the print function in the software may not use the built-in printf function of C, nor the io_printf function in the TF subprogram, but instead use the PLI interface and Verilog's system display functions ($display or $write) to complete a user-defined software print function.

This time, a software print function is designed, named print_my, with the output format of "string + integer".

Design Analysis

The user-defined software print function print_my is just a superficial shell, used to pass the print information to the software formal parameter variables. To pass the print information to Verilog, a system task built with a TF subprogram is also needed, named $send_my().

It should be noted that the system tasks completed with TF subprograms generally need to be called in the Verilog code. Directly calling this "system task" in the software is equivalent to calling a software function, and there is no direct connection with the description of the related variables in the Verilog code. Therefore, it is meaningless to directly call the "software function" send_my in the software function print_my, and some specific software behaviors need to be added to the print_my to trigger the Verilog call to the system task $send_my.

If the digital system includes a CPU, the method of writing the bus or memory by the software and then monitoring the related signal variables in the testbench can be used. The scale of this design is relatively small, and another method can be adopted, that is, the system task $send_my is always executed in Verilog, and the global variable is set in the software function print_my to control whether to perform the information transmission and printing operation.

Software Design

The software design code is as follows, with details explained in the comments, saved in the file print_gyc.c.

Example

#include "veriuser.h"

//Print string, integer data, and the software start printing flag
char *str_mes;
unsigned int int_mes;
int flags = 0;

//===== define print_my() used in C ======
void print_my(char *str_send, unsigned int int_send){
    str_mes = str_send;
    int_mes = int_send;
    flags = 1;
}

//The string corresponding to the ASCII code of the character type data, the original character type length is limited to 100
//For example, the ASCII code of the character "1" is 0x31, and the character type data corresponding to 0x31 is 0x33, 0x31
char str_mes_format[200];
//When the TF subprogram passes string type data, it can only pass data in the relevant number system format
//For example, it can pass "0xc0de1234", but it cannot pass "www.tutorialpro.org"
//So it is necessary to convert the original string data into the corresponding ASCII character type data
void byte2hexstr(char* str, char* dest, int len)
{
    char tmp;
    int i;
    char stb[16] = { '0', '1', '2', '3', '4', '5', '6',
Due to the inability of the software part of this design to execute proactively, an additional Verilog system task designed with the TF subroutine is added. This system task, when executed in the testbench, can call the function print_my from the software program.

Add the following C code to the file print_gyc.c:

```c
void call_c_print(){
    if (tf_getp(1) == 1) //If the first parameter value of the system function is 1
        print_my("It's the first successful print: ", 0x20170714);
    else if (tf_getp(1) == 2) //If the second parameter value of the system function is 2
        print_my("2nd: ", 0x09070602);
    else
        print_my("", 0x1); //No string data is transferred, an error is reported
}

Add the following Verilog code to the file test.v:

//c print
initial begin
    #100 ;
    $call_c_print(1);
    #100 ;
    $call_c_print(2);
    #100 ;
    $call_c_print(3);
end

Compilation Simulation

Under Linux, compile print_gyc.c with the following command to output the print_gyc.o file, pay attention to the relative path.

gcc -I ${VCS_HOME}/include -c ../tb/print_gyc.c

For VCS compilation, a link table file recognizable by VCS needs to be created, named pli_gyc.tab, with the following content.

$send_my, $call_c_print are the names of the system tasks called by Verilog;

call=my_monitor, call=call_c_print and so on indicate the calling of functions in the software C program;

$send_my call=send_my
$call_c_print call=call_c_print

Add the following parameter line when compiling with VCS.

-P ../tb/pli_gyc.tab

The simulation results are as follows.

As can be seen from the diagram, the print output is normal, with no superfluous blank information.

When there is no string data in the print information, an Error will be reported, and some debugging information will be output.

You can modify some parameters in the testbench for debugging and learning in data storage format.

Download the source code for this section

Download

-0.1 Digital Logic Design

-0.2 Verilog Coding Style

-0.3 Verilog Code Specification

-1.1 Types of Verilog Gates

-1.2 Verilog Switch-Level Modeling

-1.3 Verilog Gate Delay

-2.1 Basic Knowledge of Verilog UDP

-2.2 Verilog Combinational Logic UDP

-2.3 Verilog Sequential Logic UDP

-3.1 Verilog Delay Model

-3.2 Verilog Specify Block Statements

-3.3 Verilog Setup and Hold Times

-3.4 Verilog Timing Checks

-3.5 Verilog Delay Back Annotation

-4.1 Verilog Synchronization and Asynchrony

-4.2 Verilog Cross-Clock Domain Transfer: Slow to Fast

-4.3 Verilog Cross-Clock Domain Transfer: Fast to Slow

-4.4 Verilog FIFO Design

-5.1 Introduction to Verilog Reset

-5.2 Introduction to Verilog Clock

-5.3 Verilog Clock Division

-5.4 Verilog Clock Switching

-6.1 Introduction to Verilog Low Power

-[6.2 System-Level Low Power Design in Verilog](verilog2-

❮ Google Python Styleguide Android Tutorial Intent Base ❯