axi4协议接口信号 constraint 相关

代码分享,axi4的约束,能力有限,可能存在不符合协议的情况待查。常用trans基本可以hold住。

axi4 相关变量:

// write / read common info
rand bit [2:0] xact_type  ; //0:read;1:write
rand bit [3:0] burst_size ; // 0~8
rand bit [1:0] burst_type ; //0: fixed; 1: incr; 2:wrap
rand bit [1:0] atomic_type; //0:normal; 1:exclusive;
rand bit [`SVT_AXI_MAX_BURST_LENGTH_WIDTH :0] burst_length;
rand bit [`SVT_AXI_MAX_ADDR_USER_WIDTH - 1:0] addr_user; 
rand bit [`SVT_AXI_MAX_ADDR_WIDTH - 1     :0] addr;
rand bit [`SVT_AXI_MAX_CACHE_WIDTH -1     :0] cache_type;
rand bit [`SVT_AXI_MAX_ID_WIDTH -1        :0] id;

// write info
rand bit [`SVT_AXI_MAX_WSTRB_WIDTH - 1 : 0] wstrb;
rand bit [`SVT_AXI_MAX_DATA_WIDTH  - 1 : 0] data;

// value for calucate
rand bit [13:0] addr_range;
rand bit [`SVT_AXI_MAX_ADDR_WIDTH - 1 :0] addr_mask;
int strb_str_flag[];
int strb_end_flag[];
rand bit aligned_addr_flag;
bit [`SVT_AXI_MAX_ADDR_WIDTH - 1 :0] max_possible_addr;
int log_2_byte_width; // for max burst_size


constraint:

constraint axi_info_constraint{
  // solve order
  solve xact_type before burst_type;
  solve xact_type before burst_type;
  solve atomic_type before burst_length;
  solve burst_type before burst_length;
  solve burst_length before wstrb;
  solve burst_size before addr;
  solve burst_type before addr;
  solve atomic_type before addr;
  solve xact_type before wstrb; 
  solve burst_length before data;
  solve xact_type before data;
  solve burst_size before data;
  solve addr_mask before addr;
  solve aligned_addr_flag before addr;

  xact_type inside {0,1};
  burst_type inside {0,1,2};
  atomic_type inside {0,1};
  burst_size inside {[0:log_2_byte_width]};
  
  if(burst_type == 2) {
    burst_length inside {2,4,8,16};
  } else if (burst_type == 0) {
    burst_length inside {[1:16]};
  } else {
    burst_length inside {[1:256]};
  }
  (burst_length << burst_size) <= (1<<12); // total_size <= 4096
  if(xact_type == 0) {
    wstrb.size() == 0;
    data.size() == burst_length;
  } else if(xact_type == 0) {
    wstrb.size() == burst_length;
    data.size() == burst_length;
  }
  if(burst_type != 0) {
    addr_range == (burst_length << burst_size);
    if(burst_type == 2) {
      if(burst_length == 2) 
        addr_mask == ({`SVT_AXI_MAX_ADDR_WIDTH{1'b1}} << (burst_size+1));
      else if(burst_length == 4) 
        addr_mask == ({`SVT_AXI_MAX_ADDR_WIDTH{1'b1}} << (burst_size+2));
      else if(burst_length == 8) 
        addr_mask == ({`SVT_AXI_MAX_ADDR_WIDTH{1'b1}} << (burst_size+3));
      else if(burst_length == 16) 
        addr_mask == ({`SVT_AXI_MAX_ADDR_WIDTH{1'b1}} << (burst_size+4));
      addr == (addr & addr_mask);
      (addr & addr_mask) + addr_range - 1 <= max_possible_addr;
      (addr[12-1:0] & addr_mask) <= ((1<<12) - addr_range);
    } else {
      // incr
      addr_mask == ({`SVT_AXI_MAX_ADDR_WIDTH{1'b1}} << burst_size);
      (addr[12-1:0] & addr_mask) <= ((1<<12) - addr_range);
      ((addr >> burst_size) << burst_size) + addr_range -1 <= max_possible_addr;
      if(aligned_addr_flag) addr == (addr & addr_mask);
    }
  }
  //exclusive 
  if(atomic_type == 1) {
    burst_length <= 16;
    cache_type[3:2] == 0;
    addr_mask == ({`SVT_AXI_MAX_ADDR_WIDTH{1'b1}} << log_2_byte_width);
    addr == (addr & addr_mask);
    (burst_length << burst_size) inside {1,2,4,8,16,32,64,128};
  } 
  //else {
  //}
  (cache_type[1] == 0) -> (cache_type[3] == 0);
   cache_type != 4'b0100;
   cache_type != 4'b0101;
   cache_type != 4'b1000;
   cache_type != 4'b1001;
   cache_type != 4'b1100;
   cache_type != 4'b1101;
}

pre_randomize

//因为在seq中可以get到port的设置,transaction也可以取得seq中的port设置
max_possible_addr = {cfg.addr_width{1'b1}};
log_2_byte_width = $clog2(cfg.addr_width);

post_randomize

//calculate wstrb

bit [`SVT_AXI_WSTRB_WIDTH-1:0] wstrb_mask;
strb_str_flag = new[burst_length];
strb_end_flag = new[burst_length];
if(xact_type==1) begin
  if(burst_type != 0) begin 
    //incr wrap
    foreach(strb_str_flag[i]) begin
      if(i==0) strb_str_flag[i] = addr & {log_2_byte_width{1'b1}};
      else     strb_str_flag[i] = (strb_end_flag[i-1]+1) & {log_2_byte_width{1'b1}};
      if(i==0) strb_end_flag[i] = ((addr>>burst_size<<burst_size)+(1<<burst_size)-1) & {log_2_byte_width{1'b1}};
      else     strb_end_flag[i] = (strb_end_flag[i-1]+(1<<burst_size)) & {log_2_byte_width{1'b1}};
    end
  end else begin
    // fixed
    foreach(strb_str_flag[i]) begin
      strb_str_flag[i] = addr & {log_2_byte_width{1'b1}};
      strb_end_flag[i] = ((addr>>burst_size<<burst_size)+(1<<burst_size)-1) & {log_2_byte_width{1'b1}};
    end
  end
  foreach(wstrb[i]) begin
    wstrb_mask = ({`SVT_AXI_WSTRB_WIDTH{1'b1}} << (`SVT_AXI_WSTRB_WIDTH-1-strb_end_flag[i]) >> (`SVT_AXI_WSTRB_WIDTH-1-strb_end_flag[i])) >>strb_str_flag[i]<<strb_str_flag[i];
    wstrb[i] = wstrb[i]&wstrb_mask;
  end
end

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值