UPGRADE YOUR BROWSER

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!

Reply

Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Visitor
Posts: 5
Registered: ‎03-09-2017

Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Hello,

  I have a trouble to synthesize a code of VHDL register vector which bits are assigned by different processes (each bit of the vector is assigned exactly once, of course) with Vivado 2016.4 64bit (2016.2 too).

 

SIGNAL r_regBE0 : std_logic_vector(7 DOWNTO 0);

 

PROCESS (rstn, clk)
BEGIN
  IF rstn = '0' THEN
    r_regBE0( 7 DOWNTO 6 ) <= "01";    
    r_regBE0( 3 DOWNTO 2 ) <= "10";       
  ELSIF (clk'event AND clk = '1') THEN
    IF store = '1' THEN   
      r_regBE0( 7 DOWNTO 6 ) <= dout( 7 DOWNTO 6 );
      r_regBE0( 3 DOWNTO 2 ) <= dout( 3 DOWNTO 2 );
    END IF;   
  END IF;
END PROCESS;

PROCESS (clk)
BEGIN
  IF (clk'event AND clk = '1') THEN   
    IF store = '1' THEN   
      r_regBE0( 5 DOWNTO 4 ) <= dout( 5 DOWNTO 4 );
      r_regBE0( 1 ) <= dout( 1 );
      r_regBE0( 0 ) <= dout( 0 );      
    END IF;    
  END IF;
END PROCESS;

 

The elaborated schematics shows there are multiple REG instances driving the output, the second REG has its D input not connected (please see the attached picture).

These multiple drivers lead to the following warnings during the synthesis;

WARNING: [Synth 8-3332] Sequential element (r_regBE0_reg[5]) is unused and will be removed from module M.
WARNING: [Synth 8-3332] Sequential element (r_regBE0_reg[4]) is unused and will be removed from module M.
WARNING: [Synth 8-3332] Sequential element (r_regBE0_reg[1]) is unused and will be removed from module M.
WARNING: [Synth 8-3332] Sequential element (r_regBE0_reg[0]) is unused and will be removed from module M.
WARNING: [Synth 8-3332] Sequential element (r_regBE0_reg[5]__0) is unused and will be removed from module M.
CRITICAL WARNING: [Synth 8-3352] multi-driven net Q with 1st driver pin 'M/r_regBE0_reg[5]__0/Q' [code.vhd:548]
CRITICAL WARNING: [Synth 8-3352] multi-driven net Q with 2nd driver pin 'GND' [code.vhd:548]
CRITICAL WARNING: [Synth 8-5559] multi-driven net Q is connected to constant driver, other driver is ignored [code.vhd:548]
WARNING: [Synth 8-3332] Sequential element (r_regBE0_reg[4]__0) is unused and will be removed from module M.
CRITICAL WARNING: [Synth 8-3352] multi-driven net Q with 1st driver pin 'M/r_regBE0_reg[4]__0/Q' [code.vhd:548]
CRITICAL WARNING: [Synth 8-3352] multi-driven net Q with 2nd driver pin 'GND' [code.vhd:548]
CRITICAL WARNING: [Synth 8-5559] multi-driven net Q is connected to constant driver, other driver is ignored [code.vhd:548]

Consequently, these registers are incorrectly replaced by constant value signals, effectively removing a whole bunch of functional logic driven by these signals. Same happens to the REGs at bit position [1:0]. I think it is a bug in the Vivado elaboration.

 

The above design code has been synthesized correctly by other tools including the Xilinx ISE Webpack 14.7.

I'm not sure whether this might have the same cause as similar previous reports here, e.g.; the post with the "Critical warnings [Synth 8.5559] and [Synth 8-3352] with Vivado 2016.3" topic.

 

Thank you.

Vivado_16.4_Synth-8-3352_bug.png
Voyager
Posts: 322
Registered: ‎04-21-2014

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

[ Edited ]

Looks like it might be a bug. Sorry if my response keeps Xilinx employees from seeing and responding to your post.  Also, at the risk of offending a VHDL guru who just posted a simple example to illustrate a more sophisticated issue, as a work around, you might try:

 

 

SIGNAL r_regBE0 : std_logic_vector(7 DOWNTO 0) := (others => '0'); -- explicit initialization

...


process(clk)
begin
 if (rising_edge(clk)) then
  -- put following lines outside synchronous reset conditional to avoid CE inference
    r_regBE0( 5 DOWNTO 4 ) <= dout( 5 DOWNTO 4 );
    r_regBE0( 1 )          <= dout( 1 );
    r_regBE0( 0 )          <= dout( 0 );     
   if(rst = '1') then
     r_regbe0( 7 downto 6 ) <= "01";   
     r_regbe0( 3 downto 2 ) <= "10"; 
   else
      if store = '1' then  
        r_regbe0( 7 downto 6 ) <= dout( 7 downto 6 );
        r_regbe0( 3 downto 2 ) <= dout( 3 downto 2 );
      end if;
    end if;
  end if;
end process;

 


The advantage here:


1.  Only one process.  What you did should work based on my quick visual inspection, but it doesn't according to your report.  The above (or below) may get around the parsing problem you seem to have identified


2.  Synchronous active high reset (recommended on 7-series).   Xilinx supports achromous resets so this is just to comply with Xilinx recommendations for 7-series.  Note, however, when you use synchronous resets, you need to "beware CE inference" (data enable inference would be a better term, but Xilinx calls it "clock enable inference").


3.  If you need the asynchronous reset, you could try this (noting that "ce inference" isn't an issue with asynchronous resets):

 

 

-- FOR THE SAKE OF PEOPLE QUICKLY READING THIS THREAD, DON'T MIMIC the FOLLOWING CODE WHICH

-- WAS UNTESTED...see below for another option.

signal r_regbe0 : std_logic_vector(7 downto 0) := (others => '0'); -- explicit initialization


process (rstn, clk)
begin
  if rstn = '0' then
    r_regbe0( 7 downto 6 ) <= "01";   
    r_regbe0( 3 downto 2 ) <= "10";       
  elsif (clk'event and clk = '1') then
    if store = '1' then  
      r_regbe0( 7 downto 6 ) <= dout( 7 downto 6 );
      r_regbe0( 5 downto 4 ) <= dout( 5 downto 4 );
      r_regbe0( 3 downto 2 ) <= dout( 3 downto 2 );
      r_regbe0( 1 ) <= dout( 1 );
      r_regbe0( 0 ) <= dout( 0 );       
    end if;   
  end if;
end process;

 

Lastly, note that by having some registers reset, and others not, the registers cannot be packed in same slice (especially if they are asynchronously reset).  This may effect slice utilization. 

***Many of us who help you are just FPGA enthusiasts, and not Xilinx employees. If you receive help, and give kudos (star), you're likely to continue receiving help in the future. If you get a solution, please mark it as a solution.***
Xilinx Employee
Posts: 2,061
Registered: ‎11-09-2015

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Hi @kraboun,

 

Could you share a test case? I want to have a full view of your RTL.

 

Thanks and Regards,

 

Florent

------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
Explorer
Posts: 199
Registered: ‎04-26-2012

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

[ Edited ]

@kraboun " I have a trouble to synthesize a code of VHDL register vector which bits are assigned by different processes "

 

Signals in VHDL should normally be driven only from within a single process or assignment statement.

see edit below

>

> each bit of the vector is assigned exactly once, of course

>

Even though you are only explicitly assigning some bits from each process, each process creates an inherent driver for the entire signal, causing your multi-driven net critical warnings. If you had simulated this code, the same problem would be apparent in simulation.

EDIT: I might have remembered this rule incorrectly- the above statement is true for a composite type such as a record, but std_logic_vector being a vector of a resolved type might allow for individual assignment without creating the default driver on all bits- I'd need to rummage though a VHDL reference to be sure.

 

EDIT2: I quickly looked this up - see page 83 of this book

    Simple static assigments to individual std_logic_vector bits do not create the extra drivers:

          r_regbe0( 1 ) <= din( 1 );

          r_regbe0( 0 ) <= din( 0 );      

    But indexing with this loop in a process will create 'U' drivers on bits 7:2 (loop index not considered static)

           for i in 0 to 1 loop
              r_regbe0( i ) <= din(i);
           end loop;
 

The best solution would be to put everything into one process as suggested by morgan.

 

-Brian

 

 

Visitor
Posts: 5
Registered: ‎03-09-2017

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Thank you Morgan for the hints. I agree with the design practices for FPGAs where the design shall be rather fully synchronous.

In my case, however, the RTL is the ASIC prototype code, hence those asynchronous resets, and an attempt to use flops without resets whenever possible. Please notice that your proposed code (the 2nd one using asynchronous reset in Red) creates unnecessary path from rstn to the DFF[5,4,1,0].D inputs, that is why there were two processes. Plus the explicit initialisation is not usually supported by syntesis tools.

 

 

 

Visitor
Posts: 5
Registered: ‎03-09-2017

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Hello Brian, thank you for the reference to the VHDL specification. As the above code uses only static indices, I think it should belong to the first case - drivers created only for the addressed items of the vector array.

I'm going to post the example code and let the Xilinx engineers decide whether it is a bug or not.

Visitor
Posts: 5
Registered: ‎03-09-2017

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Hello Florent,

  please see the attached code that demonstrates the trouble when elaborated by the Vivado 16.4 (target device Artix). This code works well in the RTL simulation (Cadence ncsim), and has been correctly synthesised by the Xilinx ISE 14.7 (Spartan6), and Synopsys DC Compiler (ASIC). It might be a bug in Vivado or just a different interpretation of the VHDL specification (please see Brian's post for references).

Thank you,

kraboun

Voyager
Posts: 322
Registered: ‎04-21-2014

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]


kraboun wrote:

Thank you Morgan for the hints. I agree with the design practices for FPGAs where the design shall be rather fully synchronous.

In my case, however, the RTL is the ASIC prototype code, hence those asynchronous resets, and an attempt to use flops without resets whenever possible. Please notice that your proposed code (the 2nd one using asynchronous reset in Red) creates unnecessary path from rstn to the DFF[5,4,1,0].D inputs, that is why there were two processes. Plus the explicit initialisation is not usually supported by syntesis tools.

 

 

 


I typed that previous code without testing.  Try this for your application as a workaround:

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity top is
port (
  iD     : in  std_logic_vector(7 downto 0);
  iRST_n : in  std_logic;
  iCLK   : in  std_logic;
  iEN    : in  std_logic;
  oQ     : out std_logic_vector(7 downto 0)
);
end entity top;

architecture rtl of top is
  signal Q : std_logic_vector(7 downto 0) := (others => 'U'); -- for simulation
begin

  process (iRST_n, iCLK)
  begin
    -- no reset bits
    if(rising_edge(iCLK)) then
      if iEN = '1' then  
        Q(5 downto 4) <= iD(5 downto 4);
        Q(1 downto 0) <= iD(1 downto 0);
      end if;   
    end if;
    -- reset bits
    if iRST_n = '0' then
      Q(7 downto 6) <= "01";   
      Q(3 downto 2) <= "10"; 
      -- intentionally not reseting bits 0:1 and 4:5     
    elsif (rising_edge(iCLK)) then
      if iEN = '1' then  
        Q(7 downto 6) <= iD(7 downto 6);
        Q(3 downto 2) <= iD(3 downto 2);
      end if;   
    end if;
  end process;
 
  oQ <= Q;

end architecture rtl;

***Many of us who help you are just FPGA enthusiasts, and not Xilinx employees. If you receive help, and give kudos (star), you're likely to continue receiving help in the future. If you get a solution, please mark it as a solution.***
workaround.jpg
Highlighted
Explorer
Posts: 199
Registered: ‎04-26-2012

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

[ Edited ]

 @kraboun "I'm going to post the example code"

 

A key difference in your complete example code is the inclusion of a dynamic asynchronous register initialization from the signal mo_a  (vs. the earlier fragment with only static async. initialization) :

    IF rstn = '0' THEN
      r_regBE0( 7 DOWNTO 6 ) <= mo_a;    

 

AFAIK, this sort of stuff doesn't synthesize properly in the newer devices with only one async control line per flip-flop, but I'd certainly expect a more meaningful warning or error message from the synthesizer. (Examining the elaboration step schematic reveals flip-flops with both an async set and async reset, so the tool certainly has enough information at that point to tell you this can't be synthesized properly in the target family.)

 

Replacing this dynamic assignment of mo_a with a static value in your complete example eliminates all the critical warnings, and the resulting post-synthesis schematic looks sensible at a quick glance.

 

From UG1026 page 8 for Ultrascale:

async_ctl_set.png

Or this Virtex6 AR:

  https://www.xilinx.com/support/answers/33209.html

 

-Brian

Visitor
Posts: 5
Registered: ‎03-09-2017

Re: Vivado RTL elaboration of VHDL registers driven by multiple processes [Synth 8-3352]

Hello Brian (@), 

  you are right, I forgot the mo_a input in my code - I did not consider it to be a dynamic culprit as it was the regBE0[5:4] and [1:0] flops that suffered from the "critical warning", not the regBE0[7:6] flops that use the mo_a input. (Apparently, the current Vivado tool supports the DFFs with both asynchronous set and reset the same (and the best) way it was solved in the ISE - at least I can see one FDPE, one LDCE, and one FDCE per each such RTL register in the synthesised schematics (plus I'm not able to find any warning about it). Of course, a sub-optimal performance etc. might still apply so it should be avoided in regular FPGA designs.)

 

  Hence, the issue seems to be an incompatibility between the Vivado and other tools. While Vivado creates drivers for all the elements of the r_regbBE0 array upon detection of a dynamic input, other tools incl. ISE possibly treat the std_logic vector array elements separately and associate the drivers only to those elements that depend on these dynamic inputs (r_regBE0[7:6]). I'm unable to tell what is right, my understanding has been the latter one whole time. I hope Xilinx engineers (@) can check and confirm their implementation of this is not incorrect with respect to the VHDL specification.

Thank you.

kraboun