Skip navigation.
Home

SystemVerilog Interface

SystemVerilog introduced the interface as a means to abstract the connectivity between modules. At the most basic level, it can be used to group together wires that make up a bus in a design. This snippet demonstrates how the SystemVerilog interface construct can be used to create an interface for an asynchronous memory and memory controller.

The async_mem_bus is the name of the interface that will connect the asychronous memory (async_mem) and the memory controller (mem_ctrl). The memory controller just writes to the memory and reads back from it a few times before terminating.

// basic inteface for an async memory bus.
interface async_mem_bus;
  logic       oe, we;    // output enable and write enable.
  wire  [7:0] data;      // bidirectional data bus.
  logic [7:0] addr;      // address.
endinterface : async_mem_bus
 
// module to model an async memory. 
// write the memory on rising edge of write enable.
module async_mem (async_mem_bus mem_bus);
logic [7:0] mem [0:255];  // memory array.
 
always @(posedge mem_bus.we)
  mem[mem_bus.addr] = mem_bus.data;  // data registering.
 
// bidirectional control.
assign  mem_bus.data = mem_bus.oe ? mem[mem_bus.addr] : 'z;
 
endmodule
 
// sample module that exercises the async_mem_bus_interface
// it simply writes the first 128 bytes then reads it back.
module mem_ctrl(input bit clk, reset,
                async_mem_bus mem_bus,
                output bit done);
 
logic       write_mode;  // read or write mode.
// internal control signals.
logic [7:0] data_capt,data_int,cnt,toggle_cnt; 
 
// bidirectional control.
assign mem_bus.data = mem_bus.oe ? 'z : data_int;
 
// main sync process.
always @(posedge clk) begin
  if (reset) begin 
    write_mode   <= 1;
    mem_bus.we   <= 0;
    mem_bus.oe   <= 0;
    mem_bus.addr <= 0;
    data_capt    <= 0;
    toggle_cnt   <= 0;
    done         <= 0;
    cnt          <= 0;
    data_int     <= 0;
  end
  else begin
    cnt <= cnt + 1;
 
    // process to write 128 bytes then read them back.
    if ((cnt==255 && write_mode) || (cnt==127 && !write_mode)) begin 
      write_mode   <= ~write_mode;
      toggle_cnt   <= toggle_cnt + 1;
      data_int     <= 0;
      mem_bus.addr <= '0;
      cnt          <= 0;
    end
    else if (write_mode) begin
      mem_bus.we <= ~mem_bus.we;
      mem_bus.oe <= 0;
 
      if (mem_bus.we) begin 
        mem_bus.addr <= mem_bus.addr + 1;
        data_int     <= data_int + 1;
      end
    end
    else begin
      mem_bus.oe   <= 1;
      mem_bus.we   <= 0;
      mem_bus.addr <= mem_bus.addr + 1;
      data_capt    <= mem_bus.data;
    end
 
    // do this 4 times then tell the test bench we are done.
    if (toggle_cnt==4) done <= 1;
  end
end
 
endmodule
 
// test bench to stimulate the design.
module tbbasic_interface;
 
bit clk;    // clock signal.
bit reset;  // reset signal.
bit done;   // done signal.
 
// async memory bus interface instance.
async_mem_bus mem_bus_inst();
 
always #10 clk = ~clk;  // clock generation.
 
// async mem instance.
async_mem async_mem(.mem_bus(mem_bus_inst));
 
// memory controller instance.
mem_ctrl  mem_ctrl(.clk(clk), .reset(reset),
                   .mem_bus(mem_bus_inst),
                   .done(done));
 
// initial input.
initial begin
  reset = 1;
  #100ns reset = 0;
  wait(done==1);
  $stop;
end
 
endmodule

AttachmentSize
system_verilog_basic_interface.sv2.66 KB