sliceverilogvhdlvivado

Verilog slice direction differs from VHDL


I have a VHDL entity with some unconstrained std_logic_vector ports that is wrapped by a verilog module that clearly defines those port widths.

Verilog wrapper:

module conv_wrapper (din,dout,clk,ce);
input [7:0] din;
output [7:0] dout;
input clk;
input ce;
conv conv_inst (
.din(din),
.dout(dout),
.clk(clk),
.ce(ce));
endmodule

VHDL module:

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;

entity conv is
    port(
        clk  : in  std_logic;
        ce   : in  std_logic;
        din  : in  std_logic_vector;
        dout : out std_logic_vector
    );
end entity conv;

architecture behavioural of conv is

    signal s_nosignbit : std_logic_vector(din'high - 1 downto din'low) := (others => '0');
    signal s_nosignbit_not : std_logic_vector(din'high - 1 downto din'low) := (others => '0');
    signal s_dout : std_logic_vector(din'range) := (others => '0');
    signal msb : std_logic := '0';

begin
    -- Assign the MSB
    msb <= din(din'high);
    -- Assign the rest of the bits excluding the MSB
    s_nosignbit <= din(din'high - 1 downto din'low);
     -- Perform bitwise NOT operation on s_nosignbit
    s_nosignbit_not <= not s_nosignbit;
    -- Concat
    s_dout <= msb & s_nosignbit_not;
    dout <= s_dout;
end architecture behavioural;

The VHDL module essentially just converts a number to 2's complement. There are probably simpler ways to do this but that is not the point here really.

I'm getting an error during simulation that this line: s_nosignbit <= din(din'high - 1 downto din'low); is incorrectly assigning the values as the "slice direction differs from its index type range". I've often used unconstrained ports in my designs and have never seen this before. Does Vivado not correctly translate 7:0 as 7 downto 0 perhaps?

Using Vivado 2024.1

Thank you all.


Solution

  • Some things to keep in mind:

    1. There is no standard for VHDL under Verilog or the other way around, so each tool vendor will provide different capabilities and limitations.

    2. Because of 1., keep the types used at the interface between the VHDL and Verilog domains very simple, example scalers (1 bit) or an array/vector (a group of bits considered together). No records, structures, enums, arrays of arrays etc.

    3. Taking 2. further, specify the size of the ports explicitly, don't rely on the tools figuring out the size of the ports based on rules that work within either language. Based on this, I would specify the vector size as din : in std_logic_vector(7 downto 0); in the VHDL entity. Make the same change for dout. If you need portability use a VHDL generic. Another classic example of this is that in Verilog ints are always 32 bits; VHDL will not know that.

    4. A direct quote from Xilinx UG 901 Synthesis Guide
      "Recommended: Do not use unconstrained ports. Define ports that are constrained through generics. Apply different values of those generics at instantiation. Do not have an unconstrained port on the top-level entity."

    5. Same change 3. for the component statement if needed.

    6. Order the ports the same order on the wrapper module and the instance. Don't count on the languages native ability to do named association correctly. Include the component statement in this rule. If you use VHDL generics, then order the port map generics the same as the entity. Same with Verilog parameters on a module instance.

    7. There is a section on Vivado mixed language support here UG901 Synthesis Guide

    The general rule about mixing VHDL and Verilog this is to lower your expectations and not be disappointed, however bits and bit vectors should behave as expected. Just be explicit about the vector size everywhere in the code that you can.