数字IC设计工具教程——VCS(lab2 VCS Debugging Basics)

数字IC设计工具教程——VCS(lab2)

参考:Synopsys VCS lab2

注意:由于UCLI(Unified Command-Line Interface)debug较困难,一般不常用!

Getting Started

我们将再次使用以下进位选择的8-bit加法器:
在这里插入图片描述
我们在实验文件中嵌入了错误。 目标是使用调试技术来定位和修复错误。 我们看到的块图是Verilog代码打算实现的内容。这个实验分为两部分。 每个部分都有自己的相关任务。

下面是概览:

  • 编译并仿真加法器以记录错误是什么。
  • 在Part A中,将Verilog系统任务调用插入设计文件中,然后编译、仿真和解释Verilog系统任务调用输出,以尝试将错误点固定。在找到并纠正错误之前,您将重复此过程。
  • 在Part B中,将启用UCLI调试器进行编译。 使用UCLI交互式模拟控制来完成代码的执行并定位错误源。更正错误并仿真以确认校正有效。
    在这里插入图片描述

Part A: 调用Verilog的系统任务debug

Task 1: 有用的VCS开关

进入lab2 Part A目录。

从此实验开始,将使用各种编译和运行时开关。 万一忘记了这些开关是什么,可以通过以下快速方式获取提醒:

shell> vcs -full64 -h

此命令将为您提供常用VCS编译时和运行时开关的列表,以及对其功能的简要说明。

Task 2: 编译执行第一次通过验证

编译并仿真进位选择加法器。

shell> vcs -full64 -f adder.f -R

一个错误被报告:
在这里插入图片描述
输入a=01,b=01,进位cin=0,但和sum=00而不是02(十六进制)。错误可能在任何的RTL模块中。我们将检查每一个操作。
在这里插入图片描述

Task 3: Debug错误

在调试中,必须能够通过设计跟踪错误。 如果选择仅使用Verilog系统任务调用调试,通常有两种跟踪错误的方法。 可以直接在RTL模块中插入Verilog系统任务调用,也可以在testbench中添加Verilog系统任务调用。

最好在testbench中添加调试语句。 原因有二:一是testbench通常是进行结果检查的地方。 使用Verilog系统任务调用以及结果检查程序可以有效地提供断点功能。 第二,出于性能原因,希望避免重新编译。通过将调试语句仅放在testbench中,您可以将重新编译限制为仅testbench文件。

修改testbench,以便通过设计层次结构跟踪错误。首先,查看testbench,选择Verilog系统任务调用放置的位置。 输入以下UNIX命令:

1. shell> more addertb.v

查看testbench如下:
在这里插入图片描述
最佳插入点是在检测错误之后。在此处插入更多$display系统任务调用,以便通过设计层次结构跟踪错误。首先查看add8模块中发生的情况。
(注:当在编译仿真时命令中加入参数+monitoroff后,$test\$plusargs("monitoroff")为True,否则为False)

在addertb.v中加入下面三行于$finish之前。

$display("\nIn add8(u1)");
$display("a = %b, b = %b, sum = %b; cin = %b, cout = %b", 
		u1.a, u1.b, u1.sum, u1.cin, u1.cout);

在这里插入图片描述
再编译仿真加法器看看add8模块级的结果。

2. shell> vcs -full64 -f adder.f -R

插入$display后的结果如下:
在这里插入图片描述
add4(u1)的输出sum[1]应该是1,相反,它错误地被计算为0。去add4(u1)看看发生了什么。
在这里插入图片描述
在addertb.v中加入下面三行于$finish之前。

$display("\nIn add4(u1)");
$display("a = %b, b = %b, sum = %b; cin = %b, c = %b, cout = %b", 
		u1.u1.a, u1.u1.b, u1.u1.sum, u1.u1.cin, u1.u1.c, u1.u1.cout);

将系统任务$finish改为$stop创建一个断点。
在这里插入图片描述
通过此修改,每次检测到错误时,都会打印$display中列出的结果,此时将停止testbench。

再次编译运行testbench:

3. shell> vcs -full64 -f adder.f -R

当VCS遇到我们嵌入的$stop系统任务调用时,它会将您放入UCLI调试器中。 您将看到UCLI提示 ucli%

首先看$display信息:
在这里插入图片描述
lsb操作看起来不错,但是,第二个lsb有问题。 看起来未加入进位。
在这里插入图片描述
继续仿真到下一个错误点,看看是否可以推断这真的是一个问题。 继续使用"run"进行仿真。 在继续之前,请尝试其他一些UCLI命令,看看它们是否有效。

4. ucli% run

仿真应该继续至下一个错误点并停止,可以看到:
在这里插入图片描述
注意到,问题似乎出在fa模块如何处理进位中。
在这里插入图片描述
退出UCLI命令模式:

5. ucli% quit

查看fa.v文件的内容:

6. shell> more fa.v

fa.v文件内容如下:
在这里插入图片描述
可以看到fa.v模块中全加器的进位未加入,修改为assign {cout, sum} = a + b + cin并重新编译,显示编译成功。
在这里插入图片描述
取消monitor系统任务进行仿真,这样可以提高仿真速度。

