IEEE Standard for SystemVerilog—Chapter25.5 Modports

 25.5 Modports

        为了限制模块内的接口访问,有一些modport列表,其中包含在接口内声明的方向。关键字modport表示方向是在模块内部声明的。

interface i2;
    wire a, b, c, d;
    modport master (input a, b, output c, d);
    modport slave (output a, b, input c, d);
endinterface

        在本例中,可以在模块头部中指定modport列表名称(master or slave),其中接口名称选择接口,modport名称为模块头部中访问的接口信号选择适当的方向信息。

module m (i2.master i);
    ...
endmodule

module s (i2.slave i);
    ...
endmodule

module top;
    i2 i();
    m u1(.i(i));
    s u2(.i(i));
endmodule

        interface_name.modport_name reference_name的语法为层次引用提供了一个本地名称。通过编写interface.modport_name reference_name,可以将此技术推广到具有给定modport名称的任何接口。modport列表名称(master or slave)也可以在与模块实例的端口连接中指定,其中modport名称是从接口实例分层的。

module m (i2 i);
    ...
endmodule

module s (i2 i);
    ...
endmodule

module top;
    i2 i();
    m u1(.i(i.master));
    s u2(.i(i.slave));
endmodule

        如果端口连接在模块实例和模块头部声明中都指定了modport列表名称,则这两个modport列表名应相同。modport声明中使用的所有名称应由与modport本身相同的接口声明。特别是,使用的名称不应是由另一个封闭接口声明的名称,modport声明也不应隐式声明新端口。
以下接口声明是非法的:

interface i;
    wire x, y;

        interface illegal_i;
            wire a, b, c, d;
            // x, y not declared by this interface
        modport master(input a, b, x, output c, d, y);

        modport slave(output a, b, x, input c, d, y);
    endinterface : illegal_i
endinterface : i

interface illegal_i;
    // a, b, c, d not declared by this interface
    modport master(input a, b, output c, d);
    modport slave(output a, b, input c, d);
endinterface : illegal_i

        向接口添加modports不需要在使用接口时使用任何modports如果在模块头部或端口连接中没有指定modport,那么接口中的所有网络和变量都可以通过方向inout或ref访问,如前面的示例所示。

25.5.1 Example of named port bundle

        这个接口示例展示了如何使用modports来控制端口声明中的信号方向。它在模块定义中使用modport名称。



interface simple_bus (input logic clk); // Define the interface
	logic req, gnt;
	logic [7:0] addr, data;
	logic [1:0] mode;
	logic start, rdy;
	
modport slave (input req, addr, mode, start, clk,
	output gnt, rdy,
	ref data);
	
	
modport master(input gnt, rdy, clk,
	output req, addr, mode, start,
	ref data);
endinterface: simple_bus


module memMod (simple_bus.slave a); // interface name and modport name
	logic avail;
always @(posedge a.clk) // the clk signal from the interface
	a.gnt <= a.req & avail; // the gnt and req signal in the interface
endmodule

module cpuMod (simple_bus.master b);
	
	always @(posedge b.clk)
		b.start<=1;
	
	
endmodule


module top;
	logic clk = 0;
	simple_bus sb_intf(clk); // Instantiate the interface
	initial repeat(10) #10 clk++;
		memMod mem(.a(sb_intf)); // Connect the interface to the module instance
		cpuMod cpu(.b(sb_intf));
endmodule

25.5.2 Example of connecting port bundle

        这个接口示例展示了如何使用modports来限制接口信号访问并控制其方向。它在模块实例化中使用modport名称。

interface simple_bus (input logic clk); // Define the interface
	logic req, gnt;
	logic [7:0] addr, data;
	logic [1:0] mode;
	logic start, rdy;
	
modport slave (input req, addr, mode, start, clk,
	output gnt, rdy,
	ref data);
	
modport master(input gnt, rdy, clk,
	output req, addr, mode, start,
	ref data);
endinterface: simple_bus

module memMod(simple_bus a); // Uses just the interface name
	logic avail;
always @(posedge a.clk) // the clk signal from the interface
	a.gnt <= a.req & avail; // the gnt and req signal in the interface
endmodule


module cpuMod(simple_bus b);
	...
endmodule

module top;
	logic clk = 0;
	simple_bus sb_intf(clk); // Instantiate the interface
	initial repeat(10) #10 clk++;
		memMod mem(sb_intf.slave); // Connect the modport to the module instance
		cpuMod cpu(sb_intf.master);
endmodule

25.5.3 Example of connecting port bundle to generic interface

        这个接口示例展示了如何使用modports来控制信号方向。它显示了interface关键字在模块定义中的使用。实际接口和modport在模块实例化中指定。

interface simple_bus (input logic clk); // Define the interface
	logic req, gnt;
	logic [7:0] addr, data;
	logic [1:0] mode;
	logic start, rdy;
	
modport slave (input req, addr, mode, start, clk,
	output gnt, rdy,
	ref data);
	
modport master(input gnt, rdy, clk,
	output req, addr, mode, start,
	ref data);
endinterface: simple_bus

module memMod(interface a); // Uses just the interface
	logic avail;
	always @(posedge a.clk) // the clk signal from the interface
		a.gnt <= a.req & avail; // the gnt and req signal in the interface
endmodule

