SystemVerilog中使用generate語句實現Interface批量連線
---UVM中連線和set interface的技巧
前言:在前文(Link)中我們談過generate語句在Verilog中的用法及案例,本文將詳細介紹generate在Testbench中的使用。通過引入generate,將大大減少連線或者set interface的工作量,從而避免一些低級的錯誤。
一、應用場景
- 假如我們需要4個ckdly_agent,那麼我們應該在env中例化4份,並且要在top層中給每個agent都set interface,並且連線
1.1、在env中例化ckdly_agent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class ckdly_env extends uvm_env; ckdly_agent ckdly_agent_inst[4]; `uvm_component_utils(ckdly_env) endclass : ckdly_env function void ckdly_env::build_phase(uvm_phase phase); super.build_phase(phase); foreach(ckdly_agent_inst[i]) begin ckdly_agent_inst[i] = ckdly_agent::type_id::create($sformatf("ckdly_agent_inst[%0d]", i), this); ckdly_agent_inst[i].is_active = UVM_PASSIVE; //不需要例化driver和sequencer end endfunction : build_phase |
- 注意create方法中的$sformatf()函數,方括號裡面的佔位符一定不能寫成循環變量i,否則會在simulation中出現找不到agent實例的問題
- 在agent中通過枚舉類型的變量is_active = {UVM_ACTIVE, UVM_PASSIVE}來控制是否create driver和sequencer,如果是UVM_PASSIVE,就只創建Monitor
1.2、在top中使用generate循環連線并完成set interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | module top(); logic digrf_sys_clk[4]; //假設每個bit所代表的Clock的frequency不同 logic digrf_sys_rst_n[1]; // generate for(genvar i = 0; i < 4; i = i + 1) begin : dl_ckdly_intf ckdly_if ckdly_vif(.clk_ck(digrf_sys_clk[i]), .rst_n(digrf_sys_rst_n[0])); assign dl_ckdly_intf[i].ckdly_vif.da_resync = top.u_serdes.u_l1_top.u_phya.da_resync; assign dl_ckdly_intf[i].ckdly_vif.da_rstdly = top.u_serdes.u_l1_top.u_phya.da_rstdly; initial begin uvm_config_db#(virtual ckdly_if.mon)::set(uvm_root::get(), $sformatf("uvm_test_top.top_env.dl_env.cal_ckdly_inst[%0d]", i), "mon_vif", dl_ckdly_intf[i].ckdly_vif.mon); end end endgenerate endmodule |
1.3、案例詳解
- 注意上面的assign語句,左值一定要指明Hierarchy,如上面的例子,給信號賦值時是帶著Hera仍處於的: assign dl_ckdly_intf[i].ckdly_vif.da_resync = top.u_serdes.u_l1_top.u_phya.da_resync;
- 注意uvm_config_db中的set方法,其中的第四個參數(需要set的value)也需要帶上Hierarchy:dl_ckdly_intf[i].ckdly_vif.mon
- 上面的generate for語句的作用是generate 4個層次,每一層都會有一個ckdly_vif Interface
二、generate用二重循環的例子
2.1、應用場景
- 假如現在有6個sub_env,在top_env中會例化這6個sub_env
2.2、top中連線的實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | module top(); logic digrf_syc_clk[5]; logic digrf_reset_n[5]; generate for(genvar i = 0; i < 6; i = i + 1) begin : clk_i_intf for(genvar j = 0; j < 6; j = j + 1) begin : clk_j_intf clk_if sys_clk_vif(.clk(digrf_syc_clk[i][j])); initial begin : set_digrf_clk_intf uvm_config_db#(virtual clk_if.mst)::set(uvm_root::get(), $sformatf("uvm_test_top.top_env.slv_env[%0d].clk_agent_inst[%0d]*", i, j), "vif", clk_i_intf[i].clk_j_intf[j].sys_clk_vif); end end end endgenerate endmodule |
- 如上面的例子,第一層for循環,創建了Hierarchy:clk_i_intf,主要用於Maping不同的sub_env
- 第二層for循環創建了Hierarchy:clk_j_intf,主要是對應於不同的Clock frequency
2.3、總結
- Interface的聲明要放在generate for裡面
- set interface要用initial begin end包起來,也放在generate for裡面
- initial begin end中不能放assign語句
- 採用generate for begin之後,Hierarchy將發生變化,無論是assign還是set,在對generate for begin下面的變量做操作是都要帶上Hierarchy --- 即begin之後的label