Is it normal for this combinational code to generate latches? - vhdl

I am doing some investigation on what kind of code does/does not generate latches on different synthesizers. The code below drives a 7-segment display from a 4-bit input. I would expect it not to generate latches, because all possible cases are covered in the conditional signal assignment.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity seven_seg_conditional is
port (
value: in std_logic_vector(3 downto 0);
digit: out std_logic_vector(6 downto 0)
);
end;
architecture behavior of seven_seg_conditional is
signal value_int: integer range 0 to 15;
begin
value_int <= to_integer(unsigned(value));
digit <=
"0111111" when value_int = 0 else
"0000110" when value_int = 1 else
"1011011" when value_int = 2 else
"1001111" when value_int = 3 else
"1100110" when value_int = 4 else
"1101101" when value_int = 5 else
"1111101" when value_int = 6 else
"0000111" when value_int = 7 else
"1111111" when value_int = 8 else
"1101111" when value_int = 9 else
"1110111" when value_int = 10 else
"1111100" when value_int = 11 else
"0111001" when value_int = 12 else
"1011110" when value_int = 13 else
"1111001" when value_int = 14 else
"1110001" when value_int = 15;
end;
If I run it through Quartus 13.0, a latch is generated on each output. Is this correct behavior for a synthesizer as per the ongoing standards?
Note: if I rewrite the code using a case statement then there are no latches, even though I never added a when others clause. If I add an unconditional else clause at the end there are no latches as well.

If I run it through Quartus 13.0, a latch is generated on each output.
Is this correct behavior for a synthesizer as per the ongoing
standards?
The applicable standard (IEEE Std 1076.6-1999/2004, 8.9.5.1 Conditional signal assignment) defines what syntactical constructs will be recognized for synthesis, not how they are interpreted. That leaves the syntactical meaning found in the VHDL LRM (IEEE Std 1076-1993/2002, year supported varying by synthesis vendor, generally not all inclusive either, no standard for VHDL 2008).
When you add an "unconditional else":
"1110001" when value_int = 15 else (others => 'X');
end;
The thinking goes that conversion functions are essentially ignored and the equivalent condition expression to_integer(unsigned(value)) = 15, etc. doesn't cover all the choices for value. Also 'X' assignments are ignored for synthesis and the else requires something.
A concurrent conditional signal assignment has an equivalent process comprised of if then elsif then ... end if. You could postulate the presence of the trailing else conveys that all choices are covered.
Expressions are evaluated during simulation (e.g. value_int = 15). There either needs to be something in the syntax to signal all choices are covered or the choices have to be all inclusive.
Note that a VHDL simulator get's rid of the uncertainty in your original concurrent signal assignment statement expressions by the package numeric_std TO_INTEGER outputting an assertion warning - "metavalue detected, returning 0". Using value_int has the savings grace of only generating one warning when a value other than a '1' or '0' is detected as an element of the array value.
The range of the integer value_int implies a bit array size. Type conversions have no real meaning for synthesis which is concerned with binary logic.
If you ignore conversion functions and through synthesis 'magic' assume say 15 is representable as a binary value then there isn't anything signaling the choices are all inclusive without the trailing else to not infer latches.
Could a vendor do a better job converting the concurrent signal assignment to logic? Likely, by not deferring to the original array subtype value. Is the behavior you describe correct for ongoing standards? It appears to be. Standards tend to shy away from areas that can conflict between vendors covering instead common ground.
You could also imagine there should be some reasonable limit on the inference of latches, in this case because of combinatorial delays (difference in rise and fall times) in the evaluated expressions. It isn't generally safe to infer a latch enable by gates representing state, there are cases where inferring latch enables should be an error although the inference of latches would work with a one hot state machine or ring counter, which doesn't match the expressions evaluating value.

Related

if statement problem while converting a vector

