We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Showing results for 
Search instead for 
Did you mean: 
Observer baf2099

Verilog wrapper for system verilog interface with inout ports

I've been utilizing the system verilog interface feature to simplify and organize my code better. Unfortunately though, when packaging IP with Vivado you need to use a verilog wrapper. In order to accommodate my interfaces I've resorted to writing an interface converter that sits between my verilog wrapper and system verilog top design file...


verilog_wrapper.v (top module for the purpose of packaging IP)

system_verilog_interface_converter.sv (declares interfaces and then breaks out their signals to individual ports)

system_verilog_top.sv (actual top of my design, WISH I could just package from this)

design_modules.sv (multiple design files that all use interfaces)


...Until now I've never had to deal with an interface that includes an inout port. I've begun using the MIG IP which generates a DDR4 interface that includes inout ports for signals like the "dq" that are truly bi-directional. The question is how does one perform an interface conversion of an inout port? It can't just be assigned as a normal input or output signal would be as this would indicate a one way directionality.


Here is a sampling of what the interface looks like...

interface intf_ddr4 #(
	// Width of Address Bus (18 - 17)
	parameter ADDR_WIDTH = 17,
	// Width of DQ Bus (min 8, mult of 8)
	parameter DQ_WIDTH = 64

  logic [ADDR_WIDTH-1:0] adr;
  logic [DQ_WIDTH-1:0] dq;

modport std (
    output adr,
    inout  dq);


 The interface converter would look something like this...

module intf_converter (
  //DDR4 interface
  output [16:0] ddr4_adr,
  inout [63:0] ddr4_dq

//interface declerations
intf_ddr4 ddr4();

//interface mapping
assign ddr4_adr = ddr4.adr;
assign ddr4_dq??? 

//system verilog top module
sv_top sv_top (
  .ddr4 (ddr4));

...so you can see the dilemma, but I'm hoping someone has a neat solution to this issue

0 Kudos
1 Reply
Scholar markcurry

Re: Verilog wrapper for system verilog interface with inout ports

We found this a few years ago - in the exact same instance - for creating a ddr interface.  We worked with Xilinx in coming up with an acceptable solution.  There was multiple variants, all a little clunky, but the following is what we agreed on.  First create a "Bidi feedthru" module:

module bidi_feedthru
  parameter WIDTH = 64
  inout wire [ WIDTH - 1 : 0 ] p0,
  inout wire [ WIDTH - 1 : 0 ] p1
  tran t1[ WIDTH - 1 : 0 ]( p1, p0 );

This module creates a parameterizable width bidirectional feedthru using the switch primitives of the verilog language.  There were other alternatives for how to code this module.  But working with Xilinx this was the agreed upon method that IS supported by Vivado synthesis.


Next, instantiate a bidi feedthru instance wherever you need to connect up the top-level ports into the higher level SystemVerilog interface construct - on a per member basis:

module top
  inout wire [ 7 : 0 ] DRAM_DQS_P,
  inout wire [ 63 : 0 ] DRAM_D,

my_ddr_if ddr_ctl_if();
bidi_feedthru #( .WIDTH( 8 ) ) dqsp_alias( DRAM_DQS_P, ddr_ctl_if.dqs_p ); bidi_feedthru #( .WIDTH( 64 ) ) ddr_d_alias( DRAM_D, ddr_ctl_if.data ); ... endmodule

Done!  We've used this since Vivado 2015.4, and it works great.







0 Kudos