VPI:
Verilog Prodecure Interface(VPI), 最开始也称作PLI 2.0, 一个主要面向C语言的接口. 可以让行为级别的Verilog代码调用C函数, 让C函数调用标准Verilog系统函数.
1 // adder.c
2#include <vpi_user.h>
3
4static int sum_compiletf(char *user_data)
5{
6 fprintf(stderr, "Yes, youcompiled me\n");
7 return 0;
8}
9
10static int sum (char *user_data)
11{
12 vpiHandle systfref, args_iter,argh;
13 // typedef struct t_vpi_values_vpi_value
14 struct t_vpi_value argval;
15 unsigned int value, value2;
16 char res[1024];
17
18 systfref = vpi_handle(vpiSysTfCall,NULL);
19 args_iter =vpi_iterate(vpiArgument, systfref); // 迭代所有参数.
20
21 argh = vpi_scan(args_iter); // 获取下一个参数
22 argval.format = vpiIntVal; // 设定格式为int
23 vpi_get_value(argh, &argval); //获取参数值
24 value = argval.value.integer; // 读取获取到的参数值
25
26 argh = vpi_scan(args_iter); // 获取下一个参数
27 argval.format = vpiHexStrVal; // 以hex格式读入
28 vpi_get_value(argh, &argval);
29 sscanf(argval.value.str, "%x",&value2); // 将hex str格式读入的值转换为int
30
31 argh = vpi_scan(args_iter); // 获取第三个参数
32 argval.format = vpiHexStrVal; // 设置格式为hex str, verilog读取的时候会自动转换的.
33 sprintf(res, "%x", value+ value2); // 在C里计算两个值的和, 并将其转换为hex格式的字符串
34
35 argval.value.str = res;
36 vpi_put_value(argh, &argval, 0,vpiNoDelay); // 设置第三个参数的值
37
38 vpi_put_value(systfref,&argval, 0, vpiNoDelay);
39 vpi_free_object(args_iter);
40 return 0;
41}
42
43
44// 注册 $sum
45void sum_register() {
46 s_vpi_systf_data tf_data;
47
48 tf_data.type = vpiSysTask; // 类型. 还有一个是SysFunc
49 tf_data.tfname = "$sum"; // 在verilog中调用的名称
50 tf_data.calltf = sum; // 被verilog调用时调用的函数
51 tf_data.compiletf = sum_compiletf; //被编译时调用的函数
52 tf_data.sizetf = 0; // 不知道
53 tf_data.user_data = 0; // 不知道
54 vpi_register_systf(&tf_data); //注册
55}
56
57
58
59// 在这个函数数组里的函数会自动被调用.
60void (*vlog_startup_routines[])() = {
61 sum_register,
62 0
63};
1 // adder_tb.v
2`timescale 1ns/1ns
3module adder_tb();
4 reg [3:0] a;
5 reg [3:0] b;
6 wire [7:0] c;
7
8 reg clk,rst_n;
9
10 integer i, n, nf;
11
12 adder DUT (
13 .clk(clk),
14 .rst_n(rst_n),
15 .a(a),
16 .b(b),
17 .c(c)
18 );
19
20 always begin
21 #10 clk = 0;
22 #10 clk = 1;
23 end
24
25 initial begin
26 $display("=============================");
27 $display("Tb start athere");
28 rst_n = 1;
29 n = 0;
30 nf = 0;
31 // $test($random%4,2);
32 for (i = 0; i < 20; i++)
33 test($urandom%5'b10000,$urandom%5'b10000);
34 $display("%d total, %dfail", n, nf);
35 $finish;
36 end
37 task test;
38 input [3:0] in;
39 input [3:0] in2;
40 begin: test
41 reg [7:0] e;
42 a = in;
43 b = in2;
44 $sum(a,b,e); // HERE
45 @(posedge clk);
46 @(negedge clk);
47 n = n + 1;
48 if (c == e) begin
49 $display("Itworks, %d + %d = %d", in, in2, e);
50 end else begin
51 nf = nf + 1;
52 $display("opps%d + %d ~= %d, expect %d", in, in2, c, e);
53 end
54 end
55 endtask
56
57 // initial begin
58 //$dumpfile("wave.vcd");
59 // $dumpvars;
60 // end
61endmodule