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

VHDL default signal state bug ?

Altera_Forum
Honored Contributor II
1,747 Views

We tried to do a very simple thing: a demultiplexer that enables one of several gates according to the state of an n-signal vector. (Just static, no Flipflops involved.) 

 

So we defined a 2^n signal vector and set the default value to "0" and later in the code we set one of it's the signals to "1" by an appropriate statement.  

 

We were used to use this method with Xilinx projects and it did work fine there. 

 

We did find a (supposedly more "recommended") way to create a demultiplexer (without using default values), so no harm done, but.... 

 

Our first try might be considered "bad style" but the Quartus did not complain and I don't see why this does not work with Quartus (but with teh Xilinx tool chain). So I feel this is might be a bug.... 

 

-Michael
0 Kudos
15 Replies
Altera_Forum
Honored Contributor II
797 Views

Please post the code, as it will make alot more sense than your explanation.

0 Kudos
Altera_Forum
Honored Contributor II
797 Views

You also didn't mention what's the unexpected behaviour. 

 

Usually, similar issues turn out as strictly correct operation related to the respective HDL specification.
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

This did not work (seemingly load(i) always was 0 in some or all cases ):  

signal load: std_logic_vector (63 downto 0) := (others => '0'); ... load(conv_integer(address)) <= '1'; ... < now we use load(...) > ... This did work:  

signal load: std_logic_vector (63 downto 0); ... G1: for i in 0 to 63 generate begin load(i) <= '1' when (conv_integer(address) = i) else '0'; end generate G1 ... < now we use load(...) > ... -Michael
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

From looking at the code you have posted, they are not the same thing. 

 

The second example sets every bit to '0', and the selected address to '1' every time the address changes. 

 

The first (non working) example is making latches. You may be inititialising all the results to '0' but you are latching a '1' into them when the address is set, and then they will stay at '1' for ever.
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

Oops (maybe this is a silly question, as I am new to VHDL, while the colleage of mine who does work with VHDL since some time, is not available right now. And of course this is strictly of-topic,so feel free to ignore). 

 

>>"The second example sets every bit to '0'," 

 

When ? (My thinking was, "always, unless something else is stated", thus not time-depending but just as logical result of all lines in the module.) 

 

What exactly makes the compiler think that I want to store something with the first code and thus it needs to implement any FlipFlops, and not just logic gates ? (No clock is mentioned anywhere, RS-FF with just a set and no reset does not seem to make any sense.) 

 

Is it just because there is not "else" ?  

 

If we want to do a "synchronous" design (state changes only due to clock edges), how to make sure that no "parasitic" R/S FFs are created ? 

 

-Michael
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

The second example is simply a decoder, clear combinational code without any ambiguousities. 

 

The first example must implement latches (in a FPGA, they are created as logic loops) to hold the state of the unselected bits. You have at least the problem, that changing the select input can set additional bit's due to glitches, but never reset them. I'm also not sure, if the default expression is synthesized correctly with latches as it works with registers.
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

 

--- Quote Start ---  

The first example must implement latches (in a FPGA, they are created as logic loops) to hold the state of the unselected bits. You have at least the problem, that changing the select input can set additional bit's due to glitches, but never reset them. I'm also not sure, if the default expression is synthesized correctly with latches as it works with registers. 

--- Quote End ---  

 

 

I see. (Only in my terminology a "Latch" is a D-FF, while - as here is no clock - the code only can result in an R/S-FF.) An R/S FF of course can be done using just hogical equations (i.e. gates). 

 

I do see that the code can (or must) be interpreted in the way you mention. So my question is how to be sure that this is not happening. Do I really need to give an "else" with any "when", so that the compiler knows that I don't want a previous result ?  

 

-Michael
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

 

--- Quote Start ---  

 

 

I do see that the code can (or must) be interpreted in the way you mention. So my question is how to be sure that this is not happening. Do I really need to give an "else" with any assignment, so that the compiler knows that I don't want a previous result ?  

 

-Michael 

--- Quote End ---  

 

 

Any code that is not clocked must have all cases covered, otherwise latches (ie. memory) are infered because it assumes there are some states you dont want it to react to, and keep the previously stored value. Latches are not good things because you cannot guarantee timing on them, and glitches are likely to occur. For example in the case above - if the individual bits in the adddress line change at a different time, you are going to set 2 output bits when you only meant to set 1. 

 

In a clocked process, if you dont cover all cases, the register will just become a DFFE (register with enable port) with the existing conditions setting the enable port. This is safe and normally what you want, because they are timed against the clock. Use the following template - it will only load a value when enable = '1': 

 

process(clk) begin if rising_edge(clk) then if enable = '1' then q <= d; end if; end if; end process;  

 

 

