W
William Wallace
Guest
THE IMPORTANCE OF PROVIDING A RESET THAT LEAVES THE RESET
SYNCHRONOUSLY EVEN IF IT DRIVES THE ASYNCHRONOUS RESET:
Consider a simple one hot state machine that cycles through 3 states:
S001: 001
S010: 010
S100: 100
S001: 001
S010: 010
S011: 100
This is a simple, trivial state machine, but it will serve the purpose
of highlighting why you should leave reset synchronously.
What happens if the asynchronous reset comes at a time and has delays
such that two of the flops to see clock N as the first clock, but the
third flop to see clock N+1 as the first clock. Your state machine
might end up running like so:
S001: 001
Invalid: 011
Invalid: 110
Invalid: 101
Invalid: 011
Invalid: 110
Invalid: 101
Two flip flops are hot. This is bad.
You could get around this by treating your one hot as a binary encoded
state machine, and treating all other states other than {001, 010,
100} as dead end states that must transition to one of the valid
states, but in doing so, you loose the advantages of a one hot state
machine (specifically, the combinatorial logic required to protect
against these dead end states may make it harder to meet timing, and
may chew up more resources than you want).
A different approach would be to process your reset into the FPGA such
that the entire design is reset asynchronously, but the majority of
the design leaves reset synchronously (though under control of the
asynchronous reset input)
E.g., (and not syntax checked):
process(clk,iReset)
begin
if(iReset='1') then
ResetSR="00";
elsif(clk'event and clk = '1') then
ResetSR(0) <= '1';
ResetSR(1) <= ResetSR(0);
end if;
end process;
RESET <= ResetSR(1);
simplesm : process(clk,RESET)
begin
if(Reset = '1') then -- NOTE, this is not iReset
state <= S001;
elsif(clk'event and clk='1') then
case state is =>
when S001 =>
state <= S010;
when S010 =>
state <= S100;
when S100 =>
state <= S001;
end case
end if
end process simplesm;
Here, if the path delays on the internal signal RESET are less than
the clock period, all three registers used to implement the state
machine will see the same first clock after reset.
Any thoughts? (Probably pretty obvious to some who have actually
encountered problems due to different registers in a design seeing
different first clocks, but it wasn't so obvious to me until somebody
recently recommended this practice to me, since I never had a problem
that I traced back to this type of issue.)
But for this to work, static timing analysis tools should check path
delays on the internal RESET signal to make sure it makes it to all
the registers asynchronous resets before the clock after it was
generated.
Do static timing analysis tools do this?
SYNCHRONOUSLY EVEN IF IT DRIVES THE ASYNCHRONOUS RESET:
Consider a simple one hot state machine that cycles through 3 states:
S001: 001
S010: 010
S100: 100
S001: 001
S010: 010
S011: 100
This is a simple, trivial state machine, but it will serve the purpose
of highlighting why you should leave reset synchronously.
What happens if the asynchronous reset comes at a time and has delays
such that two of the flops to see clock N as the first clock, but the
third flop to see clock N+1 as the first clock. Your state machine
might end up running like so:
S001: 001
Invalid: 011
Invalid: 110
Invalid: 101
Invalid: 011
Invalid: 110
Invalid: 101
Two flip flops are hot. This is bad.
You could get around this by treating your one hot as a binary encoded
state machine, and treating all other states other than {001, 010,
100} as dead end states that must transition to one of the valid
states, but in doing so, you loose the advantages of a one hot state
machine (specifically, the combinatorial logic required to protect
against these dead end states may make it harder to meet timing, and
may chew up more resources than you want).
A different approach would be to process your reset into the FPGA such
that the entire design is reset asynchronously, but the majority of
the design leaves reset synchronously (though under control of the
asynchronous reset input)
E.g., (and not syntax checked):
process(clk,iReset)
begin
if(iReset='1') then
ResetSR="00";
elsif(clk'event and clk = '1') then
ResetSR(0) <= '1';
ResetSR(1) <= ResetSR(0);
end if;
end process;
RESET <= ResetSR(1);
simplesm : process(clk,RESET)
begin
if(Reset = '1') then -- NOTE, this is not iReset
state <= S001;
elsif(clk'event and clk='1') then
case state is =>
when S001 =>
state <= S010;
when S010 =>
state <= S100;
when S100 =>
state <= S001;
end case
end if
end process simplesm;
Here, if the path delays on the internal signal RESET are less than
the clock period, all three registers used to implement the state
machine will see the same first clock after reset.
Any thoughts? (Probably pretty obvious to some who have actually
encountered problems due to different registers in a design seeing
different first clocks, but it wasn't so obvious to me until somebody
recently recommended this practice to me, since I never had a problem
that I traced back to this type of issue.)
But for this to work, static timing analysis tools should check path
delays on the internal RESET signal to make sure it makes it to all
the registers asynchronous resets before the clock after it was
generated.
Do static timing analysis tools do this?