VerilogPLItutorial.doc

上传人:sk****8 文档编号:3520772 上传时间:2019-06-01 格式:DOC 页数:53 大小:741KB
下载 相关 举报
VerilogPLItutorial.doc_第1页
第1页 / 共53页
VerilogPLItutorial.doc_第2页
第2页 / 共53页
VerilogPLItutorial.doc_第3页
第3页 / 共53页
VerilogPLItutorial.doc_第4页
第4页 / 共53页
VerilogPLItutorial.doc_第5页
第5页 / 共53页
点击查看更多>>
资源描述

1、Verilog PLI 教程 1Verilog PLI 教程:第一部分 介绍2007-09-24 来源:数字集成电路设计者 作者:5lifeVerilog PLI(可编程语言接口)是在 Verilog 代码中运行 C 或者 C+的一种机制。用 C/C+写函数编译代码并产生共享库(windows 下是*.dll 文件,Unix 下是*.so 文件)。VCS 这样的仿真工具也允许静态链接。在 verilog 代码中调用这些函数Verilog PLI(可编程语言接口)是在 Verilog 代码中运行 C 或者 C+的一种机制。 系统调用是指在 verilog 代码中调用的函数。一个例子:内置系统任务

2、$display,$stop,$random。 PLI 允许用户创建自己的系统调用,实现 Verilog 语法不能实现的功能。如: 功耗分析 代码覆盖率工具 能修改 verilog 仿真数据结构,得到更精确的延时信息 用户定制的输出显示 联合仿真 设计调试工具 仿真分析 创建 C 模型接口,加快仿真 Testbench 建模 为了实现上述 PLI 的一些应用,C 代码必须能 access verilog 仿真器的内部数据结构。于是,Verilog PLI 提供了一些 acc 程序或者简单的 access 程序。第二种程序系列叫做 tf 程序,或者简单的任务和函数。 tf 和 acc 都是 PL

3、I1.0 的程序,是既大又老的程序。另一种程序在最新的 verilog 2001 版本引入,叫做 vpi 程序。这是一种小而清晰的 PLI 程序,称作 PLI2.0。 通过 Verilog 2001 LRM 和 PLI1.0 IEEE 文档,你可以查阅 PLI 提供的每个函数的详细资料。Verilog IEEE LRM 是为有硬件背景的人都可以读懂而写的。如果你拿不到以上的 IEEE 文档,你可以购买在书籍章节里列出的 PLI 书籍。 PLI 是如何工作的 用 C/C+写函数 编译代码并产生共享库(windows 下是*.dll 文件,Unix 下是*.so 文件)。VCS这样的仿真工具也允许

4、静态链接。 在 verilog 代码中调用这些函数(大多数是在 verilog 的 testbench) 在 verilog 代码的编译过程中,把 C/C+函数详细信息传给仿真器。一旦链接成功,就可以像任何 verilog 仿真一样运行仿真器 在仿真器执行 verilog 代码时,当仿真器遇到用户自定义的任务(以$开头),PLI 程序(C/C+函数)得到运行控制。 例子 - Hello World 我们将定义一个 hello 函数,当它被调用时,将打印出“Hello Deepak”。这个例子将不使用任何的 PLI 标准函数(ACC,TF 和 VPI)。对于详细的链接信息,请参考仿真器的手册。每

5、个仿真器都有它自己的方式把 C/C+函数链接到仿真器。 C 代码 1i nclude 2 3void hello () 4 printf ( “nHello Deepakn“ ); 5verilog 代码1module hello_pli ();2 3initial begin4 $hello;5 #10 $finish;6end7 8endmodule开始仿真一旦链接完成,仿真就如以前我们见过的普通仿真一样,只是在命令行的选项上有些许改变。就是我们必须要告诉仿真器,我们要使用 PLI(Modelsim 需要在命令行上指定加载哪个共享对象)。Verilog PLI 教程 1Verilog PL