7. shell> simv +monitoroff

仿真结果如下:
在这里插入图片描述

Part B: 用VCS UCLI调试器debug

Task 1: 编译执行第一次通过验证

在Part A中,您可能注意到的一件事是,使用Verilog系统任务调用插入进行调试是一项大量工作。 不断执行完整的修改-编译-模拟-验证循环。 数据输入不仅耗时,此调试回路中的其他步骤也非常耗时。 在Part B,我们将使用UCLI命令集来简化调试过程。

在Part A,您需要使用笔和纸来帮助您诊断问题。UCLI简化,但并不能消除对笔和纸的需求。

切换至lab2 Part B目录。

再次,编译和仿真加法器,看看它是否正常工作。

shell> vcs -full64 -f adder.f -R

注意在时间50时出现了错误:
在这里插入图片描述在这里插入图片描述

Task 2: 启用UCLI调试器开关进行编译

重新编译,这一次,启用UCLI调试器。

首先,通过将文件$finish修改为$stop,在addertb.v中添加硬断点:
在这里插入图片描述
启用UCLI进行编译和仿真。

shell> vcs -full64 -f adder.f -R -debug_all -ucli

当VCS遇到我们嵌入的$stop系统任务调用时,它会进入UCLI调试器中。 将看到UCLI提示符ucli%

Task 3: 用UCLI调试器debug

调用UCLI调试器时,会将被放置在仿真时间0。

如果您忘记了UCLI可用命令,请尝试以下UCLI命令快速摘要:

ucli% help

要了解我们在设计层次结构中的位置,输入:
在这里插入图片描述
要到达问题区域,输入:
在这里插入图片描述
查看addertb中定义的信号。
在这里插入图片描述
列出所有信号/端口/范围等。要查看感兴趣的信号值,请使用获取命令。
在这里插入图片描述
sum_test总线不正确。 跟踪sum_test信号以查找问题。 使用scope命令进入u1(add8)模块。
在这里插入图片描述
在这里插入图片描述
在调试中,通常需要多次打印出同一组变量的值。为这个通常执行的任务创建一个别名将使事情变得容易得多。一旦我们创建了别名,执行任务可以通过键入别名。
在这里插入图片描述
在这里插入图片描述
可以在此处查看错误的详细信息。 2:1mux应选择"0"的sum_0值,但选择了"1"的sum_1值。 这可能是问题所在。
在这里插入图片描述
将UCLI窗口保留(不要退出UCLI)。 打开一个新的UNIX窗口,看看add8.v文件。
在这里插入图片描述
看看mux代码。 对mux的输入被颠倒。 事实上,sum和carry mux都有相同的错误。
在这里插入图片描述
幸运的是,可以在不离开UCLI环境的情况下仿真校正。如果将sum_0加法器的进位更改为"1",并将sum_1加法器的进位更改为"0",则将有效地纠正问题。
在这里插入图片描述
请注意zero_add_cin和one_add_cin信号的当前值。
在这里插入图片描述
将zero_add_cin信号强制到"1",将one_add_cin信号强制到"0"。
在这里插入图片描述
要查看所有值,请使用创建的"prvars"别名。但是,在创建别名时,没有包括zero_add_cin和one_add_cin。由于需要查看所有值,因此需要将它们添加到命令行中。
在这里插入图片描述
进位值已更改,sum[7:4] 保持不变。 这是因为我们没有增加仿真时间以允许执行新的值。 将仿真时间执行10时间增量。
在这里插入图片描述
看一下目前的值。
在这里插入图片描述
现在,所有值都应该是正确的。 返回testbench级别并验证加法器是否正常工作。
在这里插入图片描述
这些都是正确的结果。 设置一个断点,其中c4在add8模块中添加从"0"到"1"的更改,并查看这是否有效。
在这里插入图片描述
在这里插入图片描述
您已将仿真从60到26400,而不会遇到错误。 看看这些值。
在这里插入图片描述
VCS遇到了c4从"0"到"1"的过渡,并停止了仿真。 但是,除了尚未遇到这些事件之外,可能还有其他事件。 在此特定情况下,4位MSB(在 addertb.u1 中的sum_1)添加发生在 u1.c4 信号转换后。因此,sum_test的当前值尚未更新。 你所看到的是以前sum_test的值。

您需要将仿真至少执行到下一个时间步骤,以查看当前时间步骤中所有事件的全部效果。
在这里插入图片描述
在这里插入图片描述
现在看起来对了。移除断点并继续仿真。
在这里插入图片描述
我们可以通过删除断点序号来删除断点。

重新仿真。
在这里插入图片描述
您已成功检测到错误,并在仿真中解决了错误。

如果厌倦了一遍又一遍地重新键入相同的命令,使用日志文件作为生成脚本文件的参考。这将简化调试命令条目。

我们已经生成了一个脚本文件。 在此脚本文件中,定义常用别名并执行仿真的进位固定命令。

(注意:记住这不是一个真正的解决方法! 它仅用于允许仿真在不离开UCLI环境的情况下继续。)