The most common place for people to create latches is in state machine processes when the 2-process technique is used. In this case, people often forget to assign every signal in every state. The usual way to bypass this is to assign a default value at the top of the process, or just ignore the 2-process method altogether and keep it to a single process. 

 

Back to the origional question, there are many ways to do various things. For your example, there is another way of doing the same thing instead of using a generate loop: 

 

process(address) begin load <= (others => '0'); load(conv_integer(address)) <= '1'; end process; In this case, when address changes, load has all bits set to '0', but the address bit is overidden with a '1'. This should output the same logic as with the generate loop.
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

I see.  

 

In some VHDL book it seems that "when" implicitly creates a process that internally does "if" instead. This of course is exactly what I wanted to avoid (even though I suppose when all cases are covered the compiler can optimize out the FlipFlops that the process needs to hold the sequential states).  

 

so instead of  

load(i) <= '1' when (conv_integer(address) = i) else '0'; I'd better write something like  

load(i) <= not (conv_integer(address) xor i); Would this avoid the problem from ground up ?  

-Michael
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

 

--- Quote Start ---  

I see.  

 

In some VHDL book it seems that "when" implicitly creates a process that internally uses if instead. This of course is exactly what I wanted to avoid (even though I suppose when all cases are covered the compiler can optimize out the FlipFlops that the process needs to hold the sequential states.  

 

--- Quote End ---  

 

 

All assignments outside a process are implicit processes sensitive to every signal on the right hand side of the assignment. "when" is just a way of creating a mux. There are many ways to do exactly the same thing. Look at the following code blocks - they all do exactly the same thing. 

 

output <= A when threebits = "000" else B when ( threebits = "001" or threebits = "010" ) else C; out_mux : with threebits select output <= A when "000", --single case <= B when "001" | "010", -- 2 states set the same case, <= C when others; -- catch all the reset of the states process(threebits, A, B, C) begin if threebits = "000" then output <= A; elsif ( threebits = "001" or threebits = "010" ) then output <= B; else output <= C; end if; end process;  

 

With all of these, you have to explicitly say each case. They are only good when you have a small number of cases, otherwise it is best to use loops like you have already done. If you tried to do the above with your load, you'd have to define 64 explicit cases. 

 

 

--- Quote Start ---  

 

so instead of  

load(i) <= '1' when (conv_integer(address) = i) else '0'; I'd better write something like  

load(i) <= not (conv_integer(address) xor i'; Would this avoid the problem from ground up ?  

-Michael 

--- Quote End ---  

this second method has no meaning, because you cannot xor an integer with anything, or invert it, or assing it directly to a std_logic_vector.
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

 

--- Quote Start ---  

this second method has no meaning, because you cannot xor an integer with anything, or invert it, or assing it directly to a std_logic_vector. 

--- Quote End ---  

 

 

Oops, no simple operations creating logical results from numerical values ?!?!?! 

 

But if you cay a process does not harm, I do see how to proceed. 

 

Thanks a lot for the VHDL introduction !!! 

 

Michael (having noticed that C is a straight forward language :) )
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

 

--- Quote Start ---  

Oops, no simple operations creating logical results from numerical values ?!?!?! 

 

--- Quote End ---  

 

 

VHDL is strongly typed, so you have to be careful with your typecasting. an integer is not a collection of bits, so you cant extract them from it. A std_logic_vector is NOT an integer, it is a collection of bits, and can represent anything (an unsigned integer, signed integer, float, double, a bus full of control bits, fixed point binary, BCD - anything). But if you mean to store something as an integer, use an integer type rather than a std_logic_vector. 

 

I notice you use the std_logic_arith/unsigned packages. You might want to change over to iee.numeric_std instead seeing as you are a beginner - best to get into good habits now. Numeric_std is an ieee standard, std_logic_arith and the like are not - they encourage you to forget about the typing that VHDL provides and use std_logic_vectors as integers, which they are not!
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

Tricky, Thanks a lot for your help !!! 

-Michael
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

 

--- Quote Start ---  

Numeric_std is an ieee standard, std_logic_arith and the like are not 

--- Quote End ---  

 

std_logic_arith is the old IEEE standard, still used in all Altera IP till now. It doesn't involve std_logic_unsigned/signed, which is a different thing. Regarding the original question, if you are intending just a simple combinational decoder, the generate variant is a straightforward way to build it.
0 Kudos
Altera_Forum
Honored Contributor II
797 Views

std_logic_arith was never an IEEE standard. It was created by synopsys to bring together what everyone else had done in their own packages. Because numeric std wasnt around until vhdl '93 everyone adopted it.  

 

VHDL '08 brings std_logic_arith packages all together again into IEEE standard packages.
0 Kudos
Reply