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

Latch inference is Quartus bug or specified VHDL behaviour?

Altera_Forum
Honored Contributor II
2,134 Views

Hello, 

 

does anybody know, why Quartus infers latches for the below combinational function if we use an initial value expression for the variable definition of mirrored_data? I looks like a Quartus bug at first sight, because all output bits are actually defined, there's nothing to be latched. 

 

The latches are generated for the function result. If you register y in the upper level, the problem disappears.  

 

The problem is originated from this Edaboard discussion: http://www.edaboard.com/thread273938.html 

 

Best regards, 

Frank 

 

LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY test IS GENERIC ( size: integer :=7); PORT ( x: IN UNSIGNED( size DOWNTO 0); a: IN INTEGER RANGE 0 TO size; b: IN INTEGER RANGE 0 TO size; y : OUT UNSIGNED (size DOWNTO 0)); END; ARCHITECTURE FLOW OF test IS function mirror ( data : unsigned ; top : integer ; bottom : integer ) return unsigned is -- Using an initial value expression in this place causes latch inference, why? -- variable mirrored_data : unsigned ( data ' range ) := data; variable mirrored_data : unsigned ( data ' range ); begin mirrored_data := data; for index in 0 to data ' length - 1 loop if (index <= top) and (index >= bottom) then mirrored_data ( index ) := data ( top - index + bottom ) ; end if ; end loop ; return mirrored_data ; end function mirror ; BEGIN y <= mirror ( x , a , b ) ; END FLOW;
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

Hello, 

 

does anybody know, why Quartus infers latches for the below combinational function if we use an initial value expression for the variable definition of mirrored_data? I looks like a Quartus bug at first sight, because all output bits are actually defined, there's nothing to be latched. 

 

The latches are generated for the function result. If you register y in the upper level, the problem disappears.  

 

The problem is originated from this Edaboard discussion: http://www.edaboard.com/thread273938.html 

 

Best regards, 

Frank 

 

LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY test IS GENERIC ( size: integer :=7); PORT ( x: IN UNSIGNED( size DOWNTO 0); a: IN INTEGER RANGE 0 TO size; b: IN INTEGER RANGE 0 TO size; y : OUT UNSIGNED (size DOWNTO 0)); END; ARCHITECTURE FLOW OF test IS function mirror ( data : unsigned ; top : integer ; bottom : integer ) return unsigned is -- Using an initial value expression in this place causes latch inference, why? -- variable mirrored_data : unsigned ( data ' range ) := data; variable mirrored_data : unsigned ( data ' range ); begin mirrored_data := data; for index in 0 to data ' length - 1 loop if (index <= top) and (index >= bottom) then mirrored_data ( index ) := data ( top - index + bottom ) ; end if ; end loop ; return mirrored_data ; end function mirror ; BEGIN y <= mirror ( x , a , b ) ; END FLOW; 

--- Quote End ---  

 

 

Have you tried bitwise intialisation of mirrored_data: 

 

mirrored_data(0) := data(0); 

mirrored_data(1) := data(1); 

... 

then apply loop.
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

Probably I misunderstood your exact issue. But is initialising variable with non constant legal?

0 Kudos
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

But is initialising variable with non constant legal? 

--- Quote End ---  

 

I'm no aware of a limitation.  

 

In fact there's a simple solution for the problem, use an explicite assignment instead of the initial value expression, as in my code example. Personally, I'm preferring this style anyway. 

 

The initial value expression should give the same result, but it doesn't. 

 

The VHDL spec tells in chapter 4.3.1.3 Variable declarations: 

 

--- Quote Start ---  

If the variable declaration includes the assignment symbol followed by an expression, the expression specifies an initial value for the declared variable; the type of the expression must be that of the variable. Such an expression is said to be an initial value expression. 

 

If an initial value expression appears in the declaration of a variable, then the initial value of the variable is determined by that expression each time the variable declaration is elaborated. In the absence of an initial value expression, a default initial value applies. 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

I'm no aware of a limitation.  

 

In fact there's a simple solution for the problem, use an explicite assignment instead of the initial value expression, as in my code example. Personally, I'm preferring this style anyway. 

 

The initial value expression should give the same result, but it doesn't. 

 

The VHDL spec tells in chapter 4.3.1.3 Variable declarations: 

--- Quote End ---  

 

 

Ok that implies you can but I don't see how the function call will synthesize to a fixed initial value if data is a variable. In other words I presume the synthesized logic must latch the intial value to know it then apply it. 

 