重新打开仿真。
在这里插入图片描述
您可以看到,zero_add_cin和one_add_cin已设置为仿真值。 试试别名tb。
在这里插入图片描述
这个别名有效! 让我们仿真一下。
在这里插入图片描述
祝贺! 退出UCLI并查看仿真日志文件。 日志文件应显示在仿真会话中所做的一切。
在这里插入图片描述
可以使用此文件的内容作为生成脚本文件的参考。

Part C: 获得帮助

Task 1: 提交文件寻求帮助

如果您需要从VCS支持团队获得帮助,则有两个开关可以使与支持人员的工作更加顺畅。 它们是-ID-Xman=4
在这里插入图片描述
您应该看到正在使用的VCS版本和工作站操作系统信息的摘要。 这将有助于支持人员快速关注与特定 VCS 版本和工作站操作系统相关的问题。

当电话支持不能解决您的问题时,您的下一个行动计划应该是提交一个测试案例供Synopsys工程师使用,为此目的使用 –Xman=4开关。
在这里插入图片描述
应该看到已生成文件tokens.v,打开看看包含所有测试案例。

/*
                    instances: 0
                        nodes: 6 (0)
                  node widths: 44 (0)
                      process: 1 (0)
                        ports: 1 (0)
                 portconnects: 5 (0)
*/

`portcoerce
`inline
// No timescale specified
module addertb;

	reg	[7:0]		a_test;
	reg	[7:0]		b_test;
	wire	[7:0]		sum_test;
	reg			cin_test;
	wire			cout_test;
	reg	[17:0]		test;

	add8 u1(a_test, b_test, cin_test, sum_test, cout_test);

	initial begin
	  for (test = 0; (test <= 18'h1ffff); test = (test + 1)) begin
	    cin_test = test[16];
	    a_test = test[15:8];
	    b_test = test[7:0];
	    #(50) ;
	    if ({cout_test, sum_test} !== ((a_test + b_test) + cin_test)) begin
	      $display("***ERROR at time = %0d ***", $time);
	      $display("a = %h, b = %h, sum = %h;  cin = %b, cout = %b", a_test,
		      b_test, sum_test, cin_test, cout_test);
	      $stop;
	    end
	    #(50) ;
	  end
	  $display("*** Testbench successfully completed! ***");
	  $finish;
	end
endmodule

/*
                    instances: 0
                        nodes: 12 (0)
                  node widths: 39 (0)
                   contassign:  4 (0)
                        ports: 5 (0)
                        ports: 3 (0)
                 portconnects: 15 (0)
*/

// No timescale specified
module add8(a, b, cin, sum, cout);

	input	[7:0]		a;
	input	[7:0]		b;
	input			cin;
	output			cout;
	output	[7:0]		sum;

	wire			c4;
	wire			c8_0;
	wire			c8_1;
	wire			zero_add_cin;
	wire			one_add_cin;
	wire	[7:4]		sum_0;
	wire	[7:4]		sum_1;

	assign sum[7:4] = (c4 ? sum_0 : sum_1);
	assign cout = (c4 ? c8_0 : c8_1);
	assign zero_add_cin = 0;
	assign one_add_cin = 1;

	add4 u1(a[3:0], b[3:0], cin, sum[3:0], c4);
	add4 zero_add(a[7:4], b[7:4], zero_add_cin, sum_0, c8_0);
	add4 one_add(a[7:4], b[7:4], one_add_cin, sum_1, c8_1);
endmodule

/*
                    instances: 0
                        nodes: 6 (0)
                  node widths: 17 (0)
                        ports: 5 (0)
                        ports: 4 (0)
                 portconnects: 20 (0)
*/

// No timescale specified
module add4(a, b, cin, sum, cout);

	input	[3:0]		a;
	input	[3:0]		b;
	input			cin;
	output			cout;
	output	[3:0]		sum;

	wire	[3:1]		c;

	fa u1(a[0], b[0], cin, sum[0], c[1]);
	fa u2(a[1], b[1], c[1], sum[1], c[2]);
	fa u3(a[2], b[2], c[2], sum[2], c[3]);
	fa u4(a[3], b[3], c[3], sum[3], cout);
endmodule

/*
                    instances: 0
                        nodes: 5 (0)
                  node widths: 5 (0)
                   contassign:  1 (0)
                        ports: 5 (0)
*/

// No timescale specified
module fa(a, b, cin, sum, cout);

	input			a;
	input			b;
	input			cin;
	output			sum;
	output			cout;

	assign {cout, sum} = ((a + b) + cin);
endmodule

/*     Design Summary
                      modules: 4
                         udps: 0
                mod flatinsts: 0
                udp flatinsts: 0
                        nodes: 29 (0)
                  node widths: 105 (0)
                      process: 1 (0)
                        gates: 0 (0)
                  contassigns: 5 (0)
                        ports: 15 (0)
                     modinsts: 8 (0)
                     udpinsts: 0 (0)
                 portconnects: 40 (0)
*/

// END: VCS tokens
  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值