构建测试case中常需要一些重复性的工作,有些可以用函数或者任务完成(也可以将两者结合起来,在函数和任务中定义并调用宏),比如产生驱动。有些需要宏定义来完成,比如在PCIE的测试中需要大量发包,而且面对很多个端口,在随机发包测试时可以通过使用宏定义来定义一次约束,通过不同端口的调用来完成对所用端口的约束。
代码如下:
rand bit[63:0] pt0_mem_address,pt1_mem_address,
pt2_mem_address,pt3_mem_address;
rand bit[9:0] pt0_len,pt1_len,pt2_len,pt3_len;
rand bit[3:0] pt0_fsb,pt1_fsb,pt2_fsb,pt3_fsb;
rand bit[3:0] pt0_lsb,pt1_lsb,pt2_lsb,pt3_lsb;
`define CONSTRAINT(mc_num) \
constraint pt``mc_num``_cn{
pt``mc_num``_mem_address inside {[32'h1_000:32'h1_0ff]} \
pt``mc_num``_len inside {[1:512]} \
// PCIE 包长len单位DW 最大包长4KB,即512DW
pt``mc_num``_mem_address[11:0] + 4*pt``mc_num``_len < 4096 \
//同样是约束TLP 4K越界的,其实和上面约束重复
if(pt``mc_num``_len==1){ \
pt``mc_num``_mc_fsb inside {[1:15]};\
pt``mc_num``_mc_lsb inside==0; \
} \
else { \
pt``mc_num``_mc_fsb inside {8,12,14,15};\
pt``mc_num``_mc_lsb inside {7,3,1,15}; \
} \
} \
`CONSTRAINT(0)
`CONSTRAINT(1)
`CONSTRAINT(2)
`CONSTRAINT(3)
需要注意的是:
1.宏定义后的换行符 \ 必须要有,而且\后边不能有字符,包括空格,否则会编译报错。
2.参数可以按需要添加多个。
3.可以添加相应注释。