6、I 教程:第二部分 编写 PLI 应用程序(续)Verilog PLI 教程:第二部分 编写 PLI 应用程序 2008-08-09 01:19分类:技术文章 字号: 大大 中中 小小 先前我们所看的例子太基础也没有实际用途。让我们看计数器的例子,写一个 DUT 的参考模型以及用 C 写的 Checker 程序,并把它链入到 Verilog 的 Testbench。首先列出我们要用 PLI 写 C 模型的要求。调用 C 模型的方法,当输入信号有任何变化时; 获得 verilog 代码中改变了的信号值或者任何 C 代码内部的信号的方法 通过 C 代码驱动 Verilog 内部值 VerilogP

7、LI 提供一系列满足以上要求的程序(函数) 。PLI 应用的 SPEC我们定义使用 PLI 的计数器 testbench 的要求。 该 PLI 函数我们称作 $counter_monitor用 C 实现一个计数器逻辑 用 C 实现一个检测逻辑 当 checker 失败时,终止仿真 调用 C 函数用 C 写计数器非常简单,但是什么时候我们要增加计数器的值呢?所以我们就需要监测时钟信号的变化(顺便说一句,通过 verilog 代码驱动复位和时钟信号是个好习惯)一旦时钟发生变化,计数器函数就要被执行。这可以通过以下的函数实现:使用 acc_vcl_add 程序。该函数的语法可以查阅 Verilog

8、PLI LRM 基本上 acc_vcl_add 程序能检测许多信号,一旦任何一个信号改变就会调用用户定义的函数(也就是定制的 C 程序) 。VCL 程序有 4 个自变量:需要监测对象的句柄 用户 C 程序,当对象值变化就会调用它 传递给 C 程序的字符串 预定义的 VCL 标志:vcl_verilog_logic - 逻辑监测vcl_verilog_strength - 强度监测 acc_vcl_add(net, display_net, netname, vcl_verilog_logic);C 代码 - 基础Counter_monitor 是我们在 verilog testbench 中将

9、要调用的 C 函数。就像任何其他的 C 代码,我们需要包含针对我们所要开发的特定的应用的头文件。我们这里,需要包含 acc 程序include 文件。access 函数 acc_initialize 初始化 access 程序的环境,在程序调用任何的 access 程序前必须要调用的。在退出调用 access 程序的 C 应用程序前,在程序的最后必须要退出 access 程序环境,调用 acc_close。1 #include “acc_user.h“ 2 3 handle clk ;4 handle reset ;5 handle enable ;6 handle dut_count ;7

10、void counter ();8 9 void counter_monitor() 10 acc_initialize();11 clk = acc_handle_tfarg(1);12 reset = acc_handle_tfarg(2);13 enable = acc_handle_tfarg(3);14 dut_count = acc_handle_tfarg(4);15 acc_vcl_add(clk,counter,null,vcl_verilog_logic);16 acc_close();17 18 19 void counter () 20 io_printf( “Cloc

11、k changed staten“ ); 21 为了能 accessing verilog 对象,我们使用句柄。句柄是指预定义的数据类型,它是是设计层次中某个对象的指针。每个句柄传递给 access 函数有关唯一可以 accessible 对象的类型信息,以及如何哪里能找到有关此对象的信息。但是,我们如何把某个特定对象的信息给句柄呢?我们可以通过许多途径,但是现在我们用 verilog 采用参数传递的方式给$counter_monitor, 这些参数在 C 程序中可以采用 acc_handle_tfarg()函数获得,这里自变量和代码中一样是数字。因此 clk = acc_handle_tfa

12、rg(1) 使得 clk 作为第一参数传递的句柄。类似我们给所有的句柄赋值。现在我们可以把 clk 加入我们需要检测的信号列表中,acc_vcl_add(clk,counter,null,vcl_verilog_logic)。这里 clk 是句柄,counter 是当 clk 发生变化时,需要执行的用户函数。函数 counter()就不作任何解释了,它是类似于 hello world 简单的代码。Verilog 代码下面是计数器例子的简单的 testbench。We call the C-function using the syntax shown in code below. If obj

