Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16557 Discussions

Combinational Loop In VHDL synthesis

Altera_Forum
Honored Contributor II
3,826 Views

Dear all 

I've been working on a project in which I build an interconnection network with similar modules. Each module has 4 inout dataports. Also they have two control ports, one for R/W (Read or Write) and one for switching (like a crossbar switch). To build up the network I need to connect these modules together via their inout data ports. I want to be able to transfer data bidirectionally. I have included my code at the end. This code just has two modules connected to each other.  

- After synthesis in Quartus, ISE, or Synopsys Design Compiler or Synplify Pro, I get warnings which says there are a lot of nodes with combinational loop. But Why? Have I done anything wrong? 

- The .vho netlist I get from Quartus, has inout ports with std_logic_vector type while my original design signed inout ports. Is this resulting from the combinational loops the synthesizer detects? 

 

I would be grateful if anyone can help me with this. 

 

The Module 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity Inter_Con_Mod is generic(WL: integer:= 8); port(PortL0,PortL1,PortR0,PortR1: inout signed(WL-1 downto 0); RW: in std_logic; SW: in std_logic); end Inter_Con_Mod; architecture Behav of Inter_Con_Mod is begin PortR0 <= PortL0 when (SW = '0' and RW = '0') else PortL1 when (SW = '1' and RW = '0') else (others => 'Z'); PortR1 <= PortL1 when (SW = '0' and RW = '0') else PortL0 when (SW = '1' and RW = '0') else (others => 'Z'); PortL0 <= PortR0 when (SW = '0' and RW = '1') else PortR1 when (SW = '1' and RW = '1') else (others => 'Z'); PortL1 <= PortR1 when (SW = '0' and RW = '1') else PortR0 when (SW = '1' and RW = '1') else (others => 'Z');  

 

 

 

 

The Interconnection Example (Top Module) 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Datapath is generic(WL: integer:=8); port(DL0,DL1: inout signed(WL-1 downto 0); DR0,DR1: inout signed(WL-1 downto 0); C0,C1: in std_logic; RW: in std_logic); end Datapath; architecture Behavioral of Datapath is component Inter_Con_Mod is generic(WL: integer); port(PortL0,PortL1,PortR0,PortR1: inout signed(WL-1 downto 0); RW: in std_logic; SW: in std_logic); end component; signal M0_L0,M0_L1,M0_R0,M0_R1: signed(WL-1 downto 0); signal M1_L0,M1_L1,M1_R0,M1_R1: signed(WL-1 downto 0); begin M0: Inter_Con_Mod generic map(WL => WL) port map (M0_L0,M0_L1,M0_R0,M0_R1,RW,C0); M1: Inter_Con_Mod generic map(WL => WL) port map (M1_L0,M1_L1,M1_R0,M1_R1,RW,C1); DL0 <= M0_L0 when RW = '1' else (others => 'Z'); DL1 <= M0_L1 when RW = '1' else (others => 'Z'); M0_L0 <= DL0 when RW = '0' else (others => 'Z'); M0_L1 <= DL1 when RW = '0' else (others => 'Z'); M1_L0 <= M0_R0 when RW = '0' else (others => 'Z'); M1_L1 <= M0_R1 when RW = '0' else (others => 'Z'); M0_R0 <= M1_L0 when RW = '1' else (others => 'Z'); M0_R1 <= M1_L1 when RW = '1' else (others => 'Z'); M1_R0 <= DR0 when RW = '1' else (others => 'Z'); M1_R1 <= DR1 when RW = '1' else (others => 'Z'); DR0 <= M1_R0 when RW = '0' else (others => 'Z'); DR1 <= M1_R1 when RW = '0' else (others => 'Z'); end Behavioral;
0 Kudos
15 Replies
Altera_Forum
Honored Contributor II
2,356 Views

Why do you want inout ports? FPGA fabric cannot support inout, they will be synthesised as separate in and out ports with muxes. Only IO pins can be inout. You should really separated them in to separated in and out ports. 

 

