Concepts
-
How Verilog models connects between blocks
- Directly on physical connections in actual hardware level
-
Disadvantage
- Port connection must be duplicated in several modules
- Communication protocols must be duplicated also
- Duplication leads to mistakes that is hard to debug
- Changes in spec involves lots of modification
- Details of connection must be defined in early design cycle (not good for top-down design paradigm)
-
“interface” keyword
- Several signals grouped together to represent as a single port
- And modules use interface as a single port
-
Interface contents
- Discrete signals and port
- Communication protocol, defined as task/function
- Protocol checker and verification routines
-
Interface vs. module
- Interface doesn’t have hierarchy
- Interface can be used as module port
- Interface can contain “modport” which can represent different usage env.
How to declare an interface?
-
Similar to module, with “interface … endinterface” keyword
- Can have ports: external signals to interface
- Can use “.name” and “.*” for connection abbreviation
-
Declaration order
- Just as module, no order needed
-
Global vs. local
- Just as module, global definition can be used anywhere, local definition can be used in certain scope (for IP)
How to use interface?
-
As module ports
-
Explicitly named vs. generic
-
Explicitly named interface port can only connect to an interface with the same name
- “module <module_name> ( <interface_name> <port_name);”
-
Generic interface can connec to any interface port
- “module <module_name> ( interface <port_name);”
- Both are synthesizable
-
-
-
Instantiate and connect interface
- ILLEGAL leave an interface port unconnected
- “.name” and “.*” can be used to connect interface
-
Referencing interface’s signals
- Use dot: <port_name>.<internal_signal_name>
Modport
-
Differnet views of interface
- Ex. a interrupt sub-signal could be input to CPU, but output to peripheral modules
-
“modport” means module port
- Contains only direction and signal names, not vector size or types
-
Selecting which modport to use
-
In module instance
- “<module_name> <instance_name> ( .<port_name>(<interface_instance_name>.<modport_name>) );”
-
In module delcaration (better because of consistency)
- “module <module_name> ( <interface_name>.<modport_name> <port_name> );”
- NOT use both methods above
-
If no modport is specified
- all nets have “inout” direction, by default
- all variables have “ref” type, by default
-
Synthesizable for both
- Some synthesis tool will convert (expand) interface modport to normal ports automatically
-
-
To define different sets of connections
- Hide certain signals in different modport: incompleleted signal list while defining one modport
-
Internal signals that are not accessable from any modport
- Might be used for protocol checkers or other functionality
- Example
interface cpu_bus (input logic clk, rstb, test_en); wire [15:0] data; wire [15:0] addr; logic [ 7:0] slave_cmd; logic slave_req; logic bus_grant; logic bus_req; logic slave_ready; logic data_ready; logic mem_ren; logic mem_wen;
modport master (
);
modport slave (
);
modport mem (
);
endinterface
module top ();
// instance of an interface cpu_bus bus ( .* );
processor proc1 ( .bus(bus.master), .* ); slave1 slave1 ( .bus(bus.slave), .* ); slave2 slave2 ( .bus(bus.slave), .* ); dual_port_ram mem ( .bus(bus.mem), .data_b(next_instruction), .* );
// test generator need to access everything in inside “bus” test_generator test_gen ( .bus(bus), .* ); endmodule |
Task/function in interface
-
Implement the details of communication protocol
- Written once, shared by all modules connected using the same interface
- Values are passed to interface methods as input argument
-
“import” when defining “modport”
-
Either use the name only, or the full prototype
- Latter is useful when task is defined somewhere else
-
- Access using <interface_port_name>.<method_name>
- Task/function must be automatic to be synthesizable
-
Exporting task/function are not synthesizable
- Define task/function in module, then export it to interface, and use it in other modules
-
Export from module’s all instances
- “extern forkjoin”
- Useful when you want to broadcast signals, such ask counting one module’s instances