UVM环境介绍
HEAD commitID: 1f968ef
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
module uvma_obi_memory_1p2_assert
// Known reuse of port list from uvma_obi_memory_assert
//@DVT_LINTER_WAIVER_START "SR20211012_1" disable SVTB.33.1.0
import uvm_pkg::*;
#(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned AUSER_WIDTH = 0,
parameter int unsigned WUSER_WIDTH = 0,
parameter int unsigned RUSER_WIDTH = 0,
parameter int unsigned ID_WIDTH = 0,
parameter int unsigned ACHK_WIDTH = 0,
parameter int unsigned RCHK_WIDTH = 0
)
(
input clk,
input reset_n,
// A bus 1P1
input req,
input gnt,
input [ADDR_WIDTH-1:0] addr,
input we,
input [DATA_WIDTH/8-1:0] be,
input [DATA_WIDTH-1:0] wdata,
// A bus 1P2
input [((AUSER_WIDTH == 0) ? 0 : AUSER_WIDTH - 1) : 0] auser,
input [((WUSER_WIDTH == 0) ? 0 : WUSER_WIDTH - 1) : 0] wuser,
input [((ID_WIDTH == 0) ? 0 : ID_WIDTH - 1) : 0] aid,
input [5:0] atop,
input [1:0] memtype,
input [2:0] prot,
input reqpar,
input gntpar,
input [((ACHK_WIDTH == 0) ? 0 : ACHK_WIDTH - 1) : 0] achk,
// R bus 1P1
input [DATA_WIDTH-1:0] rdata,
input rvalid,
// R bus 1P2
input rready,
input err,
input [((RUSER_WIDTH == 0) ? 0 : RUSER_WIDTH - 1) : 0] ruser,
input [((ID_WIDTH == 0) ? 0 : ID_WIDTH - 1) : 0] rid,
input exokay,
input rvalidpar,
input rreadypar,
input [((RCHK_WIDTH == 0) ? 0 : RCHK_WIDTH - 1) : 0] rchk
);
// ---------------------------------------------------------------------------
// Local parameters
// ---------------------------------------------------------------------------
localparam EFF_ID_WIDTH = ID_WIDTH == 0 ? 1 : ID_WIDTH;
localparam ADDR_ALIGN_MASK = (1 << $clog2(DATA_WIDTH)) - 1;
localparam ATOP_LR = {1'b1, 4'h2};
localparam ATOP_SC = {1'b1, 4'h3};
//@DVT_LINTER_WAIVER_END "SR20211012_1"
// ---------------------------------------------------------------------------
// Typedefs
// ---------------------------------------------------------------------------
typedef struct {
bit [4:0] atop;
bit [EFF_ID_WIDTH-1:0] aid;
} aid_q_t;
// ---------------------------------------------------------------------------
// Local variables
// ---------------------------------------------------------------------------
string info_tag = "OBIMEM1P2ASRT";
reg atomic_in_flight;
wire valid_a_phase;
wire valid_r_phase;
aid_q_t aid_q[3:0];
bit [4:0] aid_wptr;
bit [4:0] aid_rptr;
bit atomic_trn_active;
// ---------------------------------------------------------------------------
// Clocking blocks
// ---------------------------------------------------------------------------
// Single clock, single reset design, use default clocking
default clocking @(posedge clk); endclocking
default disable iff !(reset_n);
// ---------------------------------------------------------------------------
// Begin module code
// ---------------------------------------------------------------------------
// Modeling logic and common decoding
assign valid_a_phase = req && gnt;
assign valid_r_phase = rvalid && rready;
// R-3.1.1 : A phase signals stable during address phase
property p_addr_signal_stable(sig);
req ##0 !gnt |=> $stable(sig);
endproperty : p_addr_signal_stable
a_auser_stable: assert property(p_addr_signal_stable(auser))
else
`uvm_error(info_tag, "auser signal not stable in address phase")
a_wuser_stable: assert property(p_addr_signal_stable(wuser))
else
`uvm_error(info_tag, "wuser signal not stable in address phase")
a_aid_stable: assert property(p_addr_signal_stable(aid))
else
`uvm_error(info_tag, "aid signal not stable in address phase")
a_atop_stable: assert property(p_addr_signal_stable(atop))
else
`uvm_error(info_tag, "atop signal not stable in address phase")
a_memtype_stable: assert property(p_addr_signal_stable(memtype))
else
`uvm_error(info_tag, "memtype signal not stable in address phase")
a_prot_stable: assert property(p_addr_signal_stable(prot))
else
`uvm_error(info_tag, "prot signal not stable in address phase")
a_achk_stable: assert property(p_addr_signal_stable(achk))
else
`uvm_error(info_tag, "achk signal not stable in address phase")
// R-3.1.2 : Req may not deassewrt until the gnt is asserted
property p_req_until_gnt;
req ##0 !gnt |=> req;
endproperty : p_req_until_gnt
a_req_until_gnt : assert property(p_req_until_gnt)
else
`uvm_error(info_tag, "req may not deassert until gnt asserted")
// R-4.1.1 : R phase signals stable during respnose phase
property p_r_signal_stable(sig);
rvalid ##0 !rready |=> $stable(sig);
endproperty : p_r_signal_stable
a_rdata_stable: assert property(p_r_signal_stable(rdata))
else
`uvm_error(info_tag, "rdata signal not stable in response phase")
a_err_stable: assert property(p_r_signal_stable(err))
else
`uvm_error(info_tag, "err signal not stable in response phase")
a_ruser_stable: assert property(p_r_signal_stable(ruser))
else
`uvm_error(info_tag, "ruser signal not stable in response phase")
a_rid_stable: assert property(p_r_signal_stable(rid))
else
`uvm_error(info_tag, "rid signal not stable in response phase")
a_exokay_stable: assert property(p_r_signal_stable(exokay))
else
`uvm_error(info_tag, "exokay signal not stable in response phase")
a_rchk_stable: assert property(p_r_signal_stable(rchk))
else
`uvm_error(info_tag, "rchk signal not stable in response phase")
// R-4.1.2 : Req may not deassewrt until the gnt is asserted
property p_rvalid_until_rready;
rvalid ##0 !rready |=> rvalid;
endproperty : p_rvalid_until_rready
a_rvalid_until_rready : assert property(p_rvalid_until_rready)
else
`uvm_error(info_tag, "rvalid may not deassert until rready asserted")
// These next 2 are not strictly a functional requirement, but the testbench should simulate this
// Therefore these are coded as a set of cover properties
// R-4.2.1 : master shall be allowed to de-assert (retract) rready at any time even if rvalid is deasserted
property p_rready_assert_no_rvalid;
!rvalid ##0 !rready ##1 !rvalid ##0 rready;
endproperty : p_rready_assert_no_rvalid
c_rready_assert_no_rvalid : cover property(p_rready_assert_no_rvalid);
// R-4.2.2 : master shall be allowed to de-assert (retract) rready at any time even if rvalid is deasserted
property p_rready_deassert_no_rvalid;
!rvalid ##0 rready ##1 !rvalid ##0 !rready;
endproperty : p_rready_deassert_no_rvalid
c_rready_deassert_no_rvalid : cover property(p_rready_deassert_no_rvalid);
// R-9 For each OBI transactions the slave shall mirror back the value recieved on aid via rid
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
aid_wptr <= '0;
aid_rptr <= '0;
atomic_in_flight <= '0;
end
else begin
if (valid_a_phase) begin
aid_q[aid_wptr] <= '{atop, aid};
aid_wptr <= aid_wptr + 1;
if (atop) atomic_in_flight <= 1'b1;
end
if (valid_r_phase) begin
if (aid_q[aid_rptr].atop) atomic_in_flight <= 1'b0;
aid_rptr <= aid_rptr + 1;
end
end
end
property p_rid_follows_aid;
rvalid |-> rid == aid_q[aid_rptr].aid;
endproperty
a_rid_follows_aid: assert property(p_rid_follows_aid)
else
`uvm_error(info_tag, $sformatf("rid of 0x%0x does not follow expected aid of 0x%0x", rid, aid_q[aid_rptr].aid))
// R-10.4 An atomic transaction must use a naturally aligned address
property p_atomic_addr_aligned;
req ##0 atop |-> addr & (ADDR_ALIGN_MASK) == 0;
endproperty
a_atomic_addr_aligned : assert property(p_atomic_addr_aligned)
else
`uvm_error(info_tag, $sformatf("Atomic transaction does not use aligned address: 0x%08x", addr))
// R-11 If an exclusive transaction is executing another may not be emitted
property p_one_atomic_trn;
req |-> !atomic_in_flight;
endproperty : p_one_atomic_trn
a_one_atomic_trn: assert property(p_one_atomic_trn)
else
`uvm_error(info_tag, "Detected multiple atomic transactions active at same time");
// R-12.3 EXOKAY may only be asserted in response to transactions that are LR or SC
property p_exokay_lr_sc;
rvalid && exokay |-> aid_q[aid_rptr].atop inside {ATOP_LR, ATOP_SC};
endproperty : p_exokay_lr_sc
a_exokay_lr_sc: assert property(p_exokay_lr_sc)
else
`uvm_error(info_tag, "EXOKAY may only asserted in response to an LR or SC transaction (signaled via atop)")
endmodule : uvma_obi_memory_1p2_assert
lib/uvm_agents/uvma_obi_memory/src/uvma_obi_memory_1p2_assert.sv
1. 简要介绍
该文件是OBI(Open Bus Interface)内存接口1.2版本的断言模块实现,主要功能包括:
- 验证OBI协议1.2版本的合规性
- 检查地址和数据信号的稳定性
- 监控原子操作的正确性
- 确保事务ID的匹配关系
2. 接口介绍
2.1 模块定义
module uvma_obi_memory_1p2_assert
import uvm_pkg::*;
#(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 32
)
- 代码介绍:定义参数化断言模块
- 参数:
- ADDR_WIDTH:地址总线宽度
- DATA_WIDTH:数据总线宽度
2.2 输入信号
input clk,
input reset_n,
input req,
input gnt,
input [ADDR_WIDTH-1:0] addr
- 代码介绍:定义时钟、复位和基本总线信号
- 功能:监控OBI协议的关键信号
3. 参数介绍
3.1 局部参数
localparam EFF_ID_WIDTH = ID_WIDTH == 0 ? 1 : ID_WIDTH;
localparam ADDR_ALIGN_MASK = (1 << $clog2(DATA_WIDTH)) - 1;
- 参数说明:
- EFF_ID_WIDTH:有效ID宽度
- ADDR_ALIGN_MASK:地址对齐掩码
3.2 原子操作类型
localparam ATOP_LR = {1'b1, 4'h2};
localparam ATOP_SC = {1'b1, 4'h3};
- 参数说明:定义LR(Load Reserved)和SC(Store Conditional)原子操作编码
4. 模块实现介绍
4.1 地址阶段断言
property p_addr_signal_stable(sig);
req ##0 !gnt |=> $stable(sig);
endproperty
a_auser_stable: assert property(p_addr_signal_stable(auser))
- 代码分析:
- 定义信号稳定性检查属性
- 在req有效但gnt无效时检查信号稳定性
- 应用于所有地址阶段信号
4.2 原子操作检查
property p_atomic_addr_aligned;
req ##0 atop |-> addr & (ADDR_ALIGN_MASK) == 0;
endproperty
- 代码分析:
- 检查原子操作地址对齐
- 使用地址对齐掩码验证
- 确保原子操作地址符合规范
5. 总结
该断言模块具有以下特点:
- 全面的OBI协议1.2版本检查
- 精确的信号稳定性验证
- 严格的原子操作监控
- 灵活的参数化设计
- 完善的错误报告机制
作为验证环境的关键组件,它为OBI内存接口提供了可靠的协议合规性检查,确保设计符合规范要求。
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This module facilitates easy connection of a uvma_obi_memory_if instance to the assertion module,
// which has individual wire ports
module uvma_obi_memory_assert_if_wrp
import uvm_pkg::*;
#(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned AUSER_WIDTH = 0,
parameter int unsigned WUSER_WIDTH = 0,
parameter int unsigned RUSER_WIDTH = 0,
parameter int unsigned ID_WIDTH = 0,
parameter int unsigned ACHK_WIDTH = 0,
parameter int unsigned RCHK_WIDTH = 0,
parameter bit IS_1P2 = 0
)
(
uvma_obi_memory_if obi
);
// ---------------------------------------------------------------------------
// Local parameters
// ---------------------------------------------------------------------------
// Some "WIDTHs" may be zero, set these to 1 to avoid negative bit-vector indices
localparam EFF_ID_WIDTH = ID_WIDTH == 0 ? 1 : ID_WIDTH;
localparam EFF_AUSER_WIDTH = AUSER_WIDTH == 0 ? 1 : AUSER_WIDTH;
localparam EFF_RUSER_WIDTH = RUSER_WIDTH == 0 ? 1 : RUSER_WIDTH;
localparam EFF_WUSER_WIDTH = WUSER_WIDTH == 0 ? 1 : WUSER_WIDTH;
localparam EFF_ACHK_WIDTH = ACHK_WIDTH == 0 ? 1 : ACHK_WIDTH;
localparam EFF_RCHK_WIDTH = RCHK_WIDTH == 0 ? 1 : RCHK_WIDTH;
// ---------------------------------------------------------------------------
// Begin module code
// ---------------------------------------------------------------------------
uvma_obi_memory_assert#(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH(DATA_WIDTH),
.AUSER_WIDTH(AUSER_WIDTH),
.WUSER_WIDTH(WUSER_WIDTH),
.RUSER_WIDTH(RUSER_WIDTH),
.ID_WIDTH(ID_WIDTH),
.ACHK_WIDTH(ACHK_WIDTH),
.RCHK_WIDTH(RCHK_WIDTH),
.IS_1P2(IS_1P2)
) u_assert(
.clk(obi.clk),
.reset_n(obi.reset_n),
.req(obi.req),
.gnt(obi.gnt),
.addr(obi.addr[ADDR_WIDTH-1:0]),
.we(obi.we),
.be(obi.be),
.wdata(obi.wdata[DATA_WIDTH-1:0]),
.auser(obi.auser[EFF_AUSER_WIDTH-1:0]),
.wuser(obi.wuser[EFF_WUSER_WIDTH-1:0]),
.aid(obi.aid[EFF_ID_WIDTH-1:0]),
.atop(obi.atop),
.memtype(obi.memtype),
.prot(obi.prot),
.reqpar(obi.reqpar),
.gntpar(obi.gntpar),
.achk(obi.achk[EFF_ACHK_WIDTH-1:0]),
.rdata(obi.rdata[DATA_WIDTH-1:0]),
.rvalid(obi.rvalid),
.rready(obi.rready),
.err(obi.err),
.ruser(obi.ruser[EFF_RUSER_WIDTH-1:0]),
.rid(obi.rid[EFF_ID_WIDTH-1:0]),
.exokay(obi.exokay),
.rvalidpar(obi.rvalidpar),
.rreadypar(obi.rreadypar),
.rchk(obi.rchk[EFF_RCHK_WIDTH-1:0])
);
endmodule : uvma_obi_memory_assert_if_wrp
lib/uvm_agents/uvma_obi_memory/src/uvma_obi_memory_assert_if_wrp.sv
1. 简要介绍
该文件是OBI内存接口断言模块的包装器实现,主要功能包括:
- 连接OBI内存接口到断言模块
- 处理不同位宽参数的适配
- 支持OBI协议1.2版本
- 提供参数化配置能力
2. 接口介绍
2.1 模块定义
module uvma_obi_memory_assert_if_wrp
import uvm_pkg::*;
#(
parameter int unsigned ADDR_WIDTH = 32
)
- 代码介绍:定义参数化包装器模块
- 特点:导入UVM包并支持多种位宽参数
2.2 接口端口
(uvma_obi_memory_if obi);
- 代码介绍:定义OBI内存接口实例
- 功能:作为断言模块的连接桥梁
3. 参数介绍
3.1 有效位宽计算
localparam EFF_ID_WIDTH = ID_WIDTH == 0 ? 1 : ID_WIDTH;
localparam EFF_AUSER_WIDTH = AUSER_WIDTH == 0 ? 1 : AUSER_WIDTH;
- 参数说明:处理零位宽的特殊情况
- 逻辑:当位宽为0时使用1位默认值
3.2 版本控制参数
parameter bit IS_1P2 = 0
- 参数说明:控制OBI协议版本
- 取值:1表示使用1.2版本协议
4. 模块实现介绍
4.1 断言模块实例化
uvma_obi_memory_assert#(
.ADDR_WIDTH(ADDR_WIDTH),
.IS_1P2(IS_1P2)
) u_assert(
.clk(obi.clk),
.reset_n(obi.reset_n)
);
- 代码分析:
- 参数化实例化断言模块
- 传递时钟和复位信号
- 连接所有总线信号
4.2 信号位宽适配
.aid(obi.aid[EFF_ID_WIDTH-1:0]),
.auser(obi.auser[EFF_AUSER_WIDTH-1:0])
- 代码分析:使用有效位宽参数截取信号
- 目的:避免零位宽信号的索引问题
5. 总结
该包装器模块具有以下特点:
- 灵活的位宽适配能力
- 简洁的接口连接设计
- 完善的协议版本支持
- 可靠的参数传递机制
作为验证环境的基础组件,它为OBI内存接口的断言检查提供了便捷的连接方式,确保协议验证的完整性和准确性。
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
module uvma_obi_memory_assert
import uvm_pkg::*;
#(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned AUSER_WIDTH = 0,
parameter int unsigned WUSER_WIDTH = 0,
parameter int unsigned RUSER_WIDTH = 0,
parameter int unsigned ID_WIDTH = 0,
parameter int unsigned ACHK_WIDTH = 0,
parameter int unsigned RCHK_WIDTH = 0,
parameter bit IS_1P2 = 0
)
(
input clk,
input reset_n,
// A bus 1P1
input req,
input gnt,
input [ADDR_WIDTH-1:0] addr,
input we,
input [DATA_WIDTH/8-1:0] be,
input [DATA_WIDTH-1:0] wdata,
// A bus 1P2
input [((AUSER_WIDTH == 0) ? 0 : AUSER_WIDTH - 1) : 0] auser,
input [((WUSER_WIDTH == 0) ? 0 : WUSER_WIDTH - 1) : 0] wuser,
input [((ID_WIDTH == 0) ? 0 : ID_WIDTH - 1) : 0] aid,
input [5:0] atop,
input [1:0] memtype,
input [2:0] prot,
input reqpar,
input gntpar,
input [((ACHK_WIDTH == 0) ? 0 : ACHK_WIDTH - 1) : 0] achk,
// R bus 1P1
input [DATA_WIDTH-1:0] rdata,
input rvalid,
// R bus 1P2
input rready,
input err,
input [((RUSER_WIDTH == 0) ? 0 : RUSER_WIDTH - 1) : 0] ruser,
input [((ID_WIDTH == 0) ? 0 : ID_WIDTH - 1) : 0] rid,
input exokay,
input rvalidpar,
input rreadypar,
input [((RCHK_WIDTH == 0) ? 0 : RCHK_WIDTH - 1) : 0] rchk
);
// ---------------------------------------------------------------------------
// Local parameters
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Local variables
// ---------------------------------------------------------------------------
string info_tag = "OBIMEMASRT";
wire valid_a_phase;
wire valid_r_phase;
// ---------------------------------------------------------------------------
// Clocking blocks
// ---------------------------------------------------------------------------
// Single clock, single reset design, use default clocking
default clocking @(posedge clk); endclocking
default disable iff !(reset_n);
// ---------------------------------------------------------------------------
// Begin module code
// ---------------------------------------------------------------------------
// If this is 1P2 generate the 1p2 assertion module
generate if (IS_1P2) begin : gen_1p2
uvma_obi_memory_1p2_assert#(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH(DATA_WIDTH),
.AUSER_WIDTH(AUSER_WIDTH),
.WUSER_WIDTH(WUSER_WIDTH),
.RUSER_WIDTH(RUSER_WIDTH),
.ID_WIDTH(ID_WIDTH),
.ACHK_WIDTH(ACHK_WIDTH),
.RCHK_WIDTH(RCHK_WIDTH)
) u_1p2_assert(.atop ('0), // todo: remove a-ext related signals
.exokay ('0), //
.*);
end
endgenerate
// Modeling logic and common decoding
assign valid_a_phase = req && gnt;
assign valid_r_phase = rvalid;
// R-3.1.1 : A phase signals stable during address phase
property p_addr_signal_stable(sig);
req ##0 !gnt |=> $stable(sig);
endproperty : p_addr_signal_stable
a_addr_stable: assert property(p_addr_signal_stable(addr))
else
`uvm_error(info_tag, "addr signal not stable in address phase")
a_we_stable: assert property(p_addr_signal_stable(we))
else
`uvm_error(info_tag, "we signal not stable in address phase")
a_wdata_stable: assert property(p_addr_signal_stable(wdata))
else
`uvm_error(info_tag, "wdata signal not stable in address phase")
a_be_stable: assert property(p_addr_signal_stable(be))
else
`uvm_error(info_tag, "be signal not stable in address phase")
// R-3.1.2 : Req may not deassewrt until the gnt is asserted
property p_req_until_gnt;
req ##0 !gnt |=> req;
endproperty : p_req_until_gnt
a_req_until_gnt : assert property(p_req_until_gnt)
else
`uvm_error(info_tag, "req may not deassert until gnt asserted")
// These next 2 are not strictly a functional requirement, but the testbench should simulate this
// Therefore these are coded as a set of cover properties
// R-3.2.1 : slave shall be allowed to de-assert (retract) gnt at any time even if req is deasserted
property p_gnt_assert_no_req;
!req ##0 !gnt ##1 !req ##0 gnt;
endproperty : p_gnt_assert_no_req
c_gnt_assert_no_req : cover property(p_gnt_assert_no_req);
// R-3.2.2 : slave shall be allowed to de-assert (retract) gnt at any time even if req is deasserted
property p_gnt_deassert_no_req;
!req ##0 gnt ##1 !req ##0 !gnt;
endproperty : p_gnt_deassert_no_req
c_gnt_deassert_no_req : cover property(p_gnt_deassert_no_req);
// R-5 ensure that rvalid is never asserted before or coincident to its address phase
// Model outstanding accepted addresses
bit [3:0] outstanding_trn_cnt;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
outstanding_trn_cnt <= 0;
end
else begin
if (valid_a_phase && !valid_r_phase)
outstanding_trn_cnt <= outstanding_trn_cnt + 4'h1;
else if (!valid_a_phase && valid_r_phase)
outstanding_trn_cnt <= outstanding_trn_cnt - 4'h1;
end
end
property p_r_after_a;
rvalid |-> outstanding_trn_cnt != 0;
endproperty : p_r_after_a
a_r_after_a : assert property(p_r_after_a)
else
`uvm_error(info_tag, "response phase started before address phase")
// R-7 At least one byte enable must be set
property p_be_not_zero;
req ##0 we |-> be != 0;
endproperty : p_be_not_zero
a_be_not_zero : assert property(p_be_not_zero)
else
`uvm_error(info_tag, "be was zero during an address cycle")
// R-7 All ones must be contiguous in writes
reg[3:0] contiguous_be[] = {
4'b0001,
4'b0011,
4'b0111,
4'b1111,
4'b0010,
4'b0110,
4'b1110,
4'b0100,
4'b1100,
4'b1000
};
bit be_inside_contiguous_be;
always_comb begin
be_inside_contiguous_be = be inside {contiguous_be};
end
property p_be_contiguous;
req ##0 we |-> be_inside_contiguous_be;
endproperty : p_be_contiguous
a_be_contiguous : assert property(p_be_contiguous)
else
`uvm_error(info_tag, $sformatf("be of 0x%0x was not contiguous", $sampled(be)));
// R-8 Data address LSBs must be consistent with byte enables on writes
function bit [1:0] get_addr_lsb(bit[3:0] be);
casex (be)
4'b???1: return 0;
4'b??10: return 1;
4'b?100: return 2;
4'b1000: return 3;
endcase
endfunction : get_addr_lsb
// R-8 Data address LSBs must be consistent with byte enables on writes
function bit [3:0] get_min_be(bit [ADDR_WIDTH-1:0] addr);
casex (addr)
4'b???1: return 'b0000;
4'b??10: return 'b0010;
4'b?100: return 'b0100;
4'b1000: return 'b1000;
endcase
endfunction : get_min_be
property p_addr_be_consistent;
disable iff (DATA_WIDTH !== 32) req |-> (get_min_be(addr) <= be);
endproperty : p_addr_be_consistent
a_addr_be_consistent: assert property(p_addr_be_consistent)
else
`uvm_error(info_tag, $sformatf("be of 0x%01x not consistent with addr 0x%08x", $sampled(be), $sampled(addr)));
endmodule : uvma_obi_memory_assert
uvma_obi_memory_assert.sv
1. 简要介绍
该文件是OBI内存接口的断言验证模块,主要功能包括:
- 验证OBI协议1.1和1.2版本的合规性
- 检查地址和数据信号的稳定性
- 监控事务ID匹配关系
- 确保字节使能信号的正确性
2. 接口介绍
2.1 模块定义
module uvma_obi_memory_assert
import uvm_pkg::*;
#(
parameter int unsigned ADDR_WIDTH = 32
)
- 代码介绍:定义参数化断言模块
- 特点:支持多种位宽配置和协议版本
2.2 输入信号
input clk,
input reset_n,
input req,
input gnt
- 代码介绍:定义基础控制信号
- 功能:监控协议基本时序
3. 参数介绍
3.1 版本控制参数
parameter bit IS_1P2 = 0
- 参数说明:控制OBI协议版本
- 取值:1表示使用1.2版本协议
3.2 位宽参数
parameter int unsigned DATA_WIDTH = 32
- 参数说明:定义数据总线宽度
- 默认值:32位
4. 模块实现介绍
4.1 信号稳定性检查
property p_addr_signal_stable(sig);
req ##0 !gnt |=> $stable(sig);
endproperty
a_addr_stable: assert property(p_addr_signal_stable(addr))
- 代码分析:
- 定义地址信号稳定性属性
- 在req有效但gnt无效时检查信号稳定性
- 生成断言错误信息
4.2 字节使能检查
property p_be_contiguous;
req ##0 we |-> be_inside_contiguous_be;
endproperty
- 代码分析:
- 检查写操作的字节使能连续性
- 使用预定义的合法模式匹配
- 确保字节使能符合协议要求
5. 总结
该断言模块具有以下特点:
- 全面的协议版本支持
- 严格的信号稳定性验证
- 精确的字节使能检查
- 灵活的参数化配置
- 完善的错误报告机制
作为验证环境的核心组件,它为OBI内存接口提供了可靠的协议合规性检查,确保设计实现符合规范要求。
`ifndef __UVMA_OBI_MEMORY_CONSTANTS_SV__
`define __UVMA_OBI_MEMORY_CONSTANTS_SV__
const int unsigned uvma_obi_memory_default_auser_width = `UVMA_OBI_MEMORY_AUSER_DEFAULT_WIDTH; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_wuser_width = `UVMA_OBI_MEMORY_WUSER_DEFAULT_WIDTH; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_ruser_width = `UVMA_OBI_MEMORY_RUSER_DEFAULT_WIDTH; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_addr_width = `UVMA_OBI_MEMORY_ADDR_DEFAULT_WIDTH ; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_data_width = `UVMA_OBI_MEMORY_DATA_DEFAULT_WIDTH ; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_id_width = `UVMA_OBI_MEMORY_ID_DEFAULT_WIDTH ; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_achk_width = `UVMA_OBI_MEMORY_ACHK_DEFAULT_WIDTH ; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_rchk_width = `UVMA_OBI_MEMORY_RCHK_DEFAULT_WIDTH ; // Measured in bits (b)
const int unsigned uvma_obi_memory_default_drv_slv_gnt_fixed_latency = 1;
const int unsigned uvma_obi_memory_default_drv_slv_gnt_random_latency_min = 0;
const int unsigned uvma_obi_memory_default_drv_slv_gnt_random_latency_max = 10;
const int unsigned uvma_obi_memory_default_drv_slv_rvalid_fixed_latency = 1;
const int unsigned uvma_obi_memory_default_drv_slv_rvalid_random_latency_min = 0;
const int unsigned uvma_obi_memory_default_drv_slv_rvalid_random_latency_max = 10;
const int unsigned UVMA_OBI_MEMORY_MEMTYPE_BUFFERABLE_BIT = 0;
const int unsigned UVMA_OBI_MEMORY_MEMTYPE_CACHEABLE_BIT = 1;
`endif // __UVMA_OBI_MEMORY_CONSTANTS_SV__
uvma_obi_memory_constants.sv
1. 简要介绍
该文件是OBI内存接口的常量定义文件,主要功能包括:
- 定义默认总线位宽参数
- 设置驱动响应延迟范围
- 声明内存类型标志位
- 提供协议版本控制常量
2. 接口介绍
2.1 宏定义保护
`ifndef __UVMA_OBI_MEMORY_CONSTANTS_SV__
`define __UVMA_OBI_MEMORY_CONSTANTS_SV__
- 代码介绍:标准宏定义保护结构
- 功能:防止重复包含
2.2 默认位宽定义
const int unsigned uvma_obi_memory_default_auser_width = `UVMA_OBI_MEMORY_AUSER_DEFAULT_WIDTH;
- 代码介绍:通过宏定义默认位宽
- 特点:支持参数化配置
3. 参数介绍
3.1 延迟控制参数
const int unsigned uvma_obi_memory_default_drv_slv_gnt_fixed_latency = 1;
const int unsigned uvma_obi_memory_default_drv_slv_gnt_random_latency_min = 0;
- 参数说明:
- 固定延迟:1个周期
- 随机延迟范围:0-10个周期
3.2 内存类型标志
const int unsigned UVMA_OBI_MEMORY_MEMTYPE_BUFFERABLE_BIT = 0;
const int unsigned UVMA_OBI_MEMORY_MEMTYPE_CACHEABLE_BIT = 1;
- 参数说明:定义内存属性标志位位置
- 用途:控制内存访问行为
4. 模块实现介绍
4.1 位宽参数定义
const int unsigned uvma_obi_memory_default_addr_width = `UVMA_OBI_MEMORY_ADDR_DEFAULT_WIDTH;
const int unsigned uvma_obi_memory_default_data_width = `UVMA_OBI_MEMORY_DATA_DEFAULT_WIDTH;
- 代码分析:
- 地址总线默认32位
- 数据总线默认32位
- 通过宏定义实现灵活配置
4.2 响应延迟控制
const int unsigned uvma_obi_memory_default_drv_slv_rvalid_fixed_latency = 1;
const int unsigned uvma_obi_memory_default_drv_slv_rvalid_random_latency_max = 10;
- 代码分析:
- 固定延迟和随机延迟配合使用
- 支持测试场景多样性
- 覆盖典型延迟情况
5. 总结
该常量定义文件具有以下特点:
- 全面的位宽参数配置
- 灵活的延迟控制机制
- 清晰的内存属性定义
- 标准的宏保护结构
作为验证环境的基础组件,它为OBI内存接口验证提供了统一的参数定义,确保各模块使用一致的配置参数。