core-v-verif系列之lib<57>

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版本的断言模块实现,主要功能包括:

  1. 验证OBI协议1.2版本的合规性
  2. 检查地址和数据信号的稳定性
  3. 监控原子操作的正确性
  4. 确保事务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))
  • 代码分析
    1. 定义信号稳定性检查属性
    2. 在req有效但gnt无效时检查信号稳定性
    3. 应用于所有地址阶段信号
4.2 原子操作检查
property p_atomic_addr_aligned;
  req ##0 atop |-> addr & (ADDR_ALIGN_MASK) == 0;
endproperty
  • 代码分析
    1. 检查原子操作地址对齐
    2. 使用地址对齐掩码验证
    3. 确保原子操作地址符合规范

5. 总结

该断言模块具有以下特点:

  1. 全面的OBI协议1.2版本检查
  2. 精确的信号稳定性验证
  3. 严格的原子操作监控
  4. 灵活的参数化设计
  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.

// 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内存接口断言模块的包装器实现,主要功能包括:

  1. 连接OBI内存接口到断言模块
  2. 处理不同位宽参数的适配
  3. 支持OBI协议1.2版本
  4. 提供参数化配置能力

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)
);
  • 代码分析
    1. 参数化实例化断言模块
    2. 传递时钟和复位信号
    3. 连接所有总线信号
4.2 信号位宽适配
.aid(obi.aid[EFF_ID_WIDTH-1:0]),
.auser(obi.auser[EFF_AUSER_WIDTH-1:0])
  • 代码分析:使用有效位宽参数截取信号
  • 目的:避免零位宽信号的索引问题

5. 总结

该包装器模块具有以下特点:

  1. 灵活的位宽适配能力
  2. 简洁的接口连接设计
  3. 完善的协议版本支持
  4. 可靠的参数传递机制

作为验证环境的基础组件,它为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内存接口的断言验证模块,主要功能包括:

  1. 验证OBI协议1.1和1.2版本的合规性
  2. 检查地址和数据信号的稳定性
  3. 监控事务ID匹配关系
  4. 确保字节使能信号的正确性

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))
  • 代码分析
    1. 定义地址信号稳定性属性
    2. 在req有效但gnt无效时检查信号稳定性
    3. 生成断言错误信息
4.2 字节使能检查
property p_be_contiguous;
  req ##0 we |-> be_inside_contiguous_be;
endproperty
  • 代码分析
    1. 检查写操作的字节使能连续性
    2. 使用预定义的合法模式匹配
    3. 确保字节使能符合协议要求

5. 总结

该断言模块具有以下特点:

  1. 全面的协议版本支持
  2. 严格的信号稳定性验证
  3. 精确的字节使能检查
  4. 灵活的参数化配置
  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内存接口的常量定义文件,主要功能包括:

  1. 定义默认总线位宽参数
  2. 设置驱动响应延迟范围
  3. 声明内存类型标志位
  4. 提供协议版本控制常量

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;
  • 代码分析
    1. 地址总线默认32位
    2. 数据总线默认32位
    3. 通过宏定义实现灵活配置
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;
  • 代码分析
    1. 固定延迟和随机延迟配合使用
    2. 支持测试场景多样性
    3. 覆盖典型延迟情况

5. 总结

该常量定义文件具有以下特点:

  1. 全面的位宽参数配置
  2. 灵活的延迟控制机制
  3. 清晰的内存属性定义
  4. 标准的宏保护结构

作为验证环境的基础组件,它为OBI内存接口验证提供了统一的参数定义,确保各模块使用一致的配置参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值