module cpuMod(interface b);
	...
endmodule

module top;
	logic clk = 0;
	simple_bus sb_intf(clk); // Instantiate the interface
	memMod mem(sb_intf.slave); // Connect the modport to the module instance
	cpuMod cpu(sb_intf.master);
endmodule

25.5.4 Modport expressions

        modport表达式允许数组和结构的元素、元素的级联以及接口中声明的元素的赋值形式表达式包含在modport列表中。此modport表达式使用端口标识符显式命名,仅通过modport连接可见。
        与模块端口声明中显式命名的端口一样,端口标识符存在于每个modport列表各自的名称空间中。当modport项只是一个简单的端口标识符时,该标识符既用作接口项的引用,也用作端口标识符。一旦定义了一个端口标识符,就不会有其他具有相同名称的端口定义
        例如:

interface I;
	logic [7:0] r;
	const int x=1;
	bit R;
	
modport A (output .P(r[3:0]), input .Q(x), R);
modport B (output .P(r[7:4]), input .Q(2), R);
endinterface

module M ( interface i);
	initial i.P = i.Q;
endmodule

module top;
	I i1 ();
	M u1 (i1.A);
	M u2 (i1.B);
	initial #1 $display("%b", i1.r); // displays 00100001
endmodule

        端口表达式的自行确定的类型将变为端口的类型。端口表达式不应被视为类似赋值的上下文。端口表达式应解析为模块端口类型的合法表达式(见23.3.3)。在前面的示例中,Q端口不能是output或inout,因为端口表达式是常量。端口表达式是可选的,因为可以定义不连接到端口内部任何内容的端口。

25.5.5 Clocking blocks and modports

        modport构造还可以用于指定接口内声明的clocking块的方向。与其他modport声明一样,clocking块的方向是从接口成为端口的模块中看到的方向。其语法如语法25-2所示。

modport_declaration ::= modport modport_item { , modport_item } ; // from A.2.9
modport_item ::= modport_identifier ( modport_ports_declaration { , modport_ports_declaration } )
modport_ports_declaration ::=
    { attribute_instance } modport_simple_ports_declaration
    | { attribute_instance } modport_tf_ports_declaration
    | { attribute_instance } modport_clocking_declaration
modport_clocking_declaration ::= clocking clocking_identifier

                Syntax 25-2—Modport clocking declaration syntax (excerpt from Annex A)

        modport声明中使用的所有clocking块应由与modport本身相同的接口声明。与所有modport声明一样,时钟信号的方向是从接口成为端口的模块中看到的方向。以下示例显示如何使用modports来创建同步端口和异步端口。当与虚拟接口结合使用时(见25.9.2),这些构造有助于创建抽象同步模型。


interface A_Bus( input logic clk );
	wire req, gnt;
	wire [7:0] addr, data;
	clocking sb @(posedge clk);
		input gnt;
		output req, addr;
		inout data;
		property p1; req ##[1:3] gnt; endproperty
	endclocking

	modport DUT ( input clk, req, addr, // Device under test modport
		output gnt,
		inout data );

	modport STB ( clocking sb ); // synchronous testbench modport
	
	
	modport TB ( input gnt, // asynchronous testbench modport
		output req, addr,
		inout data );
	
endinterface

然后可以如下实例化前面的接口A_Bus:

module dev1(A_Bus.DUT b); // Some device: Part of the design
	...
endmodule

module dev2(A_Bus.DUT b); // Some device: Part of the design
	...
endmodule

module top;
	logic clk;
	A_Bus b1( clk );
	A_Bus b2( clk );
	dev1 d1( b1 );
	dev2 d2( b2 );
	T tb( b1, b2 );
endmodule

program T (A_Bus.STB b1, A_Bus.STB b2 ); // testbench: 2 synchronous ports
	assert property (b1.sb.p1); // assert property from within program
	initial begin
		b1.sb.req <= 1;
		wait( b1.sb.gnt == 1 );
			...
		b1.sb.req <= 0;
		b2.sb.req <= 1;
		
		wait( b2.sb.gnt == 1 );
			...
		b2.sb.req <= 0;
	end
endprogram

        该示例显示了使用由接口端口b1和b2的时钟modport指定的同步接口的程序块。除了程序驱动和时钟块信号的采样之外,程序断言其接口b1之一的属性p1。

25.6 Interfaces and specify blocks

         specify块用于描述模块上的各种路径,并执行时序检查以验证在模块输入处发生的事件满足由模块描述的设备的时序约束。模块路径是从模块输入端口到输出端口,时序检查是相对于模块输入的。 specify块将这些端口称为terminal描述符。模块输入输出端口可以用作输入或输出端口。当其中一个端口实例是接口时,接口中的每个信号都成为可用的终端,默认方向为接口定义或受modport限制。ref端口不能用作指定块中的终端
        以下显示了将接口与指定块一起使用的示例:

interface itf;
	logic c,q,d;
	modport flop (input c,d, output q);
endinterface

module dtype (itf.flop ch);
	always_ff @(posedge ch.c) ch.q <= ch.d;
	specify
		( posedge ch.c => (ch.q+:ch.d)) = (5,6);
		$setup( ch.d, posedge ch.c, 1 );
	endspecify
endmodule

你可能感兴趣的:(Systemverilog,systemverilog)