13、ect thats been passed is a instant, then it should be passed inside double quotes. Since all our objects are nets or wires, there is no need to pass them inside double quote. 1 module counter_tb();2 reg enable;3 reg reset;4 reg clk_reg;5 wire clk;6 wire 3:0 count;7 8 initial begin9 enable = 0;10 clk

14、_reg = 0;11 reset = 0;12 $display( “%g , Asserting reset“ , $time); 13 #10 reset = 1;14 #10 reset = 0;15 $display ( “%g, Asserting Enable“ , $time); 16 #10 enable = 1;17 #55 enable = 0;18 $display ( “%g, Deasserting Enable“ , $time); 19 #1 $display ( “%g, Terminating Simulator“ , $time); 20 #1 $fini

15、sh;21 end22 23 always begin24 #5 clk_reg = !clk_reg;25 end26 27 assign clk = clk_reg;28 29 initial begin30 $counter_monitor(counter_tb.clk, counter_tb.reset, counter_tb.enable, counter_tb.count);31 end32 33 counter U(34 .clk (clk),35 .reset (reset),36 .enable (enable),37 .count (count)38 );39 40 end

16、module使用不同的仿真器,编译和运行程序不同。当你运行以上的代码,我们将得到以下的输出:0 , Asserting resetClock changed stateClock changed stateClock changed state20, Asserting EnableClock changed stateClock changed stateClock changed stateClock changed stateClock changed stateClock changed stateClock changed stateClock changed stateClock

17、changed stateClock changed stateClock changed stateClock changed stateClock changed state85, Deasserting EnableClock changed state86, Terminating SimulatorC 代码 - 完整现在我们可以看见当时钟发生变化时,我们的函数就会被调用。 我们可以写我们的计数器代码了。但是,有一个问题,每次计数器调用的时候,就会退出也就会丢失内部变量的值。我们有 2 重方法来保持变量的值。把计数器变量申明为全局变量 使用 tf_setworkarea() 和 tf_

18、getworkarea()存储和恢复本地变量的值 由于我们只有一个变量,我们可以采用第一种解决方法,也就是申明 count 为全局变量为了编写与计数器等价的模型,输入到 DUT 和代码 checker 的 clock,reset, enable 信号以及DUT count 的输出都需要。为了从 verilog 获取值,我们使用 PLI 函数:acc_fetch_value(handle,“format“)但是该值返回的是字符串,因此我们需要把它转变为整数。pli_conv 是完成这个转换的函数。当 DUT 和 TB 计数值不相同时,函数 tf_dofinish()用做终止该仿真。1 #incl

19、ude “acc_user.h“ 2 3 typedef char * string;4 handle clk ;5 handle reset ;6 handle enable ;7 handle dut_count ;8 int count ;9 int sim_time;10 string high = “1“ ; 11 void counter ();12 int pli_conv (string in_string, int no_bits);13 14 void counter_monitor() 15 acc_initialize();16 clk = acc_handle_tfa

20、rg(1);17 reset = acc_handle_tfarg(2);18 enable = acc_handle_tfarg(3);19 dut_count = acc_handle_tfarg(4);20 acc_vcl_add(clk,counter,null,vcl_verilog_logic);21 acc_close();22 23 24 void counter () 25 p_acc_value value;26 sim_time = tf_gettime();27 string i_reset = acc_fetch_value(reset, “%b“ ,value);

21、28 string i_enable = acc_fetch_value(enable, “%b“ ,value); 29 string i_count = acc_fetch_value(dut_count, “%b“ ,value); 30 string i_clk = acc_fetch_value(clk, “%b“ ,value); 31 int size_in_bits= acc_fetch_size (dut_count);32 int tb_count = 0;33 / Counter function goes here34 if (*i_reset = *high) 35

