前言:当拿到寄存器模型和总线后,就要实现总线适配器,这就是集成的过程。
接下来需要考虑选择与DUT寄存器接口一致的总线UVC, 该UVC会提供硬件级别的访问方式。 要完成一次硬件级别的总线传输, 往往需要考虑给出地址、 数据队列、 访问方式等, 而寄存器模型可以使得硬件级别的抽象级上升到寄存器级别。由此带来最直观的好处在于, 以往由具体地址来指定寄存器的方式, 将由寄存器名称来替代, 同时寄存器模型封装的一些函数使得可以对域做直接操作,这一升级使得转变后的测试序列更易读。 而伴随着项目变化, 无论寄存器基地址如何变化, 寄存器级别实现的配置序列都要比硬件级别的序列具备更好的维护性。

从激励的流向来看, 寄存器序列(而不是总线序列)将带有目标寄存器的相关信息存放到uvm_reg_item实例中, 送往adapter。
adapter在接收到uvm_reg_item之后, 从中抽取出总线UVC所需的信息 , 同时生成总线UVC需要的bus_seq_item类型。 在完成了数据内容抽取和二次写入之后,bus_seq_item由adapter送往总线UVC。
总线UVC从bus_seq _item获取地址、 数据、 操作模式等信息之后发起总线的读写访问 。如果总线上有反馈信号标示访问是否成功,则该标示应当由总线sequencer按照response item的路径返回至adapter,adapter也应对该反馈信号做出处理。这一反馈路径在读访问时也会将总线读回的数据返同至adapter, 并最终作为返回值交回到与寄存器操作有关的方法。

总线UVC的实现
MCDF访问寄存器的总线接口时序较为简单。控制寄存器接口首先需要在每一个时钟解析cmd。
- 当cmd为写指令时,即需要把数据cmd_data_in写入到cmd_addr对应的寄存器中。
- 当cmd为读指令时,即需要从cmd_addr对应的寄存器中读取数据,在下一个周期,cmd_addr对应的寄存器数据被输送至cmd_data_out接口。
总线UVC示例
下面是一段8位地址线,32位数据线的总线UVC实现代码。
class mcdf_bus_trans extends uvm_sequence_item;
rand bit[1:0]cmd;
rand bit[7:0] addr;
rand bit[31:0] wdata;
bit[31:0]rdata;
`uvm_object_utils_begin(mcdf_bus_trans)
...
`uvm_object_utils_end
endclass
class mcdf_bus_sequencer extends uvm_sequencer;
virtual mcdf_if vif;
`uvm_component_utils(mcdf_bus_sequencer)
...
function void build_phase(uvm_phase phase);
if(!uvm_config_db#(virtual_mcdf_if)::get(this,"","vif",vif))begin;
`uvm_error("GETVIE","no virtual interface is assigned")
end
endfunction
endclass
class mcdf_bus_monitor extends uvm_monitor;
virtual mcdf_if vif;
uvm_analysis_port#(mcdf_bus_trans) ap;
`uvm_component_utils(mcdf_bus_monitor)
...
function void build_phase(uvm_phase phase);
if(!uvm_config_db#(virtual mcdf_if)::get(this,"","vif",vif))begin
`uvm_error("GETVIF","no virtual interface is assigned")
end
ap=new("ap",this);
endfunction
task run_phase(uvm_phase phase);
forever begin
mon_trans();
end
endtask
task mon_trans();
mcdf_bus_trans t;
@(posedge vif.clk);
if(vif.cmd==WRITE) begin
t=new();
t.cmd=WRITE;
t.addr=vif.addr;
t.wdata=vif.wdata;
ap.write(t);
end
else if(vif.cmd==READ) begin
t=new();
t.cmd=READ;
t.addr=vif.addr;
fork
begin
@(posedge vif.clk);
#10ps;
t.rdata=vif.rdata;
ap.write(t);
end
join_none
end
endtask
endclass: mcdf_bus_monitor
class mcdf_bus_driver extends uvm_driver;
virtual mcdf_if vif;
`uvm_component_utils(mcdf_bus_driver)
...
function void build_phase(uvm_phase phase

最低0.47元/天 解锁文章
1403

被折叠的 条评论
为什么被折叠?



