SystemVerilog Modports

Modports in SystemVerilog are used to restrict interface access within a interface. The keyword modport indicates that the directions are declared as if inside the module.

Modports can have

  • input : Ports that need to be input.
  • output : Ports that need to be output.
  • inout : Ports that need to be inout
  • ref : Ports that need to be ref.

Few of the examples usages of modports are, we can have interface file for

memory controller where, we can have

  • Modports for memory
  • Modports for system side
  • Modports for testbench

Adding modports to an interface does not require that any of the modports be used when the interface is used. If no modport is specified in the module header or in the port connection, then all the nets and variables in the interface are accessible with direction inout or ref, Below example shows this in greater detail.

 //+++++++++++++++++++++++++++++++++++++++++++++++++
// Define the interface
//+++++++++++++++++++++++++++++++++++++++++++++++++
interface mem_if (input wire clk);
logic reset;
logic we_sys;
logic cmd_valid_sys;
logic ready_sys;
logic [7:0] data_sys;
logic [7:0] addr_sys;
logic we_mem;
logic ce_mem;
logic [7:0] datao_mem;
logic [7:0] datai_mem;
logic [7:0] addr_mem;
//=================================================
//
Modport for System interface
//=================================================
modport system (input clk,reset,we_sys, cmd_valid_sys,
addr_sys, datao_mem,
output we_mem, ce_mem, addr_mem,
datai_mem, ready_sys, ref data_sys);
//=================================================
// Modport for memory interface
//=================================================
modport memory (input clk,reset,we_mem, ce_mem,
addr_mem, datai_mem, output datao_mem);
//=================================================
// Modport for testbench
//=================================================
modport tb (input clk, ready_sys,
output reset,we_sys, cmd_valid_sys, addr_sys,
ref data_sys);

endinterface

//+++++++++++++++++++++++++++++++++++++++++++++++++
// Memory Model
//+++++++++++++++++++++++++++++++++++++++++++++++++
module memory_model (mem_if.memory mif);
// Memory array
logic [7:0] mem [0:255];

//=================================================
// Write Logic
//=================================================
always @ (posedge mif.clk)
if (mif.ce_mem && mif.we_mem) begin
mem[mif.addr_mem] <= mif.datai_mem;
end

//=================================================
// Read Logic
//=================================================
always @ (posedge mif.clk)
if (mif.ce_mem && ~mif.we_mem) begin
mif.datao_mem <= mem[mif.addr_mem];
end

endmodule

//+++++++++++++++++++++++++++++++++++++++++++++++++
// Memory Controller
//+++++++++++++++++++++++++++++++++++++++++++++++++
module memory_ctrl (mem_if.system sif);

typedef enum {IDLE,WRITE,READ,DONE} fsm_t;

fsm_t state;

always @ (posedge sif.clk)
if (sif.reset) begin
state <= IDLE;
sif.ready_sys <= 0;
sif.we_mem <= 0;
sif.ce_mem <= 0;
sif.addr_mem <= 0;
sif.datai_mem <= 0;
sif.data_sys <= 8'bz;
end else begin
case(state)
IDLE : begin
sif.ready_sys <= 1'b0;
if (sif.cmd_valid_sys && sif.we_sys) begin
sif.addr_mem <= sif.addr_sys;
sif.datai_mem <= sif.data_sys;
sif.we_mem <= 1'b1;
sif.ce_mem <= 1'b1;
state <= WRITE;
end
if (sif.cmd_valid_sys && ~sif.we_sys) begin
sif.addr_mem <= sif.addr_sys;
sif.datai_mem <= sif.data_sys;
sif.we_mem <= 1'b0;
sif.ce_mem <= 1'b1;
state <= READ;
end
end
WRITE : begin
sif.ready_sys <= 1'b1;
if (~sif.cmd_valid_sys) begin
sif.addr_mem <= 8'b0;
sif.datai_mem <= 8'b0;
sif.we_mem <= 1'b0;
sif.ce_mem <= 1'b0;
state <= IDLE;
end
end
READ : begin
sif.ready_sys <= 1'b1;
sif.data_sys <= sif.datao_mem;
if (~sif.cmd_valid_sys) begin
sif.addr_mem <= 8'b0;
sif.datai_mem <= 8'b0;
sif.we_mem <= 1'b0;
sif.ce_mem <= 1'b0;
sif.ready_sys <= 1'b1;
state <= IDLE;
sif.data_sys <= 8'bz;
end
end
endcase
end

endmodule

//+++++++++++++++++++++++++++++++++++++++++++++++++
// Test program
//+++++++++++++++++++++++++++++++++++++++++++++++++
program test(mem_if.tb tif);

initial begin
tif.reset <= 1;
tif.we_sys <= 0;
tif.cmd_valid_sys <= 0;
tif.addr_sys <= 0;
tif.data_sys <= 8'bz;
#100 tif.reset <= 0;
for (int i = 0; i < 4; i ++) begin
@ (posedge tif.clk);
tif.addr_sys <= i;
tif.data_sys <= $random;
tif.cmd_valid_sys <= 1;
tif.we_sys <= 1;
@ (posedge tif.ready_sys);
$display("@%0dns Writing address %0d with data %0x",
$time, i,tif.data_sys);
@ (posedge tif.clk);
tif.addr_sys <= 0;
tif.data_sys <= 8'bz;
tif.cmd_valid_sys <= 0;
tif.we_sys <= 0;
end
repeat (10) @ (posedge tif.clk);
for (int i= 0; i < 4; i ++) begin
@ (posedge tif.clk);
tif.addr_sys <= i;
tif.cmd_valid_sys <= 1;
tif.we_sys <= 0;
@ (posedge tif.ready_sys);
@ (posedge tif.clk);
$display("@%0dns Reading address %0d, Got data %0x",
$time, i,tif.data_sys);
tif.addr_sys <= 0;
tif.cmd_valid_sys <= 0;
end
#10 $finish;
end

endprogram

//+++++++++++++++++++++++++++++++++++++++++++++++++
// Testbench
//+++++++++++++++++++++++++++++++++++++++++++++++++
module interface_modports();

logic clk = 0;
always #10 clk++;
//=================================================
// Instianciate Interface and DUT
//=================================================
mem_if miff(clk);
memory_ctrl U_ctrl(miff);
memory_model U_model(miff);
test U_test(miff);

endmodule

You could download file interface_modports.sv here

 


Simulation Result : Modport

 @150ns Writing address 0 with data 24
@230ns Writing address 1 with data 81
@310ns Writing address 2 with data 9
@390ns Writing address 3 with data 63
@690ns Reading address 0, Got data 24
@770ns Reading address 1, Got data 81
@850ns Reading address 2, Got data 9
@930ns Reading address 3, Got data 63








Get free daily email updates!



Follow us!


No comments:

Post a Comment

Please provide valuable comments and suggestions for our motivation...

Popular Posts