SV中interface使用

SV中Interface使用

前言

大型IC设计中,模块中信号数量众多,不仅使用和修改麻烦,而且很难保证在信号连接中不出问题,因此systemverlog中interface出现啦!
既然写端口信号十分麻烦,那就单独为信号创建一个interface模块,然后在其他模块中例化,一旦信号名称和数量需要修改,也不必在顶层修改,只需要修改interface模块就可以。
理解interface,重点在interface只涉及模块之间共有的信号,独有的信号是没有的!

例程

下面是一个例程,方便理解interface使用方法(本例程来自一篇博客,清晰明了,稍作修改,链接在文末)

//top module 
module demo_sv (
    input     i_clk       ,
    input     i_rst_n     ,
    input     i_a         ,
    output    o_b                    
);

f_bus1 inst_f_bus1 (           //模块也可以写成   f_bus1  inst_f_bus1 (i_clk,i_rst_n);但是这种写法要注意名字顺序
    .i_clk      (i_clk),
    .i_rst_n    (i_rst_n)
);

genafic  inst_genafic (
    .f_bus1            (inst_f_bus1.master),   
    .i_a               (i_a)
);

test  inst_test (
    .f_bus1            (inst_f_bus1.slave),   
    .o_b               (o_b)
);

endmodule

//interface   子模块
interface f_bus1(input logic i_clk,i_rst_n);
    logic l_ready;
    logic l_valid;
    logic [7:0] l_cnt;
    modport master(input i_clk,i_rst_n,
                   output l_ready,l_valid,l_cnt);
    modport slave (input i_clk,i_rst_n,
                   input  l_ready,l_valid,l_cnt);
endinterface //f_bus1

// genafic 子模块
module genafic (
     interface f_bus1,         //也可以写成 f_bus1.mater  f_bus1
     input     i_a           
);
logic [7:0] l_cnt = '0;
always_ff @(posedge f_bus1.i_clk)
begin
    if (f_bus1.i_rst_n)
        l_cnt <= '0;
    else if (i_a)
        l_cnt <= l_cnt + 'd1;
end
assign f_bus1.l_ready = l_cnt[0];
assign f_bus1.l_valid = l_cnt[1];
assign f_bus1.l_cnt   = l_cnt;

endmodule:genafic

//test 子模块
module test (
    interface f_bus1,      //也可以写成 f_bus1.slave  f_bus1
    output o_b

);
logic l_b = '0;
always_ff @(posedge f_bus1.i_clk)
begin
    if (f_bus1.i_rst_n)
        l_b <= '0;
    else if (!f_bus1.l_ready && f_bus1.l_valid)
    begin
        if (f_bus1.l_cnt == 'd10)
            l_b <= 1'b1;
        else 
            l_b <= 1'b0;
    end    
end
assign o_b = l_b;
endmodule:test

例程二 ,模块不完整,仅用开来介绍模块例化时,端口信号写法

module tb;
	wr_if m_wr_if();                //没有输入量
	dut m_dut(m_wr_if);             // 接口信号简化写法
	reg clk_tb,rst_n;
	logic[31:0]addr,data;
	logic valid ,ready;
	assign m_wr_if.clk = clk_tb;
	assign m_wr_if.rst_n = rst_n;
	initial
	begin
		clk_tb = 0;
		forever
		# 5 clk_tb = ~clk_tb;
	end
	initial
	begin
		rst_n = 1;
		repeat(2)@(m_wr_if.cb);
		#2ns
		rst_n = 0;
		repeat(2)@(m_wr_if.cb);
		#2ns
		rst_n = 1;
	end
endmodule:tb

module dut(wr_if m_if);   // m_if 可以不与tb中接口例化时名称m_wr_if相同,类似形参与实参
	reg[31:0]wr_ready;
	reg 		 wr_ready;
	assign wr_ready = 1;
	assign m_if.wr_ready=1;
	always@(posedge m_if.clk ,negedge m_if.rst_n)
	begin
		if(m_if.rst_n == 1'b0)
		begin
			foreach (reg_map[i])
				reg_map[i] = 0;
		end
		else if(m_if.wr_valid && wr_ready)
		begin
			reg_map[m_if.wr_addr%10] = m_if.wr_data;
			$display("@ %0t ns, wr data[%0d] = 'h%h", $time,m_if.wr_addr%10,m_if.wr_data);
		end
	end
endmodule:dut

interface wr_if();
	logic clk;
	logic rst_n;
	logic[31:0] wr_addr;
	logic[31:0]wr_data;
	logic			wr_valid;
	logic   		wr_ready;
	clocking cb @(posedge clk);
		default input #1ns output #1ns;
		output wr_addr;
		output wr_data;
		output wr_valid;
		input wr_ready;
	endclocking
endinterface :wr_if

参考文章

1.如何在SV代码中使用interface语法
2.【SV教程】19. 时钟控制块(clocking block)

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值