I. Introduction
In the systemverilog
middle there is a very useful feature, that is interface
. When I wrote a small exercise recently, I not only used it , but interface
also interface
used it modport
, but there was a problem with the initialization at the beginning, so here is something to pay attention to.
Here is an example, this example mainly shows:
- How
module
to call ininterface
- How
testbench
to correctly instantiate the sum ininterface
andmodule
pass in the signal correspondingtestbench
tomodule
the input and output signals defined inmodule
The code function is not important, and there are some problems with my code design, I will not change the emmm! ! !
2. Examples
1. RTL code
interface ticket_if(input logic clk,rst_n,[5:0]m_in,output logic ticket_out,[5:0]m_out);
logic [5:0]sum;
task change(input logic [5:0]in_data,
output logic [5:0]out_data );
out_data = in_data - 6;
endtask //automatic
modport ticket_ports(input clk,rst_n,m_in,
output ticket_out,m_out,sum,
import task change(input logic [5:0]in_data,
output logic [5:0]out_data )
);
endinterface //interfacename
module ticket(ticket_if.ticket_ports ports);
enum logic [1:0]{
s0,s1,s2} state_c,state_n;
always_ff @(posedge ports.clk or negedge ports.rst_n)
if(!ports.rst_n)
state_c <= s0;
else
state_c <= state_n;
always_comb
case(state_c)
s0:begin
ports.sum = ports.m_in;
ports.ticket_out = 0;
if(ports.sum>=6)
state_n <= s2;
else
state_n <= s1;
end
s1:begin
ports.sum = ports.sum + ports.m_in;
if(ports.sum>=6)
state_n <= s2;
else
state_n <= state_c;
end
s2:begin
ports.change(ports.sum,ports.m_out);
//ports.m_out = ports.sum - 6;
ports.ticket_out = 1;
state_n <= s0;
end
default:state_n <= s0;
endcase
endmodule
2. Simulation code
module tb_ticket;
timeunit 1ns;
timeprecision 100ps;
logic clk,rst_n;
logic [5:0]m_in;
logic ticket_out;
logic [5:0]m_out;
initial
begin
clk = 0;
rst_n = '1;
#5 rst_n = '0;
#5 rst_n = '1;
end
initial
begin
#10 m_in=2;
#10 m_in=3;
#10 m_in=4;
#10 m_in=5;
#10 m_in=6;
#10 m_in=7;
#10 m_in=8;
end
always #5 clk = ~clk;
//ticket_if ports(.*);如果信号名称一样,你也可以直接按照这种方式来例化
ticket_if ports(.clk(clk),.rst_n(rst_n),.m_in(m_in),.ticket_out(ticket_out),.m_out(m_out));
ticket u_ticket(ports.ticket_ports);
endmodule
Three, matters needing attention
1. It should be noted that when we instantiate, we can only interface
instantiate the pair , not directly modport
. The reason for saying this is because what we are module
passing in is ticket_if.ticket_ports
that this is a modport
type, so we may want to instantiate an object of that type directly and pass it to it u_ticket
, but this will not work.
2, so we must first instantiate an interface
object type ports
, and will testbench
pass the input and output signals are defined ports
, then after the modport
type of ports.ticket_ports
pass module
type of the object u_ticket
can be. But what needs to be noted here is that in the RTL
code, we must declare module
the input and output signals used in interface
the port in the port, because only in this way can testbench
these signals be allowed to be passed to ports
. Otherwise, we will not be able to pass input and output signals, then we will not be able to drive the test module
to complete the simulation.
3. After interface
the input and output signals are declared in the port, we only need to modport
write the signal you want to put in modport
. The reason for this modport
is that one interface
may be called multiple times module
. If you want to isolate the module
different signals between these , you can module
add one for each one modport
to "wrap" only a certain one module
, as in the example. signal. Some common signals you can put interface
in the modport
outside.
In short, in order to correctly transmit the drive signals during instantiation module
, you need to interface
declare the ports where these signals are located .