APB-UART(下)

sequence

apb_sequence

  • config_apbuart
class config_apbuart extends uvm_sequence #(apb_transaction);
	`uvm_object_utils (config_apbuart)

	apb_transaction apbuart_sq;
	uart_config 	cfg;

    function new (string name = "config_apbuart");
        super.new (name);
    endfunction

    task body();
		apbuart_sq 	= apb_transaction::type_id::create("apbuart_sq");
		cfg 		= uart_config::type_id::create("cfg");
	
		// Write data for Configuring the registers	   
    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b1;
                          	 apbuart_sq.PADDR  == cfg.baud_config_addr;
							})
		`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b0;
                          	 apbuart_sq.PADDR  == cfg.baud_config_addr;
                          	})
        `uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b1;
                          	 apbuart_sq.PADDR  == cfg.frame_config_addr;
							})
    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b0;
                          	 apbuart_sq.PADDR  == cfg.frame_config_addr;
                          	})								
    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b1;
                          	 apbuart_sq.PADDR  == cfg.parity_config_addr;
							})
    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b0;
                          	 apbuart_sq.PADDR  == cfg.parity_config_addr;
                          	})								  
    
    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b1;
                          	 apbuart_sq.PADDR  == cfg.stop_bits_config_addr;
                          	})      
    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b0;
                          	 apbuart_sq.PADDR  == cfg.stop_bits_config_addr;
                          	})
	endtask

endclass
  • transmit_single_beat
    transmit模式
class transmit_single_beat extends uvm_sequence #(apb_transaction);
	
	`uvm_object_utils (transmit_single_beat)
	apb_transaction apbuart_sq; 
	uart_config 	cfg;

    function new (string name = "transmit_single_beat");
        super.new (name);
    endfunction

	task body();
    	apbuart_sq 	= apb_transaction::type_id::create("apbuart_sq");
		cfg			= uart_config::type_id::create("cfg");
	
		`uvm_do_with(apbuart_sq,{
		  					 apbuart_sq.PWRITE == 1'b1;
                             apbuart_sq.PADDR  == cfg.trans_data_addr;
                            }) 
	endtask  
endclass
  • rec_reg_test
    receive模式
class rec_reg_test extends uvm_sequence#(apb_transaction);
	`uvm_object_utils(rec_reg_test)
  	apb_transaction	apbuart_sq;
	uart_config 	cfg;

  	function new(string name = "rec_reg_test");
  		super.new(name);
  	endfunction: new

	task rec_reg_test::body();
		apbuart_sq 	= apb_transaction::type_id::create("apbuart_sq");
		cfg 		= uart_config::type_id::create("cfg");

    	`uvm_do_with(apbuart_sq,{
	  						 apbuart_sq.PWRITE == 1'b0;
                          	 apbuart_sq.PADDR  == cfg.receive_data_addr;
                          	}) 
	endtask
endclass: rec_reg_test

uart_sequence

  • recdrv_test_uart
class recdrv_test_uart extends uvm_sequence#(uart_transaction);
	`uvm_object_utils(recdrv_test_uart)
	uart_transaction uart_sq;

	function new(string name = "recdrv_test_uart");
		super.new(name);
  	endfunction: new

  	task body();
		uart_sq = uart_transaction::type_id::create("uart_sq");
		`uvm_do_with(uart_sq,{
							uart_sq.sb_corr 	== 1'b0;
						 }) 
	endtask
endclass: recdrv_test_uart
  • fe_test_uart
    错误的停止位.
class fe_test_uart extends uvm_sequence#(uart_transaction);
	`uvm_object_utils(fe_test_uart)
	uart_transaction uart_sq;

	function new(string name = "fe_test_uart");
		super.new(name);
  	endfunction: new
	  
	task body();
    	uart_sq = uart_transaction::type_id::create("uart_sq");
		`uvm_do_with(uart_sq,{
							uart_sq.bad_parity  == 1'b0;
							uart_sq.sb_corr 	== 1'b1;  
						 }) 
	endtask
endclass: fe_test_uart
  • pe_test_uart
    错误的奇偶校验位.
class pe_test_uart extends uvm_sequence#(uart_transaction);
	`uvm_object_utils(pe_test_uart)
  	uart_transaction uart_sq;

	function new(string name = "pe_test_uart");
    	super.new(name);
  	endfunction: new
	
	task body();
    	uart_sq = uart_transaction::type_id::create("uart_sq");
		`uvm_do_with(uart_sq,{
							uart_sq.bad_parity  == 1'b1;
							uart_sq.sb_corr 	== 1'b0;  
						 }) 
	endtask
endclass: pe_test_uart
  • err_free_test_uart
class err_free_test_uart extends uvm_sequence#(uart_transaction);
	`uvm_object_utils(err_free_test_uart)
  	uart_transaction uart_sq;
  
	function new(string name = "err_free_test_uart");
    	super.new(name);
 	endfunction: new
  
	task body();
  		uart_sq = uart_transaction::type_id::create("uart_sq");
		`uvm_do_with(uart_sq,{
							uart_sq.bad_parity  == 1'b0;
							uart_sq.sb_corr 	== 1'b0;
							//uart_sq.payload 	== 32'h11223344;   
						 }) 
	endtask
endclass: err_free_test_uart

test case

根据对spec的测试点分解以及sequence的开发,指定以下测试计划.

  • 通过在配置寄存器中存储特定的值来设置config。配置元素如下:波特率,帧大小,奇偶校验,停止位,可以通过使用APB接口提供的PADDR变量来访问它们的特定配置地址。
  • 首先通过运行config sequence将配置设置写入DUT,然后将一些数据写入PWDATA端口,并通过TX-pin串行(逐位)读取数据。输出应该是相同的。加载在PWDATA上的数据应该在TX-pin上串行接收。
  • 在RX引脚上逐位加载数据,然后在preready时从PRDATA端口读取数据。同样,我们可以先运行随机配置设置,然后根据相应的配置设置运行此测试。
  • 发送一个帧,其中包含损坏的停止位。DUT应响应输出PSLVERR位拉高。设置DUT为random config,然后运行此测试。
  • 发送包含损坏的奇偶校验位的帧。DUT应响应PSLVERR为高。设置DUT为random config,然后运行此测试。
  • 设置random config,随机奇偶校验错误和帧错误。使DUT处于receive模式,包括在RX引脚上逐位发送数据,然后在PREADY时从PRDATA端口读取数据。
  • 测试过程与上述随机序列相同。唯一会发生的变化是使用时钟和复位驱动器序列,时钟会有不同的周期,并会在每次transaction后进行重置。

assertion

以下是对于APB协议的断言。

  • SETUP_state
    在setup_state中,PSELx应该是HIGH, PENABLE应该是LOW, setup_state可以通过检测PSELx的上升边缘来确定。
property SETUP_state;
	@(posedge PCLK) disable iff (!PRESETn)
		$rose(PSELx) |->  !(PENABLE); 
endproperty
assert property(SETUP_state)
	//    $display("-------------------Check#1: SETUP_state PASS------------------");
else
	 `uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#1: SETUP_state FAILED :: ------"))
  • ACCESS_state
    ACCESS_state发生在SETUP_state的一个循环之后,所以PENABLE应该在PSELx拉高的下一个周期拉高。
