Search code examples
verilogsystem-verilog

How to define an enum type and include it in multiple modules?


I want to define an enumeration type for function codes, which then gets included into multiple modules. However, when I try to compile my solution using modelsim, I get the following error:

Connection type 'enum reg[2:0] ' is incompatible with 'enum reg[2:0] ' for port (function_code): Enum types must match.

The error message is contradictory and I do not really know what I am doing wrong.

I am defining the enumeration as follows:

typedef enum logic [2:0] {ALU_ADD = 3'b000, ALU_SUBTRACT = 3'b001, ALU_MULTIPLY = 3'b010} AluFunctionCode;

In my ALU module, I am using the type like this:

module ArithmeticLogicUnit #(parameter N=8) (
    input logic [N-1:0] operand_a, operand_b,
    input AluFunctionCode function_code,
    output logic [N-1:0] result
);

And in my testbench, I am instantiating the ALU as follows:

logic [7:0] a, b, result;
AluFunctionCode functionCode;

ArithmeticLogicUnit alu (.operand_a(a), .operand_b(b), .function_code(functionCode), .result(result));

Solution

  • How to define an enum type and include it in multiple modules?

    A good way to do this is to create a package and import it. Refer to IEEE Std 1800-2023 section 26. Packages.

    For example, create a file some_pkg.sv with these contents:

    package some_pkg;
    
    typedef enum logic [2:0] {
        ALU_ADD      = 3'b000,
        ALU_SUBTRACT = 3'b001,
        ALU_MULTIPLY = 3'b010
    } AluFunctionCode;
    
    endpackage
    

    In your ALU file, use import:

    import some_pkg::*;
    
    module ArithmeticLogicUnit #(parameter N=8) (
        input logic [N-1:0] operand_a, operand_b,
        input AluFunctionCode function_code,
        output logic [N-1:0] result
    );
    
    endmodule
    

    Also use import in your testbench file:

    module tb;
    
    import some_pkg::*;
    
    logic [7:0] a, b, result;
    AluFunctionCode functionCode;
    
    ArithmeticLogicUnit alu (
        .operand_a(a), 
        .operand_b(b), 
        .function_code(functionCode), 
        .result(result)
    );
    
    endmodule
    

    Something similar can be accomplished with `include, but import is usually cleaner.

    You need to make sure you add all 3 files to your compile command.