我是靠谱客的博主 粗暴天空,这篇文章主要介绍APB-UART(下)sequencetest caseassertion,现在分享给大家,希望可以做个参考。

sequence

apb_sequence

  • config_apbuart
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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模式
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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模式
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
    错误的停止位.
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
    错误的奇偶校验位.
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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的上升边缘来确定。
复制代码
1
2
3
4
5
6
7
8
9
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拉高的下一个周期拉高。
复制代码
1
2
3
4
5
6
7
8
9
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不应该是未知的。
复制代码
1
2
3
4
5
6
7
8
9
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的值不应该是未知的。
复制代码
1
2
3
4
5
6
7
8
9
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的值不应更改。
复制代码
1
2
3
4
5
6
7
8
9
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在整个写周期中应该保持不变.
复制代码
1
2
3
4
5
6
7
8
9
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时不应该是未知的.
复制代码
1
2
3
4
5
6
7
8
9
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之前断言.
复制代码
1
2
3
4
5
6
7
8
9
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 :: ------"))

最后

以上就是粗暴天空最近收集整理的关于APB-UART(下)sequencetest caseassertion的全部内容,更多相关APB-UART(下)sequencetest内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(118)

评论列表共有 0 条评论

立即
投稿
返回
顶部