0. 介绍
之前的这篇文章——UVM——tb0-alu验证平台是居于一个ALU搭建的验证平台,现在希望让这个验证平台能够输出斐波那契数列数列(1,1,2,3,5,8…),利用一种特殊的响应,写一个能够生成斐波那契数列的sequence。
1. 思路
特殊的响应
`uvm_do语句会将transaction通过sequencer发送给driver,`uvm_do执行完之后,它的第一个参数,也就是刚才发送的transaction指针,它不是null,它指向刚才发送的transaction。我们可以在driver驱动接口的时候,把计算的结果保存在transaction中,返回给sequence,这算是一种另类的响应。
2. 实现方法
这样的话,我们可以在transaction类中增加一个变量来保存计算结果,如下:
| class transaction extends uvm_sequence_item;
rand bit[7:0] A; rand bit[7:0] B; rand operation_t op; shortint unsigned result; ..... endclass
|
在driver驱动接口之后,等待加法命令执行完了,我们将计算结果返回给driver驱动的transaction,这个transaction就会传给sequence中的transaction。
在driver中:
1 2 3 4 5 6 7 8 9 10 11
| task driver::run_phase(uvm_phase phase); 22 super.run_phase(phase); 23 `uvm_info("driver","run_phase",UVM_LOW); 24 bfm.reset_alu(); 25 while(1) begin 26 seq_item_port.get_next_item(req); 27 28 bfm.drive_one_pkg(req); 29 seq_item_port.item_done(); 30 end 31 endtask
|
上面的driver的run phase中,先从sequencer中拿到一个transaction——req;然后调用接口中的任务,将transaction的数据按照一定的时序驱动到接口中;驱动完,调用item_done()。
接口中的任务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| interface alu_bfm; ... task drive_one_pkg(transaction tr); if(tr.op == rst_op) begin @(posedge clk); reset_n = 1'b0; start = 1'b0; @(posedge clk); #1; reset_n = 1'b1; end else begin @(negedge clk); op = tr.op; A = tr.A; B = tr.B; start = 1'b1; if(tr.op == no_op) begin @(posedge clk); #1; start = 1'b0; end else begin do @(negedge clk); while(done==0); tr.result = result; start = 1'b0; end end endtask ... endinterface
|
3. fabonacci sequence
所以我们就可以写一个fabonacci sequence,写法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| task pre_body(); if(starting_phase != null) starting_phase.raise_objection(this); `uvm_info("sequence0","pre_body",UVM_LOW) endtask
transaction fab_tr; task body(); shortint unsigned tmp1,tmp2; `uvm_do_with(fab_tr,{fab_tr.A==1;fab_tr.B==1;fab_tr.op==add_op;}); tmp1=1; tmp2=fab_tr.result; repeat(20) begin `uvm_do_with(fab_tr,{fab_tr.A==tmp1;fab_tr.B==tmp2;fab_tr.op==add_op;}); tmp1=fab_tr.B; tmp2=fab_tr.result; end endtask
task post_body(); `uvm_info("sequence0","post_body",UVM_LOW) if(starting_phase != null) starting_phase.drop_objection(this); endtask
|
4. 打印结果
结果如下,这个log是处理过的,只把需要的信息拿出来了,实际中比较乱。
1 2 3 4 5 6 7 8 9 10 11 12
| 33:@ 90000 fabonacci sequence is 2 39:@ 130000 fabonacci sequence is 3 45:@ 170000 fabonacci sequence is 5 51:@ 210000 fabonacci sequence is 8 57:@ 250000 fabonacci sequence is 13 63:@ 290000 fabonacci sequence is 21 69:@ 330000 fabonacci sequence is 34 75:@ 370000 fabonacci sequence is 55 81:@ 410000 fabonacci sequence is 89 87:@ 450000 fabonacci sequence is 144 93:@ 490000 fabonacci sequence is 233 143:@ 530000 fabonacci sequence is 377
|