22、count = 0;36 io_printf( “%d, dut_info : Counter is resetn“ , sim_time); 37 38 else if (*i_enable = *high) 41 else 42 count = count + 1;43 44 45 / Counter Checker function goes checker logic goes here46 if (*i_clk != *high) 48 if (tb_count != count) 49 io_printf( “%d, dut_error : Expect value %d, Got

23、 value %dn“ , sim_time, count, tb_count); 50 tf_dofinish();51 else 52 io_printf( “%d, dut_info : Expect value %d, Got value %dn“ , sim_time, count, tb_count); 53 54 55 56 57 / Multi-bit vector to integer conversion.58 int pli_conv (string in_string, int no_bits) 59 int conv = 0;60 int i = 0;61 int j

24、 = 0;62 int bin = 0;63 for ( i = no_bits-1; i = 0; i = i - 1) 64 if (*(in_string + i) = 49) 65 bin = 1;66 else if (*(in_string + i) = 120) 67 io_printf ( “%d, Warning : X detectedn“ , sim_time); 68 bin = 0;69 else if (*(in_string + i) = 122) 70 io_printf ( “%d, Warning : Z detectedn“ , sim_time); 71

25、 bin = 0;72 else 73 bin = 0;74 75 conv = conv + (1 j)*bin;76 j +;77 78 return conv;79 与仿真器链接先前我们见到的计数器例子,我们将用下面的仿真器进行链接。VCS Modelsim 在此教程中,我们使用 linux。如果你想知道如何在 windows 或者 solaris 下链接,请参考仿真器的手册查看详细资料。VCS使用 VCS 仿真器,我们需要创建一个 tab 文件。对于我们的例子,tab 文件如下所示:$counter_monitor call=counter_monitor acc=rw:*这里 $co

26、unter_monitor 是在 verilog 代码中的用户自定义函数。call=counter_monitor 是当verilog 调用$counter_monitor 时调用的 C 函数。acc=rw:*是告诉我们要使用 access 函数去读写仿真器内部数据。:*意味着应用于设计中的所有模块。编译代码的命令行选项如下:vcs -R -P pli_counter.tab pli_counter_tb.v counter.v pli_full_example.c -CFLAGS “-g -I$VCS_HOME/vcs -platform/lib“ +acc+3由于我们要使用返回值,我们使用

27、+acc+3,剩下的选项简单,你可以查阅 VCS 的用户指南。Modelsim类似于 VCS, modelsim 仿真器是用 PLI 有它自己的方式。我们需要创建函数列出所有在verilog 中要使用的用户自定义函数以及对应的 C 函数。与 VCS 不同,我们需要在 C 文件中写明,如下:1 #include “veriuser.h“ 2 #include “pli_full_example.c“ 3 4 s_tfcell veriusertfs = 5 usertask, 0, 0, 0, counter_monitor, 0, “$counter_monitor“ , 6 0 / last

28、 entry must be 0 7 ;vlib workvlog pli_counter_tb.v counter.vgcc -c -g -I$MODEL/include pli_full_example_modelsim.cld -shared -E -o pli_full_example.sl pli_full_example_modelsim.ovsim -c counter_tb -pli pli_full_example.sl在 vsim 命令行中,输入 run -all 开始仿真。查阅 modelsim 的用户指南了解详细信息以及了解如何编译和链接在 windows 下。计数器仿

29、真结果0 , Asserting reset10, dut_info : Counter is reset15, dut_info : Counter is reset20, Asserting Enable20, dut_info : Expect value 0, Got value 030, dut_info : Expect value 0, Got value 040, dut_info : Expect value 1, Got value 150, dut_info : Expect value 2, Got value 260, dut_info : Expect value

30、3, Got value 370, dut_info : Expect value 4, Got value 480, dut_info : Expect value 5, Got value 585, Deasserting Enable86, Terminating Simulator先前我们所看的例子太基础也没有实际用途。让我们看计数器的例子,写一个 DUT 的参考模型以及用 C 写的 Checker 程序,并把它链入到 Verilog 的 Testbench。首先列出我们要用 PLI 写 C 模型的要求。调用 C 模型的方法,当输入信号有任何变化时; 获得 verilog 代码中改变了

