代码分享,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