A combinatorial loop occurs when you have asynchronous logic that forms a loop. I cn only assume that this has happened somewhere with your circuit. This logic is unlikely to work and/or may become some kind of oscilator. 

 

The std_logic_vectors appear because the signed data type is really only a VHDL abstract construct. In reality you will only get 1's and 0s, so the VHO only gives you std_logic_vectors. It is functionally identical to the signed type, except you'll need the type conversion in VHDL (which has no affect whatsoeveer on the logic implemented). 

 

There must be some combination in your code that allows a logic loop. These are bad. I suggest a re-design is needed. Why have you got an asynchronous circuit? why isnt it synchronous?
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

Thanks for the reply. Asynchronous? I'm intrigued. This is just a combinational circuit. How can it be asynchronous or synchronous at all? I used inout ports because I was assuming I would just connect them and everything would be fine. I missed the point that there is no bidirectional signal in VHDL and such thing would infer a lot of tri-state buffers. 

Speaking of the vho file, I tested another module ( a simple cordic rotation) and the vho didn't change the signed ports to std_logic_vector(s). Actually, the conversion you mentioned was done inside the file (signed to std_logic_vector conversion). Now imagine I have a vho file with those std_logic_vector ports. But my testbench has signed ports and there would be a conflict. Should I change the testbench ports to std_logic_vector? Will the results be valid in that case?
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

I think you are confusing several things here: 

1. VHDL is just a high level language, and is designed as a modelling language. VHDL can be compiled by synthesis tools to logic if the VHDL describes a logic circuit. There are many VHDL constructs that will not map to real hardware, because VHDL is a modelling language so can also be written as non-synthesisable models. 

2. Combinatorial is the same as asynchronous. Synchronous would mean a circuit with a clock.  

3. Things cannot just be connected and everything be "fine". Did you think about what circuit you were trying to create? what is the purpose of the design? because VHDL is a modelling language you should first know what circuit you are rtying to create, and this is usually done before writing any code - on paper, or in a document or something. 

4. VHO file is usually some form of compiled version of your code. You dont need it to simulate the design - the VHDL can be simulated directly.  

5. Testbench ports can be any type you want. Types are just a VHDL construct to make the code easier to understand. At the end of the day, each bit will be it's own wire, so types have nothing to do with the final circuit. 

 

I cant really see what your code is supposed to do, other than connect different ports to each other. Its doesnt seem to serve much purpose. What is it supposed to do? Have you thought about making a synchronous design? FPGA fabric is really meant for synchronous circuits.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

First thanks for your time and replies. Second please be patient. I'm here like anyone else to ask and learn. So, please, if this question is so shallow for you to answer, just ignore it. 

It seems you don't get this is just a sample of a big design. As I said there is an interconnection network in my design. The purpose of this interconnection network is to connect some processors to some independent memories. This part of the design is just a combinational block which is placed between some registers.  

Believe me, I know what synthesize-able VHDL code is. And yes, I've done everything on the paper first and then moved to coding. But as my background is in software coding, sometimes I get confused and think things are the same.  

To be able to understand what the problem is, I just clipped a part of my code and presented it here. 

I also know that I can have functional or behavioral simulation of my design. I've done it and it's fine. the vho netlist file is meant for post synthesis simulation.  

And finally, the whole design is a synchronous clocked design.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

Ok - if it was fully synchronous then there should be no possibility of combinatorial loops - clearly something got missed. I can only reply to what is presented, and the code presented doesnt really seem to do much. 

I suggested remapping the design with separate ins and outs, and only leaving the inouts at the top level where bi-directional pins exist. 

is this interconnect internal or external to the FPGA?
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

I did what you say and there is no combinational any more. But this time the top level inout ports have changed to buffers in the .vho netlist file. 

For now the interconnect is internal to the FPGA. But later I might move everything to a board with separate memories.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

Is there any reason you are running post synthesis netlist simulation? With a good synchronous design and good timing analysis netlist simulation should not be needed.

0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