31、的信号值或者任何 C 代码内部的信号的方法 通过 C 代码驱动 Verilog 内部值 VerilogPLI 提供一系列满足以上要求的程序(函数) 。PLI 应用的 SPEC我们定义使用 PLI 的计数器 testbench 的要求。 该 PLI 函数我们称作 $counter_monitor用 C 实现一个计数器逻辑 用 C 实现一个检测逻辑 当 checker 失败时,终止仿真 调用 C 函数用 C 写计数器非常简单,但是什么时候我们要增加计数器的值呢?所以我们就需要监测时钟信号的变化(顺便说一句,通过 verilog 代码驱动复位和时钟信号是个好习惯)一旦时钟发生变化,计数器函数就要被执

32、行。这可以通过以下的函数实现:使用 acc_vcl_add 程序。该函数的语法可以查阅 Verilog PLI LRM 基本上 acc_vcl_add 程序能检测许多信号,一旦任何一个信号改变就会调用用户定义的函数(也就是定制的 C 程序) 。VCL 程序有 4 个自变量:需要监测对象的句柄 用户 C 程序,当对象值变化就会调用它 传递给 C 程序的字符串 预定义的 VCL 标志:vcl_verilog_logic - 逻辑监测vcl_verilog_strength - 强度监测 acc_vcl_add(net, display_net, netname, vcl_verilog_logic

33、);C 代码 - 基础Counter_monitor 是我们在 verilog testbench 中将要调用的 C 函数。就像任何其他的 C 代码,我们需要包含针对我们所要开发的特定的应用的头文件。我们这里,需要包含 acc 程序include 文件。access 函数 acc_initialize 初始化 access 程序的环境,在程序调用任何的 access 程序前必须要调用的。在退出调用 access 程序的 C 应用程序前,在程序的最后必须要退出 access 程序环境,调用 acc_close。1 #include “acc_user.h“ 2 3 handle clk ;4 h

34、andle reset ;5 handle enable ;6 handle dut_count ;7 void counter ();8 9 void counter_monitor() 10 acc_initialize();11 clk = acc_handle_tfarg(1);12 reset = acc_handle_tfarg(2);13 enable = acc_handle_tfarg(3);14 dut_count = acc_handle_tfarg(4);15 acc_vcl_add(clk,counter,null,vcl_verilog_logic);16 acc_

35、close();17 18 19 void counter () 20 io_printf( “Clock changed staten“ ); 21 为了能 accessing verilog 对象,我们使用句柄。句柄是指预定义的数据类型,它是是设计层次中某个对象的指针。每个句柄传递给 access 函数有关唯一可以 accessible 对象的类型信息,以及如何哪里能找到有关此对象的信息。但是,我们如何把某个特定对象的信息给句柄呢?我们可以通过许多途径,但是现在我们用 verilog 采用参数传递的方式给$counter_monitor, 这些参数在 C 程序中可以采用 acc_handl

36、e_tfarg()函数获得,这里自变量和代码中一样是数字。因此 clk = acc_handle_tfarg(1) 使得 clk 作为第一参数传递的句柄。类似我们给所有的句柄赋值。现在我们可以把 clk 加入我们需要检测的信号列表中,acc_vcl_add(clk,counter,null,vcl_verilog_logic)。这里 clk 是句柄,counter 是当 clk 发生变化时,需要执行的用户函数。函数 counter()就不作任何解释了,它是类似于 hello world 简单的代码Verilog PLI 教程:第二部分 编写 PLI 应用程序(续) 2008-08-09 01:21分类:技术文章 字号: 大大 中中 小小 先前我们所看的例子太基础也没有实际用途。让我们看计数器的例子,写一个 DUT 的参考模型以及用 C 写的 Checker 程序,并把它链入到 Verilog 的 Testbench。首先列出我们要

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 实用文档资料库 > 策划方案

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。