Hello Frank,
thanks for your interesting observation.
I continued the investigation and try to summarize my results. I think the state machine viewer has a bug and the compiler inserts redundant logic in special cases:
I used the code which I posted on January 11th, 2008 05:03 PM.
I have 4 different versions:
architecture performancetest of performancetest_1_fsm2conditions_2 is
type STATES is (init, green, yellow, red);
signal state : STATES;
signal reset_timer : std_logic;
signal timer_max : std_logic;
component timer
port(
clk : in std_logic;
reset : in std_logic;
reset_timer : in std_logic;
timer_max : out std_logic
);
end component;
begin
timer1:timer
port map (
clk => clk,
reset => reset,
reset_timer => reset_timer,
timer_max => timer_max
);
process(clk,reset)
variable reset_timer_var : std_logic;
begin
if reset = '1' then
output <= "00";
reset_timer_var := '0';
state <= init;
elsif clk'event and clk = '1' then
reset_timer_var := '0';
if trafficLight_ena = '0' then
reset_timer_var := '1';
state <= init;
else
case state is
when init =>
if trafficLight_ena = '1' then -- removed at version 3 & 4
output <= "00";
reset_timer_var := '1';
state <= red;
else -- removed at version 1 & 3 & 4
state <= init; -- removed at version 1 & 3 & 4
end if;
when green =>
output <= "01";
if timer_max = '1' and input = '0' then
state <= yellow;
else -- removed at version 1 & 3
state <= green; -- removed at version 1 & 3
end if;
when yellow =>
output <= "10";
reset_timer_var := '1';
state <= red;
when red =>
output <= "11";
if timer_max = '1' and input = '1' then
reset_timer_var := '1';
state <= green;
else -- removed at version 1 & 3
state <= red; -- removed at version 1 & 3
end if;
end case;
end if;
reset_timer <= reset_timer_var;
end if;
end process;
end performancetest;
1.: "without else" with redundant if statement
-> removed redundant else statements "state <= actual state";
2.: "with else" with redundant if statement = the posted version
3.: "without else" without redundant if statement
-> removed redundant condition "if trafficLight_ena = '1' then" inside state init
(= dead code because there is a "global" if statement outside the case)
-> removed redundant else statements "state <= actual state";
4.: "with else" without redundant if statement:
-> removed redundant condition "if trafficLight_ena = '1' then" inside state init
(= dead code because there is a "global" if statement outside the case)
If I use sequential state machine encoding all 4 versions are identical (technology map viewer post fit) and the state machine viewer displays the expected transitions.
12 LEs; 9 Reg; 494,56 MHz
init 0 0
green 0 1
yellow 1 0
red 1 1
init init (!trafficLight_ena)
init red (trafficLight_ena)
green init (!trafficLight_ena)
green green (!timer:timer1).(trafficLight_ena) + (timer:timer1).(input).(trafficLight_ena)
green yellow (timer:timer1).(!input).(trafficLight_ena)
yellow init (!trafficLight_ena)
yellow red (trafficLight_ena)
red init (!trafficLight_ena)
red green (timer:timer1).(input).(trafficLight_ena)
red red (!timer:timer1).(trafficLight_ena) + (timer:timer1).(!input).(trafficLight_ena)
If I use one hot state machine encoding I get completely different results and I'm quite sure now that something is wrong!
state machine encoding is equal for all versions:
init 0 0 0 0
green 0 0 1 1
yellow 0 1 0 1
red 1 0 0 1
without else = without redundant default state assignment
1.: "without else" with redundant if statement
=============================
15 LEs; 11 Reg; 380,37 Mhz
- normal state transitions are displayed inside state machine viewer
- at first glance redundant conditions for state transitions
-> state.red <= state.red*tmp + !tmp*trafficLight_en*!(timer_max*(input*state.red) + !input*state.green))
tmp = (trafficLight_en*(!timer_max + !state.green*!input + !state.red*input)*state.init*!state.yellow)
-> tmp comprises all states! so I'm not sure If the compiler generates redundant logic, but tmp is also used for state transition to state.green
- if I use optimization option speed I get the identical result as in version 2
2.: "with else" with redundant if statement = the posted version
=========================================
13 LEs; 10 Reg; 551,27 Mhz
- normal state transitions are displayed inside state machine viewer
- state.init register optimized away
- optimization area, balanced and speed are identical
3.: "without else" without redundant if statement
===============================
14 LEs; 11 Reg; 459,77 Mhz
- normal state transitions are displayed inside state machine viewer
- the transition (the data input for register) for state.red "is as coded"
- optimization area, balanced and speed are identical
4.: "with else" without redundant if statement
=============================
14 LEs; 11 Reg; 459,77 Mhz
- BUG in state machine viewer:
all transitions to state.init are missing in the table and in the chart
- but result is identical to version 3
If I compare the gate level logic for setting state.red register
version 1
state.red <= state.red*tmp + !tmp*trafficLight_en*!(timer_max*(input*state.red) + !input*state.green))
tmp = (trafficLight_en*(!timer_max + !state.green*!input + !state.red*input)*state.init*!state.yellow)
with version 2:
state.red <= trafficLight_ena*!state.green*!(state.red*timer_max*input)
or version 3 / 4:
state.red <= traffic_ena*((state.red*!(timermax*input)) + !(!state.yellow*state.init))
I'm confused about the results, because I coded and intended the same hardware.
In fact version 1 and 2 have identical RTL Viewer and State machine viewer output. But the results are different. I tested the impact of the missing default state assignments at another bigger component and the effect was the same.
I would be happy if someone can verify the State Machine Viewer Bug and halp to investigate the impact of (redundant/non redundant) if conditions outside the case statement in correlation with redundant default state assignments.
TIA,
Axel