Search code examples
verilogsystem-verilog

Using a SystemVerilog interface as an input port to a module


There are multiple modules where I take as input (among other things) a

input[15:0] instruction

Then, in all these modules I copy and paste the following code:

wire aluBit = instruction[15];
wire jumpBit = instruction[14];
wire[2:0] mainOpcode = instruction[13:11];
wire constantBit = instruction[10];
wire standaloneBit = instruction[9];
wire[7:0] embeddedConstant = instruction[9:3];
wire[2:0] instrParam1 = instruction[8:6];
wire[2:0] instrParam2 = instruction[5:3];
wire[2:0] instrDestination = instruction[2:0];

I believe interfaces would streamline this and get rid of the copy-pasting. But I don't understand how to make it work.

Note: If it helps, I am using a SystemVerilog to Verilog converter called sv2v.

I tried alot, for example:

interface Instruction;
    logic[15:0] instruction,
    logic aluBit, jumpBit, isConstantInstruction, standaloneBit,
    logic[2:0] mainOpcode, instrParam1, instrParam2, instrDestination,
    logic[7:0] embeddedConstant

    always_comb aluBit = instruction[15];
    always_comb jumpBit = instruction[14];
    always_comb mainOpcode = instruction[13:11];
    always_comb isConstantInstruction = instruction[10];
    always_comb standaloneBit = instruction[9];
    always_comb embeddedConstant = instruction[9:3];
    always_comb instrParam1 = instruction[8:6];
    always_comb instrParam2 = instruction[5:3];
    always_comb instrDestination = instruction[2:0];
endinterface

Then I tried to define the ControlUnit module, with an Instruction input port:

module ControlUnit(Instruction instruction);
    wire example = instruction.jumpBit;
    ...
endmodule

It just does not compile though.


Solution

  • Here is an example of an interface definition (using the OP as a baseline) and its use as a module port taking the interface to be a bundle of wires with no ports (meaning the interface itself has no ports).

    The posted code is missing semicolons on the wires near the beginning.

    • Added semicolons to interface
    • Declared the interface (must be defined outside a module, a module and an interface are both fundamental design units)
    • Created module ControlUnit with interface port , and printed a couple of the interface values.
    • Instantiated somemodule in a testbench
    • Declared an interface type variable to connect to the module port
    • Drove the interface variable with a constant
    • Connected interface variable to the testbench DUT
    • Ran the testbench

    interface:

    interface Instruction ();
        logic[15:0] instruction;
        logic aluBit, jumpBit, isConstantInstruction, standaloneBit;
        logic[2:0] mainOpcode, instrParam1, instrParam2, instrDestination;
        logic[7:0] embeddedConstant;
    
        always_comb aluBit = instruction[15];
        always_comb jumpBit = instruction[14];
        always_comb mainOpcode = instruction[13:11];
        always_comb isConstantInstruction = instruction[10];
        always_comb standaloneBit = instruction[9];
        always_comb embeddedConstant = instruction[9:3];
        always_comb instrParam1 = instruction[8:6];
        always_comb instrParam2 = instruction[5:3];
        always_comb instrDestination = instruction[2:0];
    endinterface
    

    module:

    module ControlUnit(
      Instruction instruction
      );
      
        wire example = instruction.jumpBit;
      
      initial begin
        #1;
        $display("instruction.jumpBit = %0b",instruction.jumpBit);
        $display("instruction.aluBit = %0b",instruction.aluBit);
      end
      
    endmodule 
    

    testbench:

    module tb ();
      
      Instruction tb_stub();
      
      assign tb_stub.instruction = 16'ha5a5;
      
      ControlUnit dut(
       .instruction(tb_stub)
      );
    
    endmodule   
    

    produces:

    instruction.jumpBit = 0
    instruction.aluBit = 1      
    

    on Cadence, Mentor, Synopsys, and Aldec simulators.