systemverilog接口

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了systemverilog接口相关的知识,希望对你有一定的参考价值。

在verilog中每当遇到复杂的模块时,我们都不得不书写一长串端口声明,

稍有不慎就会写错,并且难以检查。但在systemverilog中,接口interface

则是避免了这个问题。

下面的代码是对一个一位加法器的验证,使用了接口。

`timescale 1ns / 1ps
interface if_port( input bit clk );     //   声明接口
  logic a , b , cin , sum ,cout ;      //   声明所有的连接线
  
  clocking [email protected](posedge clk);           //    声明在同一个时钟变化下,连接线的方向。  
    output a , b, cin ;
  endclocking
  
  clocking [email protected](posedge clk);
    input a , b , cin , sum ,cout;
  endclocking
  
  modport simulus(clocking cp);      //   声明端口的输入与输出
  modport adder( input a , b , cin , output sum ,cout );
  modport monitor(clocking cn);
endinterface

module simulus(if_port.simulus port);   //    使用接口的激励模块
  
  [email protected](port.cp) begin
    port.cp.a <= $radnom()%2 ;
    port.cp.b <= $random()%2 ;
    port.cp.cin <= $random()%2 ;
  end
endmodule:simulus

module adder(if_port.adder port);       //     一位加法器
  assign { port.cout , port.sum } = port.a + port.b + port.cin ;
endmodule:adder

module monitor(if_port.monitor mon);    //       监测模块,在时钟的下降沿打印结果
  [email protected]( mon.cn )begin
    $display(" %d %d %d %d  %d ",mon.cn.a , mon.cn.b , mon.cn.cin , mon.cn.cout , mon.cn.sum );
  end
endmodule

module top;
  timeunit 1ns ;
  timeprecision 1ps ;      //    模块内部的时钟情况
  bit clk ;
  
  if_port port(clk);           //    实例化所有模块,并且连接接口
  simulus sim(port.simulus);
  adder add(port.adder);
  monitor mon(port.monitor);
  
  initial begin
    clk <= 0 ;                  //   时钟的生成
    while(1) #10 clk = ~clk ;
  end
  
endmodule

相信由这个例子,大家可以看出接口的使用方法。尽管在这个例子中接口的使用比较繁琐,

但在一个较大型的模块中时,使用接口绝对是最佳的方式。


在接口中还有一种叫做虚接口,虚接口是接口的一个句柄,可以同过虚接口来操作接口成员的值。

下面就看看IEEE sv标准中的例子。

interface  SBus;    // A Simple bus interface    
    logic  req, grant;    
    logic [7:0] addr, data;
endinterface

class    SBusTransctor;   // SBus transactor class    
    virtual SBus bus;    // virtual interface of type Sbus  
      
    function new( virtual SBus s );                
        bus = s;    // initialize the virtual interface    
    endfunction
    
   task request();  // request the bus                
       bus.req <= 1'b1;    
   endtask
   
   task wait_for_bus(); // wait for the bus to be granted                
       @(posedge bus.grant);    
   endtask
endclass

module  devA( Sbus s ) ... 
endmodule    // devices that use SBus
module  devB( Sbus s ) ... 
endmodule

module  top;    
       SBus s[1:4] ();  // instantiate 4 interfaces
    devA a1( s[1] );  // instantiate 4 devices    
    devB b1( s[2] );    
    devA a2( s[3] );    
    devB b2( s[4] );    
    
    initial begin            
        SbusTransactor t[1:4];  // create 4 bus-transactors and bind            
        t[1] = new( s[1] );            
        t[2] = new( s[2] );            
        t[3] = new( s[3] );            
        t[4] = new( s[4] );            
        // test t[1:4]        
endendmodule

可以看出接口与模块还是以实例化的方式相互连接,但在激励上使用了类与虚接口来进行实现。

这样在书写激励时可以动态的修改激励,并且在一定程度上增进了代码的复用程度。

以上是关于systemverilog接口的主要内容,如果未能解决你的问题,请参考以下文章

在系统verilog接口内声明的包

求systemverilog vimrc 高亮方法(要代码)

SystemVerilog 采样和数据驱动

凿子中的systemverilog联合类型

icarus 的 SystemVerilog 支持(iverilog 编译器)

在 systemverilog 中正确使用“禁用分叉”