如何在SV代码中使用interface语法
前言
测试下可综合的interface接口,为了方便未来接口定义的懒惰操作以及减少出错的概率。
综合工具:Vivado2018.3
流程
首先看接口是什么?
顾名思义,用于模块间信号交互的路。是一系列信号组。
想象一辆公交车(bus),分立的信号就是乘客,将乘客封装进bus,就是接口。
对于最简单的使用interface的demo需要三个模块:top,输入,输出。用接口简化输入输出的信号组。
(1)定义interface:interface可以有外界输入信号。通过modport定义不同的接口方向。
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
使用了extern语法,对top层的信号组进行了外界定义,模块定义的时候信号组无需重复申明。
定义interface及用modport指定不同方向,子模块的方向根据modport指定。
interface的实例,如果没有外界信号送入,则为空,这里有时钟和复位送入。
genafic产生interface的输出信号送入到test模块中。
注意:bus的连接通过interface的实例加modport的名称指定。
extern module demo_sv (
input i_clk ,
input i_rst_n ,
input i_a ,
output o_b
);
///子层模块定义
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
module demo_sv (.*);
f_bus1 inst_f_bus1 (
.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内部信号的方式进行使用。
module genafic (
interface 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
同样定义interface,使用一样。
module test (
interface 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
好处就是:如果interface内部信号发生更改,无需修改模块间例化的部分,降低工作量。
以上。