Do I need to reset my FPGA design after startup?
For Xilinx FPGAs, the Answer Record AR# 44174 confirms that:
Timing violations can occur with flip-flops and SRLs since GWE is releasing synchronous elements with respect to the configuration clock instead of the user's system clock.
Propagation of the GWE signal means SRLs and flip-flops might be released at slightly different times which results in some parts of the design starting up before others.
So we have two options:
- Stop the user's system clock until startup is completed.
- Automatically apply a reset pulse after GWE or similar is asserted.
If no external reset input is required otherwise in the design, then solution 1 in the Answer Record is useful for Xilinx FPGAs.
- Initially after startup, the clock should be stopped.
- Once the EOS signal asserts from the STARTUP primitive, the clock can be restarted synchronously to the user's systemclock.
- The best way to control this is to use a BUFGCE, BUFR reset, or BUFHCE.
I tried this solution, but Chipscope revealed that not all flip-flops started to toggle at the same time. It seems that the synchronous assertion of the clock enable pin CE
of the BUFGCE
is not that easy.
I recommend to use the second (following) technique instead. Instead of an external reset (reset_pin
below), a '0' zero (no reset) has just to be feed into the reset synchronizer.
If there is an external reset anyway, then the reset synchronizer can be initialized such in a way, that a reset will be asserted after GWE or alike is asserted during the startup sequence. The reset synchronizer will not start the release sequence (i.e. flip-flops toggling towards '0') until GWE is asserted. The duration of the release sequence must be longer than the skew on the GWE. This solution will work on Xilinx and Altera FPGAs.
Declarations:
signal reset_sync : std_logic_vector(1 downto 0) := (others => '1');
signal reset : std_logic;
Architecture Body (register chain):
reset_sync <= reset_sync(reset_sync'high-1 downto 0) & reset_pin when rising_edge(clock);
reset <= reset_sync(reset_sync'high); -- active-high
Of course, the counter logic now requires a reset:
process(clock)
begin
if rising_edge(clock) then
if reset = '1' then
counter <= x"55555555_55555555_55555555_55555555_55555555_55555555_55555555_55555555";
else
counter <= counter(0) & counter(counter'left downto 1);
end if;
end if;
end process;
The screenshot below shows errors due to the asynchronous assertion of GWE. To provoke these, I omitted the signal initialization, so that, all counter flip-flops were initialized to '0' during configuration. As reset
is asserted from the beginning, one would expect that all flip-flops change to the requested reset value with the first rising clock-edge after GWE is asserted. But, at time 0 (T marker), the counter value is not a sequence of x"5". Due to the reset-chain, the expected reset value is restored. The reset is released in cycle 2 (X marker), so that all flip-flops toggle in sub-sequent cycles. The clock frequency here is 200 MHz.
You should assume the clock input to your flip-flops is toggling unless you can prove otherwise (by a guaranteed power on or post configuration delay). All the flip-flops on a given clock domain are not guaranteed to start on the same clock edge based on GWE or GSR. Both act like an asynchronous reset and cause potential problems for some logic (counters, one-hot state machines, etc).
Specifically a one-hot state-machine that transitions immediately after configuration WILL (eventually) FAIL (transition to an invalid state). The frequency of failure will depending on the clock period compared to the device (and place and route) specific skew for your design.
Another simple experiment to see this behavior initialize a relatively fast count down counter with 10000000 and look at its behavior immediately after configuration. Some bits make the transition to 01111111 and some bits miss that first transition but the subsequent counting sequence will be correct.
The white paper mentioned by Krunal Desai talks about this very problem and is a great reference. Any SRAM based FPGA will most likely have a similar issue.
There is no need to reset the registers to get a known value. If you have logic that is sensitive to all starting on the same clock edge will need to add synchronization logic (this can consist of a synchronously de-asserted reset or other synchronous logic). Xilinx AR44174 talks about the issue a little more. I would add a third method of mitigation which is to guarantee clocked logic is not changing/transitioning during the first several clock cycles after startup.