i'm new to vhdl and fpga. I'm currently working with a basys3 board programmed in vhdl using vivado. I made a 3(binary) to 8(decimal) dencoder with a for loop. My test bench is also with a for loop. What i now notice is strange output flickering between my normal output changes. Could somebody give me a reason for this problem?
main:
entity bindec38 is
Port ( sw : in STD_LOGIC_VECTOR (2 downto 0) := (others => '0');
led : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0'));
end bindec38;
architecture Behavioral of bindec38 is
begin
process (sw)
variable int : integer := 0;
begin
int := to_integer(unsigned(sw));
for j in 0 to 7 loop
if (int = j) then
led(int) <= '1'; -- correct schrijven deze led hoog
else
led(j) <= '0'; -- schrijven de andere dan laag tijdens de loop
end if;
end loop;
end process;
end Behavioral;
test bench:
entity simdec is
-- Port ( );
end simdec;
architecture Behavioral of simdec is
component bindec38 is
Port ( sw : in STD_LOGIC_VECTOR (2 downto 0);
led : out STD_LOGIC_VECTOR (7 downto 0));
end component bindec38;
-- input signal
signal sw : STD_LOGIC_VECTOR (2 downto 0) := (others => '0');
-- output singal
signal led : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
begin
UUT: bindec38
Port Map (sw => sw, led => led);
-- sim process
sim_pro: process begin
for i in 0 to 7 loop
sw <= std_logic_vector(to_unsigned(i, 3));
wait for 100 ns;
end loop;
wait;
end process;
end Behavioral;
see the simulation output simulation it only happens in 2 out of 8 transitions.
-
\$\begingroup\$ wow first time i see this kinda thing in a simulator \$\endgroup\$Mitu Raj– Mitu Raj2018年05月10日 05:08:49 +00:00Commented May 10, 2018 at 5:08
2 Answers 2
You have designed an asynchronous one of n decoder, and carried out a post-implementation or timing simulation.
Because a timing simulation uses the real timing of your placed and routed design, each signal will have fractionally different timing, even if the signals are part of the same logical element, for example sw
in your case.
Whatever logic your FPGA uses to implement the circuit, because it is asynchronous, if the signals arrive at the input to that logic at different times, the output will transition through intermediate states in some cases when your logical element only transitions once. As the other answer points out, these race conditions create runt pulses in the output.
Taking the transition of sw
from 3
to 4
as an example, the possible transitions in the binary signals that represent this number, depending on the detailed routing of these signals in the FPGA are:
"011" > "111" > "110" > "100" = 3 > 7 > 6 > 4
"011" > "111" > "101" > "100" = 3 > 7 > 5 > 4
"011" > "010" > "110" > "100" = 3 > 2 > 6 > 5
"011" > "010" > "000" > "100" = 3 > 2 > 0 > 4
"011" > "001" > "000" > "100" = 3 > 1 > 0 > 4
"011" > "001" > "101" > "100" = 3 > 1 > 5 > 4
"011" > "101" > "100" = 3 > 5 > 4
"011" > "110" > "100" = 3 > 6 > 4
"011" > "100" = 3 > 4
As you can see, depending on the routing and resulting timing, your one of n decoder could see a variety of inputs during the transition in sw
, and so produce a corresponding variety of outputs. Note that the intermediate transitions occur over a very short space of time, typically under 1 nanosecond in a modern FPGA.
Let's compare this to one of the transitions that does not show runts in the output, when sw
goes from 4
to 5
. The possible transitions are:
"100" > "101" = 4 > 5
Since only one bit changes, there is only one possible transition. As a result, you won't see any runts on this transition, no matter how the signals are routed.
Now let's think about how the tools will actually implement your circuit. You can check in the implemented schematic, but each led
output should be driven by a separate Look Up Table (LUT) element. You can use the tools to view the logic equation of each LUT, but essentially they will be looking to see if the 3-bit sw
input corresponds to that particular led
. Where the other answer is wrong is that just because the logic is implemented in a single LUT, it does not mean that these race conditions are a simulation artifact only.
Relating this back to the 3
to 4
transition, because each led
output is implemented in a different LUT, the timing seen by each LUT will be different. We see runt pulses on the 1
, 2
, 6
, and 7
outputs. From this we can deduce that the LUT for led(1)
saw either 3> 1> 0> 4 or 3> 1> 5> 4, led(2)
saw either 3> 2> 6> 5 or 3> 2> 0> 5, and so on.
The common way to avoid runts is to use a synchronous design, i.e. one that uses a clock. Note that for this to work reliably, the input (sw
in this case) must also be synchronous to clk
.
process(clk)
begin
if (rising_edge(clk)) then
led <= (others => '0');
led(to_integer(unsigned(sw)) <= '1';
end if;
end process;
Now, the one of n decoder will still see the varying transitions on the LUT inputs, and have corresponding runts on the LUT outputs, but these outputs then feed a register. Since in a synchronous system that has met timing, the transitions will all have completed by the time the clock edge occurs, the final output will not have any runt pulses.
Another option is to decide that you don't care about these runt pulses. In a design that simply drives some LEDs, you probably don't care if there's a chance of the wrong LED illuminating for 0.5 nanoseconds.
The most important point in all this is that these are not just simulation artifacts, and could cause real world problems in a design.
-
1\$\begingroup\$ If in the bigger picture the thing is being driven by a counter of some form, you can sometimes use Gray codes to avoid the issue with Fabric delays that causes this problem even in the single LUT case (@scary_jeff is right about that). The single LUT case removes the logic delay from the picture, but leaves the propagation times thru the fabric. \$\endgroup\$Dan Mills– Dan Mills2018年05月10日 10:04:58 +00:00Commented May 10, 2018 at 10:04
The tell is that it occurs only when two of the inputs change state simultaneously.....
Basically, at least as far as the simulator is concerned you have a race condition where the logic driving an output has two different paths with different propagation delays, and hence you get a runt pulse until the second set of logic catches up. If you have a lot at the schematic your tool produces you should see this.
Note that this may or may not really happen in a synthesised circuit on a real gate array as my guess will be that with only 3 inputs in play everything will actually collapse to 1 LUT per output which clearly does not have this issue.
This is probably a simulation artefact (But is something you can get in asynchronous logic) in that one path driving those outputs has one more gates worth of delta cycles then another so you see the race condition.