im new at vhdl coding, and there is a problem with if statement
so my code is the following
i want to convert a vector(bar), if the statement is true (so in this example if its smaller than 10)
process(bar)
variable tmp : integer;
begin
tmp := to_integer(signed(bar));
if tmp < 10 then
good(3) <= bar(3);
good(2) <= bar(3) xor bar(2);
good(1) <= bar(2) xor bar(1);
good(0) <= bar(1) xor bar(0);
end if;
end process;
but the problem is that the statement is not working, if i put a bigger number for example "1111" it is converting in the same way as it converted before
From the comments it seems you want good to be set to 0 whenever bar >= 10. In that case you can just do:
process(bar)
variable tmp : integer;
begin
tmp := to_integer(signed(bar));
if tmp < 10 then
good(3) <= bar(3);
good(2) <= bar(3) xor bar(2);
good(1) <= bar(2) xor bar(1);
good(0) <= bar(1) xor bar(0);
else
good <= (others => '0');
end if;
end process;
The vector good is only assigned when tmp < 10. So there is a latch inferred by this process.
You need to define what's the "else" value for good in any other conditions.
You state that
if i put a bigger number for example "1111" it is converting in the
same way as it converted before
As Tricky pointed out in a comment above, your problem is this line here:
tmp := to_integer(signed(bar));
^^^^^^
You have not posted an MCVE, so I cannot be sure, but your question implies that bar is 4 bits wide. Assuming that is the case, the value "1111" as a signed number is -1. So, if bar is set to "1111", tmp will be -1. -1 is less than 10, so this if statement will evaluate as true:
if tmp < 10 then
If you consider than "1111" is greater than 10 (ie it's 15), then you need to convert via the unsigned type, ie
tmp := to_integer(unsigned(bar));
^^^^^^^^
The range of a 4-bit signed number is -8 to +7. All the values in that range are less than 10, so your if statement will evaluate as true whatever the value of bar.
The above solution assumes that bar is always zero or positive. If that is not the case, then you need more bits in the signal bar. 5 is enough. A 5-bit signed number has the range -16 to +15.
So, I can see two solutions:
use an unsigned type in your type conversion or
make bar 5 bits
or wider.
Others have pointed out that, assuming this is synthsisable code and assuming that this is intended to be combinational logic, then you are missing a branch in your if statement; you don't drive the signal good in the case that the if statement is false and so if you were to synthesise this code as combinational logic, then you would get latches. But that is not the question you asked.

Unsigned multiplication creates a x2 sized array

I'm trying to create a Shift Register, by using multiplication (*2) to shift bits one position.
However, when I do it, ISE (Xilinx IDE) says me that this expression has x2 the number of elements the original signal has.
To be specific, I've:
if rising_edge(clk) then
registro <= unsigned(sequence);
registro <= registro * 2;
-- Just adds into the last position the new bit, Sin (signal input)
registro <= registro or (Sin, others => '0');
sequence <= std_logic_vector(registro);
end if;
And before, I've declared:
signal Sin : std_logic;
signal sequence : std_logic_vector(0 to 14) := "100101010000000";
signal registro : unsigned (0 to 14);
So I'm getting the error (at multiplication line):
Expression has 30 elements ; expected 15
So, why does it creates a x2 sized vector, if I've only multiplied *2?
What am I missing? How can I accomplish it?
Thank you in advance
Word width grows because you have used multiplication.
Multiplying 2 16-bit unsigned numbers gives you a 32 bit unsigned, in general.
Now it would be possible to optimise your specific case of multiplication by a constant, 2, and have synthesis do the correct thing. In which case the error message would change to
Expression has 16 elements ; expected 15
but why should the synthesis tool bother?
Use a left shift instead, either using a left (right?) shift operator, or explicit slicing and concatenation, for example:
registro <= registro(1 to registro'length-1) & '0';
Incidentally:
Using ascending bit order range is quite unconventional for arithmetic : all I can say is good luck with that...
you have three assignments to the same signal within the same process; only the last one will take effect. (See Is process in VHDL reentrant? for some information on the semantics of signal assignment)
If you declared "sequence" as unsigned in the first place you'd save a lot of unnecessary conversions and the code inside the process would reduce to a single statement, something like
sequence <= ('0' & sequence(0 to sequence'length-2)) or
(0 => Sin, others => '0') when rising_edge(clk);
I am utterly unfamiliar with "wrong way round" arithmetic so I cannot vouch that the shifts actually do what you want.

How to design a decoder that will have extra outputs?

For an application I am creating I would like to use a decoder that helps write to one of 42 registers. In order to account for all possible registers, I need a 6 bit input since the ceiling of lg(42) is 6.
However, this will create a 6 to 64 decoder, leaving me with an extra 12 outputs that I do not know how to handle. I know that in VHDL I can write a case statement for it:
case input is
when "000000" => output <= reg0;
when "000001" => output <= reg1;
.
.
.
when others => output <= ???;
end case;
Hopefully everything else will be designed so that an input > 41 does not occur, but how should the code be written to handle that case? Is there a way to handle it without stopping the application some how? Or, as an alternative, is there a way to write a decoder that has only 42 outputs?
An easier way to write this is:
type regs_type is array (integer range <>) of std_logic_vector(7 downto 0);
signal regs : regs_type (0 to 41) := (others => (others => '0'));
...
output <= regs(to_integer(unsigned(input));
Assuming 'input' is an std_logic_vector, and that your registers are 8-bits wide.
Then use the regs array for your registers 0-41. I suppose if you wanted to be explicit about registers 42+, you could create an array of size 64, and leave the upper elements unconnected, but I believe the above code would achieve the same thing.
If your registers actually have meaningful names, not just reg0 etc, you can have a separate block of code connecting these to the regs array, example:
regs(0) <= setup_reg;
regs(1) <= data_out;
and so on. If I was doing it this way, I would have defined constants for the regs index values, example:
constant SETUP_REG_ADDRESS : integer := 0;
constant DATA_OUT_ADDRESS : integer := 1;
...
regs(SETUP_REG_ADDRESS) <= setup_reg;
regs(DATA_OUT_ADDRESS) <= data_out;
Alternatively, if you wanted to keep the case statement, you could write your others clause as
when others => output <= (others => '-');
This 'don't care' value allows the tools to do whatever is the most efficient in these cases that you believe to be unreachable anyway. If you were concerned about something undefined being assigned to output if input somehow did exceed 41, you could always replace the '-' with a '0'.

vhdl code (for loop)

Description:
I want to write vhdl code that finds the largest integer in the array A which is an array of 20 integers.
Question:
what should my algorithm look like, to input where the sequential statements are?
my vhdl code:
highnum: for i in 0 to 19 loop
i = 0;
i < 20;
i<= i + 1;
end loop highnum;
This does not need to be synthesizable but I dont know how to form this for loop a detailed example explaining how to would be appreciated.
Simply translating the C loop to VHDL, inside a VHDL clocked process, will work AND be synthesisable. It will generate a LOT of hardware because it has to generate the output in a single clock cycle, but that doesn't matter if you are just simulating it.
If that is too much hardware, then you have to implement it as a state machine with at least two states, Idle and Calculating, so that it performs only one loop iteration per clock cycle while Calculating, and returns to the Idle state when done.
First of all you should know how have you defined the array in vhdl.
Let me define an array for you.
type array_of_integer array(19 downto 0) of integer;
signal A : array_of_integer :=(others => 0);
signal max : integer;
-- Now above is the array in vhdl of integers all are initialized to value 0.
A(0) <= 1;
A(1) <= 2;
--
--
A(19)<= 19;
-- Now the for loop for calculating maximum
max <= A(0);
for i in 0 to 19 loop
if (A(i) > max) then
max <= A(i);
end if;
end loop;
-- Now If you have problems in understating that where to put which part of code .. in a ----vhdl entity format .. i.e process, ports, etc... you can reply !

Unsigned logic, vector and addition - How?

I'm creating a program counter that is supposed to use only unsigned numbers.
I have 2 STD_LOGIC_VECTOR and a couple of STD_LOGIC. Is there anything I need to do so that they only use unsigned? At the moment I only have library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
I also need to increase one of the binary vectors by 1 under certain conditions (as you probably have guessed by now). Would you be so kind to explain how to perform such actions (using unsigned and adding up one) considering one of the vectors is output with 32 bits.
I'm guessing (I tried) Output <= Output + 1; won't do. Oh and I'm using a process.
In brief, you can add the ieee.numeric_std package to your architecture (library ieee; use ieee.numeric_std.all;) and then do the addition using:
Output <= std_logic_vector(unsigned(Output) + 1);
to convert your std_logic_vector to an unsigned vector, increment it, and finally convert the result back to an std_logic_vector.
Note that if Output is an output port, this won't work because you can't access the value of an output port within the same block. If that is the case, you need to add a new signal and then assign Output from that signal, outside your process.
If you do need to add a signal, it might be simpler to make that signal a different type than std_logic_vector. For example, you could use an integer or the unsigned type above. For example:
architecture foo of bar is
signal Output_int : integer range 0 to (2**Output'length)-1;
begin
PR: process(clk, resetn)
begin
if resetn='0' then
Output_int <= 0;
elsif clk'event and clk='1' then
Output_int <= Output_int + 1;
end if;
end process;
Output <= std_logic_vector(to_unsigned(Output_int, Output'length));
end foo;
Output_int is declared with a range of valid values so that tools will be able to determine both the size of the integer as well as the range of valid values for simulation.
In the declaration of Output_int, Output'length is the width of the Output vector (as an integer), and the "**" operator is used for exponentiation, so the expression means "all unsigned integers that can be expressed with as many bits as Output has".
For example, for an Output defined as std_logic_vector(31 downto 0), Output'length is 32. 232-1 is the highest value that can be expressed with an unsigned 32-bit integer. Thus, in the example case, the range 0 to (2**Output'length)-1 resolves to the range 0...4294967295 (232=4294967296), i.e. the full unsigned range that can be expressed with 32 bits.
Note that you'll need to add any wrapping logic manually: VHDL simulators will produce an error when you've reached the maximum value and try to increment by one, even if the synthesized logic will cleanly wrap around to 0.

Resources