property ACCESS_state;
	@(posedge PCLK) disable iff (!PRESETn)
		$rose(PSELx) |->  ##1($rose(PENABLE));
endproperty
assert property(ACCESS_state)
	//    $display("-------------------Check#2: ACCESS_state PASS------------------
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#2: ACCESS_state FAILED :: ------"))
  • valid_PWRITE_PADDR_in_SETUP
    在SETUP_state中,PWRITE和PADDR不应该是未知的。
property valid_PWRITE_PADDR_in_SETUP;
	@(posedge PCLK) disable iff (!PRESETn)
		(PSELx && !PENABLE) |-> !($isunknown(PWRITE)) && !($isunknown(PADDR));
endproperty
assert property(valid_PWRITE_PADDR_in_SETUP)
	 //    $display("-------------------Check#3: valid_PWRITE_PADDR_in_SETUP PASS------------------");
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#3: valid_PWRITE_PADDR_in_SETUP FAILED :: ------"))
  • valid_PWDATA_in_write_operation
    在SETUP_state中,写操作期间PWDATA的值不应该是未知的。
property valid_PWDATA_in_write_operation;
	@(posedge PCLK) disable iff (!PRESETn)
		(PSELx && !PENABLE && PWRITE) |-> !($isunknown(PWDATA));
endproperty
assert property(valid_PWDATA_in_write_operation)
	 //    $display("-------------------Check#4: valid_PWDATA_in_write_operation PASS------------------");
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#4: valid_PWDATA_in_write_operation FAILED :: ------"))
  • stable_PWRITE_PADDR_in_ACCESS
    在ACCESS_state中,PWRITE和PADDR的值不应更改。
property stable_PWRITE_PADDR_in_ACCESS;
	@(posedge PCLK) disable iff (!PRESETn)
		(PSELx && PENABLE) |-> $stable({PWRITE, PADDR});
endproperty
assert property(stable_PWRITE_PADDR_in_ACCESS)
	 //    $display("-------------------Check#5: stable_PWRITE_PADDR_in_ACCESS PASS------------------");
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#5: stable_PWRITE_PADDR_in_ACCESS FAILED :: ------"))
  • stable_PWDATA_during_write_operation
    PWDATA在整个写周期中应该保持不变.
property stable_PWDATA_during_write_operation;
	@(posedge PCLK) disable iff (!PRESETn)
		(PSELx && PENABLE && PWRITE) |-> $stable(PWDATA);
endproperty
assert property(stable_PWDATA_during_write_operation)
	//    $display("-------------------Check#6: stable_PWDATA_during_write_operation PASS------------------");
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#6: stable_PWDATA_during_write_operation FAILED :: ------"))
  • valid_PRDATA_in_read_operation
    在读操作中,PRDATA的值在断言PREADY时不应该是未知的.
property valid_PRDATA_in_read_operation;
	@(posedge PCLK) disable iff (!PRESETn)
		(PREADY and APB_READ_CYCLE) |-> !($isunknown(PRDATA));
endproperty
assert property(valid_PRDATA_in_read_operation)
	//    $display("-------------------Check#7: valid_PRDATA_in_read_operation PASS------------------");
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#7: valid_PRDATA_in_read_operation FAILED :: ------"))
  • PSELx_and_PENABLE_multiple_operation
    对于多个读/写操作,PSELx不一定要去断言,但在所有事务完成之前,它仍然保持HIGH。所以我们必须检查每次PENABLE拉高时,PSELx应该在一个cycle之前断言.
property PSELx_and_PENABLE_multiple_operation;
	@(posedge PCLK) disable iff (!PRESETn)
		PENABLE |-> $past(PSELx);
endproperty
assert property(PSELx_and_PENABLE_multiple_operation)
	//    $display("-------------------Check#8: PSELx_and_PENABLE_multiple_operation PASS------------------");
else
	`uvm_error("ASSERTION_FAILED",$sformatf("------ :: Check#8: PSELx_and_PENABLE_multiple_operation FAILED :: ------"))
  • 4
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值