Adding register to y just masks the issue.
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

Or put it this way. When initial value is constant then it translates to wires connected to ground or source, no latching needed. If it is variable and hence unknown then the logic has look for it and keep it on wires and this implies latching. I would rather avoid it. 

 

Edit: Note also that initialising a variable(or signal) is conceptually different from appling a default value in a running process. 

Default value implies running assignment that can have conditional update in subsequent code. 

initialisation means that the value is applied once only at start only(first sample).
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

initialisation means that the value is applied once only at start only(first sample). 

--- Quote End ---  

 

VHDL spec tells the opposite "the initial value of the variable is determined by that expression each time the variable declaration is elaborated". 

 

Another strange point is, that latches are inferred even if the initial value expression is overwritten by a succeeding unconditional assignment. In other words, even if the initial value expression would be treated different, the sequential elaboration of VHDL statements seems to be invalidated. 

 

I have no problem to accept a - as it appears to me yet - minor Quartus bug that can be easily avoided. But we shouldn't read an expectable or even required behaviour into it, if it isn't.
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

Well I thought a signal is declared once and elaborated once only at function call. 

 

Actually, I am now lost badly even with the basic meaning of initialisation. I know a register can be initialised so that the value appears at powerup on first sample before it is driven on following clock edge. I know a constant always needs a value (not exactly initial) and translates to wires. But if a combinatorial signal or variable is initialised yet it is meant to be neither register nor latch so what does initial value actually mean. Initial at time 0 ?? sample 0 ?? and how is it going to be implemented. I think the best approach as you said is to not put that initial value there and spare initiating the headache of explaining the mystery latches.
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

I think the best approach as you said is to not put that initial value there and spare initiating the headache of explaining the mystery latches. 

--- Quote End ---  

 

That's what I (respectively the guy who discovered the problem) will surely do. The doubts about Quartus behaviour in this point are remaining.  

 

By the way, if I set size:=2 and enable the initial value expression, Quartus RTL netlist viewer crashes, both in V9.0 and V12.0. I also verified, that the code with initial value expressio behaves completely wrong. It latches the function output for each bit that is not "mirrored", as if all assignments mirrored_data := data are commented out. Setting mirrored_data(index) := data(index) individually in an else path doesn't help.  

 

Thanks for your contributions, 

Frank
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

ModelSim RTL simulation functions OK. I don't have a 'dataflow' licence (ASE) so I can't see the RTL it generates. 

I think it is safe to say it is a Quartus bug, but wouldn't bother to file an SR as the Altera gang will tell us to work-around it the way Kaz proposes. Which is not a problem to me, I never initialize a variable at the declaration, not even in C or C++ programs. I always initialise a variable just prior to the first use, to my idea it better documents what's going on. 

 

Setting the SIZE to 2, with the initialiser enabled, doesn't crash in 12.1 (32 bit)
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

Which is not a problem to me, I never initialize a variable at the declaration, not even in C or C++ programs. I always initialise a variable just prior to the first use, to my idea it better documents what's going on. 

--- Quote End ---  

 

 

Yes that's also my usual way to handle variable initialization. Thanks for checking in Modelsim. 

 

As an additional information, the strange behaviour only occurs with variable in functions (and probably procedures, but I didn't check it). Initial value expressions for process variables are simply ignored by Quartus. This isn't a problem, but must be considered for RTL simulation consistency when process variables are used for persistent data storage (as in the Quartus counter templates). 

 

My final conclusion is this: 

Initial value expressions for variables in functions are not working Quartus according to the VHDL specification but have strange side effects. They must be strictly avoided.  

 

Best regards 

Frank
0 Kudos
Altera_Forum
Honored Contributor II
945 Views

 

--- Quote Start ---  

 

I think it is safe to say it is a Quartus bug, but wouldn't bother to file an SR as the Altera gang will tell us to work-around it the way Kaz proposes. Which is not a problem to me, I never initialize a variable at the declaration, not even in C or C++ programs. I always initialise a variable just prior to the first use, to my idea it better documents what's going on. 

--- Quote End ---  

 

 

I would still file a SR so at least it's there for them to consider. But I also dont think they'll bother fixing it. Ive had several other VHDL SRs relating to imference of RAMs and full VHDL 2008 support that dont seem to get fixed. But they will only do them if people request them.
0 Kudos
Reply