I thought it would be good to check the post synthesis simulation results to be sure of the validity of my design. Finally I've just been able to run a post synthesis simulation although it's been less than helpful.

0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

Yes - best case is the design matches your RTL simulation results. Worst case it takes a long time to simulate and doesnt tell you alot. 

Using the RTL only (using best practice) and good timing specs, I have never run a post synthesis simulation - as there has never been a need.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

 

--- Quote Start ---  

Yes - best case is the design matches your RTL simulation results. Worst case it takes a long time to simulate and doesnt tell you alot. 

Using the RTL only (using best practice) and good timing specs, I have never run a post synthesis simulation - as there has never been a need. 

--- Quote End ---  

 

 

The only real need these days is for an accurate power analysis using toggle info from the simulation.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

The combinational loops are pretty clear. In your first assignment, PortL0 drives PortR0 and then in your third PortR0 drives PortL0. You of course intend the when clauses to make them mutually exclusive, but I doubt if the tools are that smart. You should use the proper VHDL constructs for mutually exclusive cases: 

 

if(SW='0' and RW='0') then PortR0 <= ... PortR1 <= ... PortL0 <= ... PortL1 <= ... elsif(SW='0' and RW='1') then ... elsif(SW='1' and RW='0') then ... else ... end if;  

 

Or a case statement: 

 

test_proc : process(RW, SW, PortR0, PortL0) variable sel : std_logic_vector(1 downto 0); begin sel := SW & RW; case sel is when "00" => PortR0 <= PortL0; PortL0 <= 'Z'; when "01" => PortL0 <= PortR0; PortR0 <= 'Z'; when others => PortR0 <= 'Z'; PortL0 <= 'Z'; end case; end process;  

 

You could still run into trouble though with multiple drivers at a higher level.  

 

It's not entirely clear what you are trying to do, but inout's are best avoided.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

Yeah. I had also seen this kind of implementation but I didn't know there were a preference for this. Thanks anyway. I will test it.  

As I mentioned in my former posts, I want to build a bidirectional interconnection network between some processors and some memories. This is just sample of my interconnection and I wanted to solve the combinational loop issue.
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

Project does have an ELF file. Please make sure project has been buil succcessfully

0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

 

--- Quote Start ---  

Yeah. I had also seen this kind of implementation but I didn't know there were a preference for this. Thanks anyway. I will test it.  

As I mentioned in my former posts, I want to build a bidirectional interconnection network between some processors and some memories. This is just sample of my interconnection and I wanted to solve the combinational loop issue. 

--- Quote End ---  

 

 

Point taken. Buses between chips is one of the few cases where bidirectional lines may make sense since it saves board traces. Of course, you lose the possibility of sending and receiving at the same time and will have all sort of coordination issues unless you have one master.  

 

I think the case statements (or if/else) actually make the code much more clear since it makes it obvious what the outputs are for a given set of inputs (SW and RW in your case).
0 Kudos
Altera_Forum
Honored Contributor II
2,356 Views

 

--- Quote Start ---  

Dear all 

I've been working on a project in which I build an interconnection network with similar modules. Each module has 4 inout dataports. Also they have two control ports, one for R/W (Read or Write) and one for switching (like a crossbar switch). To build up the network I need to connect these modules together via their inout data ports. I want to be able to transfer data bidirectionally. I have included my code at the end. This code just has two modules connected to each other.  

- After synthesis in Quartus, ISE, or Synopsys Design Compiler or Synplify Pro, I get warnings which says there are a lot of nodes with combinational loop. But Why? Have I done anything wrong? 

--- Quote End ---  

 

 

Your entire design is asynchronous because there is no clock. 

 

You use tristates in internal logic (not connected to I/O pins), and the fabric does not have internal tristates, so the synthesis tool attempts to implement your logic using multiplexers. 

 

When it does that, because your design is asynchronous, combinatorial loops are created. If you look at the netlist output from the synthesis tool, you might see that. 

 

The solution is to code this properly: don't use internal tristates, use proper muxes, and make sure you don't have logic loops.
0 Kudos
Reply