《SystemVerilog验证测试平台编写指南》学习笔记——连接设计和测试平台(三)

一、SystemVerilog断言

SVA可以在设计中创建时序断言,在整个仿真过程中都是有效的,仿真器会跟踪哪些断言被激活,来在此基础上收集功能覆盖率的数据。

1、立即断言

测试平台的过程代码可以检查待测设计的信号值和测试平台的信号值,并且在存在问题的时候采取相应的行动。

使用if语句检查一个信号

bus.cb.request <= 1;
repeat(2) @bus.cb;
if(bus.cb.grant != 2'b01)
	$display("ERROR, grant != 1");
	...

简单的立即断言

bus.cb.request <= 1;
repeat(2) @bus.cb;
al: assert(bus.cb.grant == 2'b01);		//成功,继续执行;不符合预期,则仿真器给出错误信息
	...

2、定制断言行为

一个立即断言有可选的then和else分句。可以修改默认的错误信息。SystemVerilog有四个输出消息的函数:$info, $warning, $error, $fatal

在立即断言中创建一个定制的错误信息

al: assert(bus.cb.grant == 2'b01);
else $error("XXXXXX");

使用then子句记录断言何时成功完成

al: assert(bus.cb.grant == 2'b01)
	grant_received++;
else 
	$error("XXXXXX");

3、并发断言

可以认为它是连续运行的模块,为整个仿真过程检查信号的值,你需要在断言内指定一个采样时钟。

检查X/Z的并发断言

interface arb_if(input bit clk);
	logic[1:0] grant, request;
	logic rst;

	property request_2state;
		@(postedge clk) disable iff(rst);		//request信号除了在复位期间,其他任何时候都不能是x或者z
		$isunknown(request) == 0;		//确保没有z或者x值存在
	endproperty
	assert_request_2state: assert property(request_2state);
endinterface

4、断言的进一步探讨

在接口中也可以使用断言,这样接口不仅可以传送信号值也可以检查协议的正确性,有一本《SystemVerilog Assertion》的书籍可以一看。

二、四端口的ATM路由器

加大难度,真正的设计具有更多的输入和输出,如四端口的ATM(Asynchronous Transfer Mode,异步传输模式)路由器。
在这里插入图片描述

1、使用端口的ATM路由器

未使用接口类型的ATM路由器模型首部
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2、使用端口的ATM顶层网单

未使用接口的顶层网单

module top;
	bit clk;
	always # 5 clk= ! clk;
	wire Rx_clk_0,Rx_clk_1,Rx_clk_2,Rx_clk_3,
		 Rx_soc_0,Rx_soc_1,Rx_soc_2,Rx_soc_3,
		 Rx_en_0,Rx_en_1,Rx_en_2,Rx_en_3,
		 Rx_clav_0,Rx_clav_1,Rx_clav_2,Rx_clav_3,
		 Tx_clk_o,Tx_clk_1,Tx_clk_2,Tx_clk_3,
		 Tx_soc_0,Tx_soc_1,Tx_soc_2,Tx_soc_3,
		 Tx_en_0,Tx_en_1,Tx_en_2,Tx_en_3,
		 Tx_clav_0,Tx_clav_1,Tx_clav_2,Tx_clav_3,rst;
	
	wire[7:0] Rx_data_0,Rx_data_1,Rx_data_2,Rx_data_3, 
			  Tx_data_o,Tx_data_1, Tx_data_2,Tx_data_3;

	atm_router al(Rx_clk_0,Rx_clk_1,Rx_clk_2,Rx_clk_3,
				  Rx_data_0,Rx_data_1,Rx_data_2,Rx_data_3,
				  Rx_soc_o,Rx_soc_1,Rx_soc_2,Rx_soc_3,
				  Rx_en_0,Rx_en_1,Rx_.en_2,Rx_en_3,
				  Rx_clav_0,Rx_clav_1,Rx_clav_2,Rx_clav_3,
				  Tx_olk_0,Tx_clk_1,Tx_clk_2,Tx__clk_3,
				  Tx_data_0,Tx_data_1, Tx_data_2,Tx_data_3,
				  Tx_soc_0, Tx_soc_1,Tx_soc_2,Tx_soc_3,
				  Tx_en_0,Tx_en_1,Tx_en_2,Tx_en_3,
				  Tx_clav_0,Tx_clav_1,Tx_clav_2,Tx_clav_3,
				  rst,clk);

test t1(Rx_clk_0,Rx_clk_1,Rx_clk_2,Rx_clx_3,
		Rx_data_o,Rx_data_1,Rx_data_2,Rx_data_3,
		Rx_soc_0,Rx_soc_1,Rx_soc_2,Rx_soc_3,
		Rx_en_0,Rx_en_1,Rx_en_2,Rx_en_3,
		Rx_clav_0,Rx_clav_1,Rx_clav_2,Rx_clav_3,
		Tx_clk_0,Tx_clk_1,Tx_clk_2,Tx_clk_3,
		Tx_data_0, Tx_data_1,Tx_data_2,Tx_data_3,
		Tx_soc_0,Tx_soc_1, Tx_soc_2, Tx_soc_3,
		Tx_en_0,Tx_en_1,Tx_en_2,Tx_en_3,
		Tx_clav_0,Tx_clav_1,Tx_clav_2,Tx_clav_3,
		rst,clk);
endmodule




使用端口的测试平台

module test (
		// 4 x Level 1 Utopia ATM layer Rx Interfaces
		Rx_clk_0,Rx_clk__1,Rx_clk_2,Rx_clk_3,
		Rx_data_0,Rx_data_1,Rx_data_2,Rx_data_3,
		Rx_soc_0,Rx_soc_1,Rx_soc_2,Rx_soc_3,
		Rx_en_0,Rx_en_1,Rx_en_2,Rx_en_3,
		Rx_clav_0,Rx_clav_1,Rx_clav_2,Rx_clav_3,
		//4 x Level 1 Utopia ATM layer Tx Interfaces
		Tx_clk_0,Tx__clk_1,Tx_clk_2,Tx_clk_3,
		Tx_data_0,Tx_data_1,Tx_data_2,Tx_data_3,
		Tx_soc_0,Tx_soc_1,Tx_soc_2,Tx_soc_3,
		Tx_en_0,Tx_en_1,Tx_en_2,Tx_en_3,
		Tx_clav_0,Tx_clav_1,Tx_clav_2,Tx_clav_3,
		//其他控制信号
		rst,clk);

		//4 x Level 1 utopia Rx Interfaces
		input Rox_clk_0,Rx_clk_l,Rx_clk_2,Rx_clk_3;
		output [7:0] Rx_data_0,Rx_data_1,Rx_data_2,Rx_data_3;
		reg [7:0] Rx_data_0,Rx_data_1,Rx_data_2,Rx_data_3;
		output Rx_soc_0,Rx_soc_1,Rx_soc_2,Rx_soc_3;
		reg Rx_soc_0,Rx_soc_1,Rx_soc_2,Rx_soc_3;
		input Rx_en_0,Rx_en_1,Rx_en_2,Rx_en_3;
		output Rx_clav_0,Rx_clav_1,Rx_clav_2,Rx_clav_3;
		reg Rx_clav_0,Rx_clav_1,Rx_clav_2,Rx_clav_3;
		// 4 x Level 1 Utopia Tx Interfaces
		input Tx_clk_0,Tx_clk_1, Tx_clk_2,Tx_clk_3;
		input [7:0] Tx_data_0,Tx_data_1,Tx_data_2,Tx_data_3;
		input Tx_soc_0,Tx_soc_1,Tx_soc_2,Tx_soc_3;
		input Tx_en_0,Tx_en_1,Tx_en_2,Tx_en_3;
		output Tx_clav_0,Tx_clav_1, Tx_clav_2,Tx_clav_3;
		reg Tx_clav_0,Tx_clav_1,Tx_clav_2,Tx_clav_3;
		//其他控制信号
		output rst;
		reg rst;
		input clk;

		initial begin
			//复位设备
			rst <= 1;
			Rx_data_0 <= 0;
			...
		end
endmodule

		

没有使用接口的多输入多输出的设备,由此可见,代码及其繁琐冗余!!!

3、使用接口简化连接

测试平台——使用接口的路由器框图,其中信号被分组装进接口
在这里插入图片描述

4、ATM接口

使用了modport和时钟块的Rx接口

interface Rx_if(input logic clk);
	logic[7:0] data;
	logic soc,en,clav,rclk;

	clocking cb @(postedge clk);
		output data,soc,clav;		//方向是相对测试平台的
		input en;
	endclocking : cb

	modport DUT(output en,rclk,
				input data,soc,clav);
	modport TB(clocking cb);
endinterface : Rx_if

使用modport和时钟块的Tx接口

interface Tx_if(input logic clk);
	logic[7:0] data;
	logic soc,en,clav,tclk;

	clocking cb @(postedge clk);
		input data,soc,en;		//方向是相对测试平台的
		output clav;
	endclocking : cb

	modport DUT(output data,soc,en,tclk,
				input clk,clav);
	modport TB(clocking cb);
endinterface : tx_if

5、使用接口的ATM路由器模型

接口中使用modport的ATM路由器模型

module atm_router(Rx_if.DUT Rx0,Rx1,Rx2,Rx3,
				  Tx_if.DUT Tx0,Tx1,Tx2,Tx3,
				  input logic clk,rst);
	...
endmodule

6、使用接口的ATM顶层网单

使用接口的顶层网单

module top;
	bit clk,rst;
	always # 5 clk = !clk;

	Rx_if Rx0(clk),Rx1(clk),Rx2(clk),Rx3(clk);
	Tx_if Tx0(clk),Tx1(clk),Tx2(clk),Tx3(clk);

	atm_router al(Rx0,Rx1,Rx2,Rx3,Tx0,Tx1,Tx2,Tx3,clk,rst);

	test t1(Rx0,Rx1,Rx2,Rx3,Tx0,Tx1,Tx2,Tx3,clk,rst);
endmodule : top

7、使用接口的ATM测试平台

接口中使用时钟块的测试平台

program test(Rx_if.TB Rx0,Rx1,Rx2,Rx3,
			 Tx_if.TB Tx0,Tx1,Tx2,Tx3,
			 input logic clk,
			 output logic rst);
	bit[7:0] bytes[ATM_CELL_SIZE];

	initial begin
		rst <= 1;
		Rx0.cb.data <= 0;
		...
		received_cell0();
		...
	end
	
	task receive_cell0();
		@(Tx0.cb);
		Tx0.cb.clav <= 1;		//准备接收
		wait(Tx0.cb.soc == 1);		//等待信元的开始
		for(int i = 0; i < ATM_CELL_SIZE; i++) begin
			wait(Tx0.cb.en == 0);		//等待使能信号
			@(TX0.cb);
			bytes[i] = Tx0.cb.data;
			@(TX0.cb);
			Tx0.cb.clav <= 0;		//释放流控信号
		end
	endtask : receive_cell0
endprogram : test

三、ref端口的方向

ref端口其实是对变量(不能是net)的引用,它的值时该变量最后一次赋的值。如果讲一个变量连接到多个ref端口,就可能产生竞争,因为多个模块的端口都可能更新同一个变量。

四、仿真的结束

仿真在程序块中的最后一个initial块结束时结束,其实是隐形地调用¥exit以标志程序的结束。所有的程序块都退出了,$finish函数的隐形调用也就结束了。
仿真并没有完全结束。模块或者程序块可以定义一个或者多个finial块来执行仿真器退出前的代码,用来放置清理任务的代码。在finial块中不能调度事件,或含有任何时延信息。

finial块

program test;
	int errors,warning;

	initial begin
		...
	end
	
	finial
		$display("test done with %0d errors and %0d warnings", errors,warnings);
endprogram
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值