这篇文章是写arbiter 验证思路,可以借鉴。。。
对于arbiter 验证,目前有了解到几种状况:
1. 可以完全用reference model 来预期golden value;
2. 由于HW比较复杂,需要借助HW internal signal 来判断,比如arbiter 和SRAM 空满强相关,此时就需要借助HW signal.
3. check 时不care各个request拉起来的状况,比如是否同时拉起来(想做成txn level check),进行分段check。即这篇文章的方法(Arbiter驗證方案分享)
第一步:Monitor Arbiter的Input:l1_sch_bsi_data與gc_sch_bsi_data(两路source)。並且分別放入2個queue中,然後分別與Reference model 產生的data序列比較。如果正確,說明Arbiter之前的電路行為復合預期。
第二步:Monitor Arbiter的output,產生一個dut_sch_bsi_data_q[$]。如果收到l1_sch_bsi_ack信號,就將refm_l1_sch_bsi_data往refm_sch_bsi_cw_q[$]裡面放,如果收到gc_sch_bsi_ack,就將refm_gc_sch_bsi_data往refm_sch_bsi_cw_q[$]裡面放。
ps:这一步借助HW 信号ack用于check data经过arbiter是否改变。
第三步:比較refm_sch_bsi_cw_q[$]與dut_sch_bsi_data_q[$]中的序列。如果序列一致,並且Assertion沒有報錯,說明Arbiter的行為正確。
(1)對於Fix Priority Arbiter,如果輸出的是低優先級的ack,那麼高優先級的req必定為低(考量高优先级的req的上升沿与低优先级ack的下降沿同时发生的情况)。
(2)對於Round Robin Priority Arbiter的Check,如果連續兩次sch_req與imm_req同時拉起,那麼每個人都能得到一次ack信號。
---------------------------------------------------------------------------------------------------------------------------------
4. 对于round robin,可以通过对各个request 灌进去相同数据量(而且every source request all the time without delay),统计最终接收的pkt cnt 比例是否满足权重,例如下表
when any source send 10000 packet, all the source will stop send data
source | MCU | DSP | DFE | FFT |
Weight(prio+1) | 4 | 1 | 2 | 4 |
Receive cnt | 9963 | 2490 | 4980 | 9962 |
Receive rate | 4.001205 | 1 | 2 | 4.000803 |
link : Arbiter驗證方案分享
fixed priority checker
property nsrc_fix_priority_arb (ack,req);
@(posedge clk) disable iff(~rst_n)
ack |-> (|req === 'h0);
endproperty
generate
for(genvar i=9;i>0;i--)begin :ARB_SRC
ASS_EVT_CHK:assert property(nsrc_fix_priority_arb(ack_grp[i],req_grp[i-1:0]))
else $error($sformatf("\n [ASS_ERROR]....",...))
round robin
思路:当某一路source req时,arb响应的T数不超过source总数,比如有六路source,arb响应的T数不超过6T.
input [5:0] mem_wr_req;
input [5:0] mem_wr_ack;
reg [7:0] no_ack_cnt[6];
generate
for(genvar i = 0; i < 6; i++) begin : CNT_6SRC_ROB_ARB
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
no_ack_cnt[i] <= 0;
else if(mem_wr_req[i] & ((|mem_wr_ack) & (mem_wr_ack[i] == 1'b0)))
no_ack_cnt[i] <= no_ack_cnt[i] + 1'b1;
else if(mem_wr_req[i] & mem_wr_ack[i])
no_ack_cnt[i] <= 0;
end
end
endgenerate
//For Counter
property rob_6src_arb_check(counter, n);
@(posedge clk) disable iff(!rst_n)
counter < n;
endproperty
//for request states
property rob_6src_arb_req_states_check(req, n);
@(posedge clk) disable iff(!rst_n)
req === n;
endproperty
//for assert counter
generate
for(genvar i = 0; i < 6; i++) begin : MEM_RD_6SRC_ROB_ARB
ASS_CNT: assert property(rob_6src_arb_check(no_ack_cnt[i], 6)) else $error();
end
endgenerate
//for cover counter
generate
for(genvar i = 0; i < 6; i++) begin : COV_MEM_RD_6SRC_ROB_ARB
COV_CNT: cover property(rob_6src_arb_check(no_ack_cnt[i], 6));
end
endgenerate
//for cover request states
generate
for(genvar i = 0; i < 64; i++) begin : COV_MEM_RD_6SRC_ROB_ARB_REQ
cover property(rob_6src_arb_req_states_check(mem_wr_req, i));
end
endgenerate