UVM环境介绍
HEAD commitID: 1f968ef
1. core-v-verif/lib/uvm_agents/uvma_axi/src/uvma_axi_ar_assert.sv
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi
// *************************** READ ADDRESS CHANNEL ************************** //
module uvma_axi_ar_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
import uvm_pkg::*;
// *************************** Check if control information Signals are not equal to X or Z when ARVALID is HIGH (Section A3.2.2) ************************** //
property AXI4_ARID_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_id));
endproperty
property AXI4_ARADDR_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_addr));
endproperty
property AXI4_ARLEN_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_len));
endproperty
property AXI4_ARSIZE_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_size));
endproperty
property AXI4_ARBURST_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_burst));
endproperty
property AXI4_ARLOCK_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_lock));
endproperty
property AXI4_ARCACHE_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_cache));
endproperty
property AXI4_ARPROT_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_prot));
endproperty
property AXI4_ARUSER_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_user));
endproperty
property AXI4_ARQOS_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_qos));
endproperty
property AXI4_ARREGION_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_region));
endproperty
// A value of X on ARVALID is not permitted when not in reset (Section A3.1.2)
property AXI4_ARVALID_X;
@(posedge clk) disable iff (!rst_n) (!$isunknown(axi_assert.psv_axi_cb.ar_valid));
endproperty
// A value of X on ARREADY is not permitted when not in reset (Section A3.1.2)
property AXI4_ARREADY_X;
@(posedge clk) disable iff (!rst_n) (!$isunknown(axi_assert.psv_axi_cb.ar_ready));
endproperty
// *************************** Check if control information Signals are stable when ARVALID is HIGH (Section A3.2.1) ************************** //
property AXI4_ARID_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_id)));
endproperty
property AXI4_ARADDR_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_addr)));
endproperty
property AXI4_ARLEN_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_len)));
endproperty
property AXI4_ARSIZE_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_size)));
endproperty
property AXI4_ARBURST_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_burst)));
endproperty
property AXI4_ARLOCK_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_lock)));
endproperty
property AXI4_ARCACHE_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_cache)));
endproperty
property AXI4_ARPROT_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_prot)));
endproperty
property AXI4_ARUSER_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_user)));
endproperty
property AXI4_ARQOS_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_qos)));
endproperty
property AXI4_ARREGION_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!axi_assert.psv_axi_cb.ar_ready |=> ($stable(axi_assert.psv_axi_cb.ar_region)));
endproperty
// Check if, Once asserted, ar_valid must remain asserted until ar_ready is HIGH (Section A3.2.1)
property AXI4_AR_VALID_READY ;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (axi_assert.psv_axi_cb.ar_valid throughout (axi_assert.psv_axi_cb.ar_ready [->1]));
endproperty
// check if a read transaction with burst type WRAP has an aligned address (Section A3.4.1)
property AXI_ARADDR_WRAP_ALIGN;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.ar_valid && axi_assert.psv_axi_cb.ar_burst == 2'b10) |-> !((axi_assert.psv_axi_cb.ar_addr) % (2**axi_assert.psv_axi_cb.ar_size));
endproperty
// check if The size of a read transfer does not exceed the width of the data interface (Section A3.4.1)
property AXI_ERRM_ARSIZE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (8*(2**axi_assert.psv_axi_cb.ar_size) <= `UVMA_AXI_DATA_MAX_WIDTH);
endproperty
// check if burst crosses 4KB boundaries (Section A3.4.1)
property AXI4_ERRM_ARADDR_BOUNDARY;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (((axi_assert.psv_axi_cb.ar_addr + (axi_assert.psv_axi_cb.ar_len + 1)*(2**axi_assert.psv_axi_cb.ar_size)) % 4096) > (axi_assert.psv_axi_cb.ar_addr % 4096)) || !((axi_assert.psv_axi_cb.ar_addr+(axi_assert.psv_axi_cb.ar_len + 1) * (2**axi_assert.psv_axi_cb.ar_size)) % 4096) ;
endproperty
// Check if the burst length equal to 2, 4, 8, or 16, for wrapping bursts (Section A3.4.1)
property AXI_ARLEN_WRAPP_BURST;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.ar_valid && axi_assert.psv_axi_cb.ar_burst == 2'b10) |-> (axi_assert.psv_axi_cb.ar_len == 1) || (axi_assert.psv_axi_cb.ar_len == 3) || (axi_assert.psv_axi_cb.ar_len == 7) || (axi_assert.psv_axi_cb.ar_len == 15);
endproperty
// Check if ar_burst can’t be 2’b11 (Table A3-3)
property AXI4_AR_BURST_CANT_2b11;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (axi_assert.psv_axi_cb.ar_burst != 2'b11);
endproperty
// Check if ARVALID is LOW for the first cycle after ARESETn goes HIGH (Figure A3-1)
property AXI4_ARVALID_RESET;
@(posedge clk) $rose(rst_n) |=> !(axi_assert.psv_axi_cb.ar_valid);
endproperty
// Check if the length of an exclusive access transaction don't pass 16 beats (Section A7.2.4)
property AXI4_ARLEN_LOCK;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_lock |-> (signed' (axi_assert.psv_axi_cb.ar_len)) <= 16;
endproperty
// Check if ARCACHE[3:2] are LOW, When ARVALID is HIGH and ARCACHE[1] is LOW (Table A4-5)
property AXI4_ARCACHE_LOW;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.ar_valid) && !(axi_assert.psv_axi_cb.ar_cache[1]) |-> !(axi_assert.psv_axi_cb.ar_cache[3:2]);
endproperty
// Check if a transactions of burst type FIXED don't have a length greater than 16 beats (Section A3.4.1)
property AXI4_ARLEN_FIXED;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.ar_burst == 2'b00) |-> (axi_assert.psv_axi_cb.ar_len <= 15);
endproperty
/********************************************** Assert Property ******************************************************/
ar_valid_ready : assert property (AXI4_AR_VALID_READY)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AR_VALID_READY");
arlen_wrapp_burst : assert property (AXI_ARLEN_WRAPP_BURST)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI_ARLEN_WRAPP_BURST");
araddr_wrap_align : assert property (AXI_ARADDR_WRAP_ALIGN)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI_ARADDR_WRAP_ALIGN");
assert_arsize : assert property (AXI_ERRM_ARSIZE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI_ERRM_ARSIZE");
ar_burst_cant_2b11 : assert property (AXI4_AR_BURST_CANT_2b11)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AR_BURST_CANT_2b11");
araddr_boundary : assert property (AXI4_ERRM_ARADDR_BOUNDARY)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ERRM_ARADDR_BOUNDARY");
arvalid_reset : assert property (AXI4_ARVALID_RESET)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARVALID_RESET");
arlen_lock : assert property (AXI4_ARLEN_LOCK)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARLEN_LOCK");
arcahce_low : assert property (AXI4_ARCACHE_LOW)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARCACHE_LOW");
arlen_fixed : assert property (AXI4_ARLEN_FIXED)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARLEN_FIXED");
arid_x : assert property (AXI4_ARID_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARID_X");
araddr_x : assert property (AXI4_ARADDR_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARADDR_X");
arlen_x : assert property (AXI4_ARLEN_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARLEN_X");
arsize_x : assert property (AXI4_ARSIZE_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARSIZE_X");
arburst_x : assert property (AXI4_ARBURST_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARBURST_X");
arlock_x : assert property (AXI4_ARLOCK_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARLOCK_X");
arcache_x : assert property (AXI4_ARCACHE_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARCACHE_X");
arprot_x : assert property (AXI4_ARPROT_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARPROT_X");
arqos_x : assert property (AXI4_ARQOS_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARQOS_X");
arregion_x : assert property (AXI4_ARREGION_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARREGION_X");
arvalid_x : assert property (AXI4_ARVALID_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARVALID_X");
arready_x : assert property (AXI4_ARREADY_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARREADY_X");
arid_stable : assert property (AXI4_ARID_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARID_STABLE");
araddr_stable : assert property (AXI4_ARADDR_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARADDR_STABLE");
arlen_stable : assert property (AXI4_ARLEN_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARLEN_STABLE");
arsize_stable : assert property (AXI4_ARSIZE_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARSIZE_STABLE");
arburst_stable : assert property (AXI4_ARBURST_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARBURST_STABLE");
arlock_stable : assert property (AXI4_ARLOCK_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARLOCK_STABLE");
arcache_stable : assert property (AXI4_ARCACHE_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARCACHE_STABLE");
arprot_stable : assert property (AXI4_ARPROT_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARPROT_STABLE");
aruser_stable : assert property (AXI4_ARUSER_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARUSER_STABLE");
arqos_stable : assert property (AXI4_ARQOS_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARQOS_STABLE");
arregion_stable : assert property (AXI4_ARREGION_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ARREGION_STABLE");
/********************************************** Cover Property ******************************************************/
cov_ar_valid_ar_ready : cover property(AXI4_AR_VALID_READY);
cov_araddr_wrap_align : cover property(AXI_ARADDR_WRAP_ALIGN);
cov_arlen_wrapp_burst : cover property(AXI_ARLEN_WRAPP_BURST);
cov_arsize : cover property(AXI_ERRM_ARSIZE);
cov_arvalid_reset : cover property(AXI4_ARVALID_RESET);
cov_ar_burst_cant_2b11 : cover property(AXI4_AR_BURST_CANT_2b11);
cov_errm_ARaddr_boundary : cover property(AXI4_ERRM_ARADDR_BOUNDARY);
cov_arlen_lock : cover property(AXI4_ARLEN_LOCK);
cov_arcache_low : cover property(AXI4_ARCACHE_LOW);
cov_arlen_fixed : cover property(AXI4_ARLEN_FIXED);
cov_arid_stable : cover property(AXI4_ARID_STABLE);
cov_araddr_stable : cover property(AXI4_ARADDR_STABLE);
cov_arlen_stable : cover property(AXI4_ARLEN_STABLE);
cov_arsize_stable : cover property(AXI4_ARSIZE_STABLE);
cov_arburst_stable : cover property(AXI4_ARBURST_STABLE);
cov_arlock_stable : cover property(AXI4_ARLOCK_STABLE);
cov_arcache_stable : cover property(AXI4_ARCACHE_STABLE);
cov_arprot_stable : cover property(AXI4_ARPROT_STABLE);
cov_aruser_stable : cover property(AXI4_ARUSER_STABLE);
cov_arqos_stable : cover property(AXI4_ARQOS_STABLE);
cov_arregion_stable : cover property(AXI4_ARREGION_STABLE);
endmodule : uvma_axi_ar_assert
1. 简要介绍
uvma_axi_ar_assert.sv
文件定义了一个名为 uvma_axi_ar_assert
的模块,该模块主要用于对 AXI4 协议读地址通道(AR 通道)的各种规则进行属性检查和断言验证。通过一系列的 SystemVerilog 属性(SVA),对 AR 通道信号的合法性、稳定性等规则进行检查,当违反规则时使用 UVM 宏输出错误信息,同时还设置了一些覆盖属性用于覆盖率统计。
2. 接口介绍
module uvma_axi_ar_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
代码分析:
module uvma_axi_ar_assert
:定义一个名为uvma_axi_ar_assert
的模块。uvma_axi_intf.passive axi_assert
:一个被动接口类型的端口,uvma_axi_intf
应该是自定义的接口类型,passive
表示该接口以被动模式使用,用于接收 AXI 接口的信号。input bit clk
:输入端口,数据类型为bit
,用于提供时钟信号,属性检查在时钟的上升沿触发。input rst_n
:输入端口,数据类型为bit
,表示异步复位信号,低电平有效,用于在复位期间禁用属性检查。
3. 参数介绍
此模块中无显式的 parameter
或 localparam
定义的参数。
4. 模块实现介绍
4.1 包导入
import uvm_pkg::*;
代码分析:导入 UVM 包中的所有内容,以便后续使用 UVM 的宏(如 uvm_error
)进行错误信息输出。
4.2 属性定义
以 AXI4_ARID_X
属性为例:
property AXI4_ARID_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_id));
endproperty
代码分析:
property AXI4_ARID_X;
:定义一个名为AXI4_ARID_X
的属性。@(posedge clk)
:指定属性检查在时钟clk
的上升沿触发。disable iff (!rst_n)
:当复位信号rst_n
为低电平时,禁用该属性检查。axi_assert.psv_axi_cb.ar_valid |-> (!$isunknown(axi_assert.psv_axi_cb.ar_id))
:当ar_valid
信号为高电平时,断言ar_id
信号的值不为X
或Z
。|->
是蕴含操作符,表示前提条件成立时,后续条件也必须成立。
类似地,模块中定义了多个属性,分别检查 AR 通道不同信号的合法性、稳定性等规则。
4.3 断言语句
以 ar_valid_ready
断言为例:
ar_valid_ready : assert property (AXI4_AR_VALID_READY)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AR_VALID_READY");
代码分析:
ar_valid_ready
:断言的名称。assert property (AXI4_AR_VALID_READY)
:对AXI4_AR_VALID_READY
属性进行断言检查。else
uvm_error (" AXI4 protocol checks assertion ", “Violation of AXI4_AR_VALID_READY”);:如果属性检查失败,使用 UVM 的
uvm_error宏输出错误信息,提示违反了
AXI4_AR_VALID_READY` 属性。
4.4 覆盖属性
以 cov_ar_valid_ar_ready
覆盖属性为例:
cov_ar_valid_ar_ready : cover property(AXI4_AR_VALID_READY);
代码分析:
cov_ar_valid_ar_ready
:覆盖属性的名称。cover property(AXI4_AR_VALID_READY)
:对AXI4_AR_VALID_READY
属性进行覆盖率统计,当该属性被触发时,覆盖率工具会记录相应的覆盖点。
5. 总结
uvma_axi_ar_assert.sv
模块通过 SystemVerilog 属性验证和 UVM 宏的结合,对 AXI4 协议读地址通道的各种规则进行了全面的检查和验证。属性定义部分详细描述了各种协议规则,断言语句在规则违反时输出错误信息,帮助开发者快速定位问题。覆盖属性则用于统计验证的覆盖率,确保验证的完整性。该模块在 AXI4 协议的验证工作中起到了重要的作用,提高了验证的效率和准确性。
2. core-v-verif/lib/uvm_agents/uvma_axi/src/uvma_axi_aw_assert.sv
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi
// ***************************WRITE ADDRESS CHANNEL ************************** //
module uvma_axi_aw_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
import uvm_pkg::*;
// *************************** Check if control information Signals are not equal to X or Z when WVALID is HIGH (Section A3.2.2) ************************** //
property AXI4_AWID_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_id));
endproperty
property AXI4_AWADDR_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_addr));
endproperty
property AXI4_AWLEN_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_len));
endproperty
property AXI4_AWSIZE_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_size));
endproperty
property AXI4_AWBURST_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_burst));
endproperty
property AXI4_AWLOCK_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_lock));
endproperty
property AXI4_AWCACHE_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_cache));
endproperty
property AXI4_AWPROT_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_prot));
endproperty
property AXI4_AWUSER_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_user));
endproperty
property AXI4_AWQOS_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_qos));
endproperty
property AXI4_AWREGION_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_region));
endproperty
// A value of X on AWVALID is not permitted when not in reset (Section A3.1.2)
property AXI4_AWVALID_X;
@(posedge clk) disable iff (!rst_n) (!$isunknown(axi_assert.psv_axi_cb.aw_valid));
endproperty
// A value of X on AWREADY is not permitted when not in reset (Section A3.1.2)
property AXI4_AWREADY_X;
@(posedge clk) disable iff (!rst_n) (!$isunknown(axi_assert.psv_axi_cb.aw_ready));
endproperty
// *************************** Check if control information Signals are stable when AWVALID is HIGH (Section A3.2.1) ************************** //
property AXI4_AWID_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_id)));
endproperty
property AXI4_AWADDR_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_addr)));
endproperty
property AXI4_AWLEN_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_len)));
endproperty
property AXI4_AWSIZE_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_size)));
endproperty
property AXI4_AWBURST_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_burst)));
endproperty
property AXI4_AWLOCK_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_lock)));
endproperty
property AXI4_AWCACHE_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_cache)));
endproperty
property AXI4_AWPROT_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_prot)));
endproperty
property AXI4_AWUSER_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_user)));
endproperty
property AXI4_AWQOS_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_qos)));
endproperty
property AXI4_AWREGION_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!axi_assert.psv_axi_cb.aw_ready |=> ($stable(axi_assert.psv_axi_cb.aw_region)));
endproperty
// Check if, Once asserted, aw_valid must remain asserted until aw_ready is HIGH (Section A3.2.1)
property AXI4_AW_VALID_READY;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> ( axi_assert.psv_axi_cb.aw_valid throughout (axi_assert.psv_axi_cb.aw_ready [->1]));
endproperty
// check if a write transaction with burst type WRAP has an aligned address (Section A3.4.1)
property AXI_AWADDR_WRAP_ALIGN;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.aw_valid && axi_assert.psv_axi_cb.aw_burst == 2'b10) |-> !((axi_assert.psv_axi_cb.aw_addr) % (2**axi_assert.psv_axi_cb.aw_size));
endproperty
// check if The size of a write transfer does not exceed the width of the data interface (Section A3.4.1)
property AXI_ERRM_AWSIZE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (8 * (2**axi_assert.psv_axi_cb.aw_size) <= `UVMA_AXI_DATA_MAX_WIDTH);
endproperty
// check if burst crosses 4KB boundaries (Section A3.4.1)
property AXI4_ERRM_AWADDR_BOUNDARY;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (((axi_assert.psv_axi_cb.aw_addr + (axi_assert.psv_axi_cb.aw_len + 1) * (2**axi_assert.psv_axi_cb.aw_size)) % 4096) > (axi_assert.psv_axi_cb.aw_addr % 4096)) || !((axi_assert.psv_axi_cb.aw_addr + (axi_assert.psv_axi_cb.aw_len + 1) * (2**axi_assert.psv_axi_cb.aw_size)) % 4096);
endproperty
// Check if the burst length equal to 2, 4, 8, or 16, for wrapping bursts (Section A3.4.1)
property AXI_AWLEN_WRAPP_BURST;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.aw_valid && axi_assert.psv_axi_cb.aw_burst == 2'b10) |-> (axi_assert.psv_axi_cb.aw_len == 1) || (axi_assert.psv_axi_cb.aw_len == 3) || (axi_assert.psv_axi_cb.aw_len == 7) || (axi_assert.psv_axi_cb.aw_len == 15);
endproperty
// Check if aw_burst can’t be 2’b11 (Table A3-3)
property AXI4_AW_BURST_CANT_2b11;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (axi_assert.psv_axi_cb.aw_burst != 2'b11);
endproperty
// Check if AWVALID is LOW for the first cycle after ARESETn goes HIGH (Figure A3-1)
property AXI4_AWVALID_RESET;
@(posedge clk) $rose(rst_n) |=> !(axi_assert.psv_axi_cb.aw_valid);
endproperty
// Check if the length of an exclusive access transaction don't pass 16 beats (Section A7.2.4)
property AXI4_AWLEN_LOCK;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_lock |-> (signed'(axi_assert.psv_axi_cb.aw_len)) <= 16;
endproperty
// Check if AWCACHE[3:2] are LOW, When AWVALID is HIGH and AWCACHE[1] is LOW (Table A4-5)
property AXI4_AWCACHE_LOW;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.aw_valid) && !(axi_assert.psv_axi_cb.aw_cache[1]) |-> !(axi_assert.psv_axi_cb.aw_cache[3:2]);
endproperty
// Check if a transactions of burst type FIXED don't have a length greater than 16 beats (Section A3.4.1)
property AXI4_AWLEN_FIXED;
@(posedge clk) disable iff (!rst_n) (axi_assert.psv_axi_cb.aw_burst == 2'b00) |-> (axi_assert.psv_axi_cb.aw_len <= 15);
endproperty
/********************************************** Assert Property ******************************************************/
aw_valid_aw_ready : assert property (AXI4_AW_VALID_READY)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AW_VALID_READY");
awaddr_wrap_align : assert property (AXI_AWADDR_WRAP_ALIGN)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI_AWADDR_WRAP_ALIGN");
assert_awsize : assert property (AXI_ERRM_AWSIZE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI_ERRM_AWSIZE");
awlen_wrapp_burst : assert property (AXI_AWLEN_WRAPP_BURST)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI_AWLEN_WRAPP_BURST");
aw_burst_cant_2b11 : assert property (AXI4_AW_BURST_CANT_2b11)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AW_BURST_CANT_2b11");
errm_awaddr_boundary : assert property (AXI4_ERRM_AWADDR_BOUNDARY)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_ERRM_AWADDR_BOUNDARY");
awvalid_reset : assert property (AXI4_AWVALID_RESET)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWVALID_RESET");
awlen_lock : assert property (AXI4_AWLEN_LOCK)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWLEN_LOCK");
awcahce_low : assert property (AXI4_AWCACHE_LOW)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWCACHE_LOW");
awlen_fixed : assert property (AXI4_AWLEN_FIXED)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWLEN_FIXED");
awid_x : assert property (AXI4_AWID_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWID_X");
awaddr_x : assert property (AXI4_AWADDR_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWADDR_X");
awlen_x : assert property (AXI4_AWLEN_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWLEN_X");
awsize_x : assert property (AXI4_AWSIZE_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWSIZE_X");
awburst_x : assert property (AXI4_AWBURST_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWBURST_X");
awlock_x : assert property (AXI4_AWLOCK_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWLOCK_X");
awcache_x : assert property (AXI4_AWCACHE_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWCACHE_X");
awprot_x : assert property (AXI4_AWPROT_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWPROT_X");
awuser_x : assert property (AXI4_AWUSER_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWUSER_X");
awqos_x : assert property (AXI4_AWQOS_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWQOS_X");
awregion_x : assert property (AXI4_AWREGION_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWREGION_X");
awvalid_x : assert property (AXI4_AWVALID_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWVALID_X");
awready_x : assert property (AXI4_AWREADY_X)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWREADY_X");
awid_stable : assert property (AXI4_AWID_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWID_STABLE");
awaddr_stable : assert property (AXI4_AWADDR_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWADDR_STABLE");
awlen_stable : assert property (AXI4_AWLEN_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWLEN_STABLE");
awsize_stable : assert property (AXI4_AWSIZE_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWSIZE_STABLE");
awburst_stable : assert property (AXI4_AWBURST_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWBURST_STABLE");
awlock_stable : assert property (AXI4_AWLOCK_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWLOCK_STABLE");
awcache_stable : assert property (AXI4_AWCACHE_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWCACHE_STABLE");
awprot_stable : assert property (AXI4_AWPROT_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWPROT_STABLE");
awuser_stable : assert property (AXI4_AWUSER_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWUSER_STABLE");
awqos_stable : assert property (AXI4_AWQOS_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWQOS_STABLE");
awregion_stable : assert property (AXI4_AWREGION_STABLE)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AWREGION_STABLE");
/********************************************** Cover Property ******************************************************/
cov_aw_valid_aw_ready : cover property(AXI4_AW_VALID_READY);
cov_awaddr_wrap_align : cover property(AXI_AWADDR_WRAP_ALIGN);
cov_awsize : cover property(AXI_ERRM_AWSIZE);
cov_awvalid_reset : cover property(AXI4_AWVALID_RESET);
cov_awlen_wrapp_burst : cover property(AXI_AWLEN_WRAPP_BURST);
cov_aw_burst_cant_2b11 : cover property(AXI4_AW_BURST_CANT_2b11);
cov_errm_awaddr_boundary : cover property(AXI4_ERRM_AWADDR_BOUNDARY);
cov_awlen_lock : cover property(AXI4_AWLEN_LOCK);
cov_awcache_low : cover property(AXI4_AWCACHE_LOW);
cov_awlen_fixed : cover property(AXI4_AWLEN_FIXED);
cov_awid_stable : cover property(AXI4_AWID_STABLE);
cov_awaddr_stable : cover property(AXI4_AWADDR_STABLE);
cov_awlen_stable : cover property(AXI4_AWLEN_STABLE);
cov_awsize_stable : cover property(AXI4_AWSIZE_STABLE);
cov_awburst_stable : cover property(AXI4_AWBURST_STABLE);
cov_awlock_stable : cover property(AXI4_AWLOCK_STABLE);
cov_awcache_stable : cover property(AXI4_AWCACHE_STABLE);
cov_awprot_stable : cover property(AXI4_AWPROT_STABLE);
cov_awuser_stable : cover property(AXI4_AWUSER_STABLE);
cov_awqos_stable : cover property(AXI4_AWQOS_STABLE);
cov_awregion_stable : cover property(AXI4_AWREGION_STABLE);
endmodule : uvma_axi_aw_assert
1. 简要介绍
uvma_axi_aw_assert.sv
文件定义了一个名为 uvma_axi_aw_assert
的模块,该模块用于对 AXI4 协议写地址通道(AW 通道)的信号进行协议规则检查。借助 SystemVerilog 属性(SVA)定义各种检查规则,通过断言语句在规则被违反时输出错误信息,同时使用覆盖属性进行覆盖率统计,以确保 AXI4 协议在写地址通道上的正确实现。
2. 接口介绍
module uvma_axi_aw_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
代码分析:
module uvma_axi_aw_assert
:声明模块名为uvma_axi_aw_assert
。uvma_axi_intf.passive axi_assert
:一个被动接口类型的端口,uvma_axi_intf
应该是自定义的接口类型,passive
表明该接口以被动模式工作,用于接收 AXI 接口的信号,以便对写地址通道信号进行监控和检查。input bit clk
:输入端口,数据类型为bit
,提供时钟信号。所有的属性检查都在时钟的上升沿触发,确保时序一致性。input rst_n
:输入端口,数据类型为bit
,表示异步复位信号,低电平有效。在复位期间,大部分属性检查会被禁用。
3. 参数介绍
此模块中没有显式使用 parameter
或 localparam
定义的参数。
4. 模块实现介绍
4.1 包导入
import uvm_pkg::*;
代码分析:导入 UVM(通用验证方法学)包中的所有内容,目的是后续可以使用 UVM 提供的宏,如 uvm_error
来输出错误信息,方便在验证环境中进行错误报告。
4.2 属性定义
以 AXI4_AWID_X
属性为例:
property AXI4_AWID_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_id));
endproperty
代码分析:
property AXI4_AWID_X;
:定义一个名为AXI4_AWID_X
的属性,用于检查写地址通道的aw_id
信号。@(posedge clk)
:指定属性检查在时钟clk
的上升沿触发。disable iff (!rst_n)
:当复位信号rst_n
为低电平时,禁用该属性检查,即复位期间不进行检查。axi_assert.psv_axi_cb.aw_valid |-> (!$isunknown(axi_assert.psv_axi_cb.aw_id))
:当aw_valid
信号为高电平时,通过蕴含操作符|->
断言aw_id
信号的值不为X
或Z
。
模块中定义了一系列类似的属性,分别对写地址通道的不同信号进行合法性、稳定性等方面的检查。
4.3 断言语句
以 aw_valid_aw_ready
断言为例:
aw_valid_aw_ready : assert property (AXI4_AW_VALID_READY)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_AW_VALID_READY");
代码分析:
aw_valid_aw_ready
:断言的名称,用于标识该断言。assert property (AXI4_AW_VALID_READY)
:对AXI4_AW_VALID_READY
属性进行断言检查。else
uvm_error (" AXI4 protocol checks assertion ", “Violation of AXI4_AW_VALID_READY”);:如果属性检查失败,使用 UVM 的
uvm_error宏输出错误信息,告知违反了
AXI4_AW_VALID_READY` 属性。
4.4 覆盖属性
以 cov_aw_valid_aw_ready
覆盖属性为例:
cov_aw_valid_aw_ready : cover property(AXI4_AW_VALID_READY);
代码分析:
cov_aw_valid_aw_ready
:覆盖属性的名称。cover property(AXI4_AW_VALID_READY)
:对AXI4_AW_VALID_READY
属性进行覆盖率统计。当该属性的条件被满足时,覆盖率工具会记录相应的覆盖点,帮助验证人员评估验证的完备性。
5. 总结
uvma_axi_aw_assert.sv
模块在 AXI4 协议的验证工作中起着关键作用。它通过定义多种 SystemVerilog 属性,全面检查写地址通道的信号是否符合 AXI4 协议规范。断言语句在协议规则被违反时及时输出错误信息,便于开发人员快速定位问题。覆盖属性则为验证人员提供了覆盖率数据,确保验证的完整性。整体而言,该模块提高了 AXI4 协议验证的效率和准确性,有助于保证设计的正确性。
3. core-v-verif/lib/uvm_agents/uvma_axi/src/uvma_axi_b_assert.sv
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi
// *************************** Write response CHANNEL ************************** //
module uvma_axi_b_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
import uvm_pkg::*;
// *************************** Check if Write Response Signals are not equal to X or Z when WVALID is HIGH (Section A3.2.2) ************************** //
property AXI4_BID_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!$isunknown(axi_assert.psv_axi_cb.b_id));
endproperty
property AXI4_BRESP_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!$isunknown(axi_assert.psv_axi_cb.b_resp));
endproperty
property AXI4_BUSER_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!$isunknown(axi_assert.psv_axi_cb.b_user));
endproperty
// A value of X on BVALID is not permitted when not in reset (Section A3.2.2)
property AXI4_BVALID_X;
@(posedge clk) disable iff (!rst_n) (!$isunknown(axi_assert.psv_axi_cb.b_valid));
endproperty
// A value of X on BVALID is not permitted when not in reset (Section A3.1.2)
property AXI4_BREADY_X;
@(posedge clk) disable iff (!rst_n) (!$isunknown(axi_assert.psv_axi_cb.b_ready));
endproperty
// *************************** Check if Write Response Signals are stable when AWVALID is HIGH (Section A3.2.1) ************************** //
property AXI4_BID_STABLE ;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!axi_assert.psv_axi_cb.b_ready |=> ($stable(axi_assert.psv_axi_cb.b_id)));
endproperty
property AXI4_BRESP_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!axi_assert.psv_axi_cb.b_ready |=> ($stable(axi_assert.psv_axi_cb.b_resp)));
endproperty
property AXI4_BUSER_STABLE;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!axi_assert.psv_axi_cb.b_ready |=> ($stable(axi_assert.psv_axi_cb.b_user)));
endproperty
// Check if, Once asserted, r_valid must remain asserted until r_ready is HIGH (Section A3.2.2)
property AXI4_BVALID_STABLE ;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> ( axi_assert.psv_axi_cb.b_valid throughout (axi_assert.psv_axi_cb.b_ready [->1]));
endproperty
// Check if RVALID is LOW for the first cycle after ARESETn goes HIGH (Figure A3-1)
property AXI4_BVALID_RESET;
@(posedge clk) $rose(rst_n) |=> !(axi_assert.psv_axi_cb.b_valid);
endproperty
/********************************************** Assert Property ******************************************************/
rvalid_reset : assert property (AXI4_BVALID_RESET)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BVALID_RESET");
bid_x : assert property (AXI4_BID_X)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BID_X");
bresp_x : assert property (AXI4_BRESP_X)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BRESP_X");
buser_x : assert property (AXI4_BUSER_X)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BUSER_X");
bvalid_x : assert property (AXI4_BVALID_X)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BVALID_X");
bready_x : assert property (AXI4_BREADY_X)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BREADY_X");
bvalid_stable : assert property (AXI4_BVALID_STABLE)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BVALID_STABLE");
bid_stable : assert property (AXI4_BID_STABLE)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BID_STABLE");
bresp_stable : assert property (AXI4_BRESP_STABLE)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BRESP_STABLE");
buser_stable : assert property (AXI4_BUSER_STABLE)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BUSER_STABLE");
/********************************************** Cover Property ******************************************************/
cov_bvalid_reset : cover property(AXI4_BVALID_RESET);
cov_bvalid_stable : cover property(AXI4_BVALID_STABLE);
cov_bid_stable : cover property(AXI4_BID_STABLE);
cov_bresp_stable : cover property(AXI4_BRESP_STABLE);
cov_buser_stable : cover property(AXI4_BUSER_STABLE);
endmodule : uvma_axi_b_assert
1. 简要介绍
uvma_axi_b_assert.sv
文件定义了一个名为 uvma_axi_b_assert
的模块,其主要功能是对 AXI4 协议中写响应通道(B 通道)的信号进行验证。该模块利用 SystemVerilog 属性(SVA)定义了一系列规则,用于检查信号的合法性、稳定性等,同时通过断言语句在规则被违反时输出错误信息,还使用覆盖属性来统计验证的覆盖率。
2. 接口介绍
module uvma_axi_b_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
代码分析:
module uvma_axi_b_assert
:声明模块名为uvma_axi_b_assert
。uvma_axi_intf.passive axi_assert
:这是一个被动接口类型的端口,uvma_axi_intf
应是自定义的接口类型,passive
表明该接口以被动模式工作,用于接收 AXI 接口的信号,以便对写响应通道的信号进行监控和验证。input bit clk
:输入端口,数据类型为bit
,提供时钟信号。所有的属性检查都在时钟的上升沿触发,保证时序同步。input rst_n
:输入端口,数据类型为bit
,表示异步复位信号,低电平有效。在复位期间,属性检查会被禁用。
3. 参数介绍
该模块中未显式定义 parameter
或 localparam
类型的参数。
4. 模块实现介绍
4.1 包导入
import uvm_pkg::*;
代码分析:导入 UVM(通用验证方法学)包中的所有内容,目的是后续可以使用 UVM 提供的宏,如 uvm_error
来输出错误信息,方便在验证环境中进行错误报告。
4.2 属性定义
以 AXI4_BID_X
属性为例:
property AXI4_BID_X;
@(posedge clk) disable iff (!rst_n) axi_assert.psv_axi_cb.b_valid |-> (!$isunknown(axi_assert.psv_axi_cb.b_id));
endproperty
代码分析:
property AXI4_BID_X;
:定义一个名为AXI4_BID_X
的属性,用于检查写响应通道的b_id
信号。@(posedge clk)
:指定属性检查在时钟clk
的上升沿触发。disable iff (!rst_n)
:当复位信号rst_n
为低电平时,禁用该属性检查,即复位期间不进行检查。axi_assert.psv_axi_cb.b_valid |-> (!$isunknown(axi_assert.psv_axi_cb.b_id))
:当b_valid
信号为高电平时,通过蕴含操作符|->
断言b_id
信号的值不为X
或Z
。
模块中定义了多个类似属性,分别对写响应通道的不同信号(如 b_resp
、b_user
、b_valid
、b_ready
等)进行合法性和稳定性检查。
4.3 断言语句
以 bid_x
断言为例:
bid_x : assert property (AXI4_BID_X)
else `uvm_error (" AXI4 protocol ckecks assertion ", "Violation of AXI4_BID_X");
代码分析:
bid_x
:断言的名称,用于标识该断言。assert property (AXI4_BID_X)
:对AXI4_BID_X
属性进行断言检查。else
uvm_error (" AXI4 protocol ckecks assertion ", “Violation of AXI4_BID_X”);:如果属性检查失败,使用 UVM 的
uvm_error宏输出错误信息,提示违反了
AXI4_BID_X` 属性。
4.4 覆盖属性
以 cov_bvalid_reset
覆盖属性为例:
cov_bvalid_reset : cover property(AXI4_BVALID_RESET);
代码分析:
cov_bvalid_reset
:覆盖属性的名称。cover property(AXI4_BVALID_RESET)
:对AXI4_BVALID_RESET
属性进行覆盖率统计。当该属性的条件被满足时,覆盖率工具会记录相应的覆盖点,帮助验证人员评估验证的完整性。
5. 总结
uvma_axi_b_assert.sv
模块是 AXI4 协议验证中重要的一部分,专注于写响应通道的信号验证。通过定义丰富的 SystemVerilog 属性,全面检查写响应通道信号的合法性和稳定性,确保协议的正确实现。断言语句在规则违反时能及时反馈错误信息,有助于开发人员快速定位问题。覆盖属性则为验证人员提供覆盖率数据,保证验证工作的完备性。整体上,该模块提高了 AXI4 协议验证的效率和准确性。
4. core-v-verif/lib/uvm_agents/uvma_axi/src/uvma_axi_intf.sv
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi
/**** AXI4 interface with parametrized : ****/
interface uvma_axi_intf #(
parameter AXI_ADDR_WIDTH = `UVMA_AXI_ADDR_MAX_WIDTH,
parameter AXI_DATA_WIDTH = `UVMA_AXI_DATA_MAX_WIDTH,
parameter AXI_USER_WIDTH = `UVMA_AXI_USER_MAX_WIDTH,
parameter AXI_ID_WIDTH = `UVMA_AXI_ID_MAX_WIDTH
) (input bit clk, bit rst_n);
// AXI4 signals
// Write Address channel
logic [AXI_ID_WIDTH-1:0] aw_id;
logic [AXI_ADDR_WIDTH-1:0] aw_addr;
logic [AXI_USER_WIDTH-1:0] aw_user;
logic [7:0] aw_len;
logic [2:0] aw_size;
logic [1:0] aw_burst;
logic aw_lock;
logic [3:0] aw_cache;
logic [2:0] aw_prot;
logic [3:0] aw_qos;
logic [3:0] aw_region;
logic aw_valid;
logic aw_ready;
logic [5:0] aw_atop;
//write data channel
logic [AXI_DATA_WIDTH-1:0] w_data;
logic [AXI_DATA_WIDTH/8-1:0] w_strb;
logic [AXI_USER_WIDTH-1:0] w_user;
logic w_last;
logic w_valid;
logic w_ready;
// write response channel
logic [AXI_ID_WIDTH-1:0] b_id;
logic [AXI_USER_WIDTH-1:0] b_user;
logic [1:0] b_resp;
logic b_valid;
logic b_ready;
// read address channel
logic [AXI_ID_WIDTH-1:0] ar_id;
logic [AXI_ADDR_WIDTH-1:0] ar_addr;
logic [AXI_USER_WIDTH-1:0] ar_user;
logic [7:0] ar_len;
logic [2:0] ar_size;
logic [1:0] ar_burst;
logic ar_lock;
logic [3:0] ar_cache;
logic [2:0] ar_prot;
logic [3:0] ar_qos;
logic [3:0] ar_region;
logic ar_valid;
logic ar_ready;
//read data channel
logic [AXI_ID_WIDTH-1:0] r_id;
logic [AXI_DATA_WIDTH-1:0] r_data;
logic [AXI_USER_WIDTH-1:0] r_user;
logic [1:0] r_resp;
logic r_last;
logic r_valid;
logic r_ready;
clocking slv_axi_cb @(posedge clk or rst_n);
output ar_ready,
r_id, r_data, r_resp, r_last, r_valid, r_user,
aw_ready,
w_ready,
b_id, b_resp, b_user, b_valid;
input ar_id, ar_addr, ar_user, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_valid,
r_ready,
aw_id, aw_addr, aw_user, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_valid, aw_atop,
w_data, w_strb, w_last, w_user, w_valid,
b_ready;
endclocking: slv_axi_cb
clocking psv_axi_cb @(posedge clk or rst_n);
input ar_id, ar_addr, ar_user, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_valid, ar_ready,
r_ready, r_id, r_data, r_resp, r_user, r_last, r_valid,
aw_id, aw_addr, aw_user, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_valid, aw_atop, aw_ready,
w_data, w_strb, w_last, w_user, w_valid, w_ready,
b_id, b_resp, b_user, b_valid, b_ready;
endclocking: psv_axi_cb
modport slave (clocking slv_axi_cb);
modport passive (clocking psv_axi_cb);
endinterface : uvma_axi_intf
1. 简要介绍
uvma_axi_intf.sv
定义了一个参数化的 AXI4 接口 uvma_axi_intf
。该接口用于在不同模块间传递 AXI4 协议相关的信号,支持对地址宽度、数据宽度、用户信号宽度和 ID 宽度等参数进行配置,同时定义了两种不同的时钟块和对应的端口模式,方便在不同场景下使用。
2. 接口介绍
interface uvma_axi_intf #(
parameter AXI_ADDR_WIDTH = `UVMA_AXI_ADDR_MAX_WIDTH,
parameter AXI_DATA_WIDTH = `UVMA_AXI_DATA_MAX_WIDTH,
parameter AXI_USER_WIDTH = `UVMA_AXI_USER_MAX_WIDTH,
parameter AXI_ID_WIDTH = `UVMA_AXI_ID_MAX_WIDTH
) (input bit clk, bit rst_n);
代码分析:
interface uvma_axi_intf
:声明一个名为uvma_axi_intf
的接口。#(
:开始参数列表,用于定义接口的可配置参数。parameter AXI_ADDR_WIDTH =
UVMA_AXI_ADDR_MAX_WIDTH:定义地址宽度参数,默认值为
UVMA_AXI_ADDR_MAX_WIDTH` 宏的值。parameter AXI_DATA_WIDTH =
UVMA_AXI_DATA_MAX_WIDTH:定义数据宽度参数,默认值为
UVMA_AXI_DATA_MAX_WIDTH` 宏的值。parameter AXI_USER_WIDTH =
UVMA_AXI_USER_MAX_WIDTH:定义用户信号宽度参数,默认值为
UVMA_AXI_USER_MAX_WIDTH` 宏的值。parameter AXI_ID_WIDTH =
UVMA_AXI_ID_MAX_WIDTH:定义 ID 宽度参数,默认值为
UVMA_AXI_ID_MAX_WIDTH` 宏的值。
)
:结束参数列表。(input bit clk, bit rst_n)
:定义接口的端口,clk
是时钟信号,rst_n
是复位信号,低电平有效。
3. 参数介绍
parameter AXI_ADDR_WIDTH = `UVMA_AXI_ADDR_MAX_WIDTH,
parameter AXI_DATA_WIDTH = `UVMA_AXI_DATA_MAX_WIDTH,
parameter AXI_USER_WIDTH = `UVMA_AXI_USER_MAX_WIDTH,
parameter AXI_ID_WIDTH = `UVMA_AXI_ID_MAX_WIDTH
代码分析:
AXI_ADDR_WIDTH
:用于指定 AXI4 协议中地址信号的宽度,默认值由UVMA_AXI_ADDR_MAX_WIDTH
宏决定。AXI_DATA_WIDTH
:用于指定 AXI4 协议中数据信号的宽度,默认值由UVMA_AXI_DATA_MAX_WIDTH
宏决定。AXI_USER_WIDTH
:用于指定 AXI4 协议中用户自定义信号的宽度,默认值由UVMA_AXI_USER_MAX_WIDTH
宏决定。AXI_ID_WIDTH
:用于指定 AXI4 协议中 ID 信号的宽度,默认值由UVMA_AXI_ID_MAX_WIDTH
宏决定。
4. 模块实现介绍
4.1 AXI4 信号定义
// Write Address channel
logic [AXI_ID_WIDTH-1:0] aw_id;
logic [AXI_ADDR_WIDTH-1:0] aw_addr;
// ... 其他信号定义 ...
代码分析:按照 AXI4 协议规范,定义了写地址通道、写数据通道、写响应通道、读地址通道和读数据通道的所有信号。信号的宽度根据前面定义的参数进行设置。
4.2 时钟块定义
clocking slv_axi_cb @(posedge clk or rst_n);
output ar_ready,
r_id, r_data, r_resp, r_last, r_valid, r_user,
aw_ready,
w_ready,
b_id, b_resp, b_user, b_valid;
input ar_id, ar_addr, ar_user, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_valid,
r_ready,
aw_id, aw_addr, aw_user, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_valid, aw_atop,
w_data, w_strb, w_last, w_user, w_valid,
b_ready;
endclocking: slv_axi_cb
clocking psv_axi_cb @(posedge clk or rst_n);
input ar_id, ar_addr, ar_user, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_valid, ar_ready,
r_ready, r_id, r_data, r_resp, r_user, r_last, r_valid,
aw_id, aw_addr, aw_user, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_valid, aw_atop, aw_ready,
w_data, w_strb, w_last, w_user, w_valid, w_ready,
b_id, b_resp, b_user, b_valid, b_ready;
endclocking: psv_axi_cb
代码分析:
clocking slv_axi_cb @(posedge clk or rst_n)
:定义一个名为slv_axi_cb
的时钟块,在时钟上升沿或复位信号变化时触发。output
部分定义了该时钟块输出的信号,input
部分定义了输入的信号,通常用于从设备的接口操作。clocking psv_axi_cb @(posedge clk or rst_n)
:定义一个名为psv_axi_cb
的时钟块,同样在时钟上升沿或复位信号变化时触发,所有信号都定义为输入,通常用于被动监控接口信号。
4.3 端口模式定义
modport slave (clocking slv_axi_cb);
modport passive (clocking psv_axi_cb);
代码分析:
modport slave (clocking slv_axi_cb)
:定义一个名为slave
的端口模式,使用slv_axi_cb
时钟块,用于从设备连接。modport passive (clocking psv_axi_cb)
:定义一个名为passive
的端口模式,使用psv_axi_cb
时钟块,用于被动监控接口信号。
5. 总结
uvma_axi_intf.sv
实现了一个灵活的 AXI4 接口,通过参数化设计,可以根据不同的需求调整地址、数据、用户和 ID 信号的宽度。时钟块和端口模式的定义使得该接口可以在不同的场景下使用,如从设备接口和被动监控。该接口为 AXI4 协议相关的设计和验证提供了基础框架,提高了代码的复用性和可维护性。
5. core-v-verif/lib/uvm_agents/uvma_axi/src/uvma_axi_macros.sv
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi
`ifndef __UVMA_AXI_MACROS_SV__
`define __UVMA_AXI_MACROS_SV__
parameter Nr_Slaves = 2; // actually masters, but slaves on the crossbar
parameter Id_Width = 4; // 4 is recommended by AXI standard, so lets stick to it, do not change
parameter Id_Width_Slave = Id_Width + $clog2(Nr_Slaves);
`define UVMA_AXI_ADDR_MAX_WIDTH 64
`define UVMA_AXI_DATA_MAX_WIDTH 64
`define UVMA_AXI_USER_MAX_WIDTH 1
`define UVMA_AXI_ID_MAX_WIDTH Id_Width_Slave
`define UVMA_AXI_STRB_MAX_WIDTH 8
`define per_instance_fcov `ifndef DSIM option.per_instance = 1; `endif
`endif // __UVMA_AXI_MACROS_SV__
1. 简要介绍
uvma_axi_macros.sv
文件主要用于定义 AXI 相关的参数和宏,这些参数和宏会在 AXI 验证环境里被复用。文件通过条件编译确保只被编译一次,定义了与 AXI 总线的从机数量、ID 宽度、地址宽度、数据宽度等相关的参数和宏,同时还包含一个与覆盖率选项有关的宏定义。
2. 接口介绍
此文件无传统意义上的接口,它主要是定义参数和宏,为其他模块或文件提供配置信息。
3. 参数介绍
parameter Nr_Slaves = 2; // actually masters, but slaves on the crossbar
parameter Id_Width = 4; // 4 is recommended by AXI standard, so lets stick to it, do not change
parameter Id_Width_Slave = Id_Width + $clog2(Nr_Slaves);
Nr_Slaves
:- 代码行:
parameter Nr_Slaves = 2; // actually masters, but slaves on the crossbar
- 介绍:定义从机的数量,注释表明实际是主机,但在交叉开关上作为从机。
- 逻辑分析:将从机数量初始化为 2,后续可根据实际需求修改该值。
- 代码行:
Id_Width
:- 代码行:
parameter Id_Width = 4; // 4 is recommended by AXI standard, so lets stick to it, do not change
- 介绍:定义 ID 的宽度,根据 AXI 标准推荐值设为 4,注释建议不要修改。
- 逻辑分析:遵循 AXI 标准,将 ID 宽度固定为 4,保证符合协议规范。
- 代码行:
Id_Width_Slave
:- 代码行:
parameter Id_Width_Slave = Id_Width + $clog2(Nr_Slaves);
- 介绍:计算从机 ID 的宽度,其值为
Id_Width
加上Nr_Slaves
以 2 为底的对数。 - 逻辑分析:根据从机数量动态计算从机 ID 的宽度,确保有足够的位宽来唯一标识每个从机。
- 代码行:
4. 模块实现介绍
4.1 条件编译
`ifndef __UVMA_AXI_MACROS_SV__
`define __UVMA_AXI_MACROS_SV__
// ... 中间代码 ...
`endif // __UVMA_AXI_MACROS_SV__
- 代码行:
ifndef __UVMA_AXI_MACROS_SV__
、define __UVMA_AXI_MACROS_SV__
和endif // __UVMA_AXI_MACROS_SV__
- 介绍:使用条件编译指令防止文件被重复编译。如果
__UVMA_AXI_MACROS_SV__
宏未定义,则定义该宏并编译中间代码;若已定义,则跳过中间代码。 - 逻辑分析:保证文件在整个编译过程中只被编译一次,避免重复定义带来的错误。
4.2 宏定义
`define UVMA_AXI_ADDR_MAX_WIDTH 64
`define UVMA_AXI_DATA_MAX_WIDTH 64
`define UVMA_AXI_USER_MAX_WIDTH 1
`define UVMA_AXI_ID_MAX_WIDTH Id_Width_Slave
`define UVMA_AXI_STRB_MAX_WIDTH 8
UVMA_AXI_ADDR_MAX_WIDTH
:定义 AXI 地址的最大宽度为 64 位。UVMA_AXI_DATA_MAX_WIDTH
:定义 AXI 数据的最大宽度为 64 位。UVMA_AXI_USER_MAX_WIDTH
:定义 AXI 用户信号的最大宽度为 1 位。UVMA_AXI_ID_MAX_WIDTH
:定义 AXI ID 的最大宽度为Id_Width_Slave
的值。UVMA_AXI_STRB_MAX_WIDTH
:定义 AXI 字节选通信号的最大宽度为 8 位。
4.3 覆盖率选项宏
`define per_instance_fcov `ifndef DSIM option.per_instance = 1; `endif
- 代码行:
define per_instance_fcov
ifndef DSIM option.per_instance = 1;endif
- 介绍:定义一个名为
per_instance_fcov
的宏,当DSIM
未定义时,设置覆盖率选项option.per_instance
为 1。 - 逻辑分析:根据编译环境是否定义
DSIM
来决定是否设置覆盖率选项,用于控制覆盖率统计的方式。
5. 总结
uvma_axi_macros.sv
文件通过参数和宏的定义,为 AXI 验证环境提供了统一的配置信息。条件编译确保文件不会被重复编译,参数和宏的设置遵循 AXI 标准并考虑了一定的灵活性,如从机 ID 宽度的动态计算。覆盖率选项宏则为验证过程中的覆盖率统计提供了控制手段,整体上提高了代码的可维护性和复用性。