Forum Discussion
Unstable fpga programming using HPS(Agilex3)
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity legacy_baseline_top is
port (
-- Clock and Reset
fpga_reset_n : in std_logic;
fpga_clk_100 : in std_logic;
);
end entity legacy_baseline_top;
architecture rtl of legacy_baseline_top is
-- Component declarations
component altera_std_synchronizer is
generic (
depth : integer := 3
);
port (
clk : in std_logic;
reset_n : in std_logic;
din : in std_logic;
dout : out std_logic
);
end component;
component qsys_top is
port (
clk_100_clk : in std_logic := 'X'; -- clk
clock_bridge_0_out_clk_clk : out std_logic; -- clk
o_pma_cu_clk_clk : out std_logic_vector(0 downto 0); -- clk
iopll_0_locked_export : out std_logic; -- export
reset_bridge_0_in_reset_reset_n : in std_logic := 'X'; -- reset_n
reset_reset_n : in std_logic := 'X'; -- reset_n
reset_bridge_pll_in_reset_reset_n : in std_logic := 'X'; -- reset_n
ninit_done_ninit_done : out std_logic; -- ninit_done
h2f_reset_reset : out std_logic -- reset
);
end component qsys_top;
-- Internal signals
signal system_clk_100 : std_logic;
signal pll_clk_100 : std_logic;
signal pll_locked : std_logic;
signal pll_locked_stable : std_logic;
signal ninit_done : std_logic;
signal combined_reset_n : std_logic;
signal system_reset_n : std_logic;
signal pll_reset_n : std_logic;
signal pll_reset_sync_n : std_logic;
signal h2f_reset : std_logic;
begin
-- Concurrent signal assignments
combined_reset_n <= fpga_reset_n and (not h2f_reset) and (not ninit_done);
pll_reset_n <= fpga_reset_n and (not ninit_done);
system_clk_100 <= fpga_clk_100;
-- Reset synchroniser
fpga_reset_n_sync : altera_std_synchronizer
generic map (
depth => 3
)
port map (
clk => system_clk_100,
reset_n => combined_reset_n,
din => '1',
dout => system_reset_n
);
-- Reset synchroniser
pll_reset_n_sync : altera_std_synchronizer
generic map (
depth => 3
)
port map (
clk => system_clk_100,
reset_n => pll_reset_n,
din => '1',
dout => pll_reset_sync_n
);
pll_stable_filter : block
constant CLK_FREQ_HZ : positive := 100_000_000;
constant STABLE_CYCLES : positive := CLK_FREQ_HZ;
signal counter : natural range 0 to STABLE_CYCLES := 0;
signal stable_r : std_logic := '0';
begin
p_filter : process (system_clk_100, pll_reset_sync_n) is
begin
if pll_reset_sync_n = '0' then
counter <= 0;
stable_r <= '0';
elsif rising_edge(system_clk_100) then
if pll_locked = '0' then
counter <= 0;
stable_r <= '0';
elsif counter = STABLE_CYCLES - 1 then
stable_r <= '1';
else
counter <= counter + 1;
stable_r <= '0';
end if;
end if;
end process p_filter;
pll_locked_stable <= stable_r;
end block pll_stable_filter;
soc_inst : qsys_top
port map (
clk_100_clk => system_clk_100,
clock_bridge_0_out_clk_clk => pll_clk_100, --clock out from pll
reset_reset_n => system_reset_n,
iopll_0_locked_export => pll_locked,
reset_bridge_pll_in_reset_reset_n => pll_reset_n, --Reset to pll
reset_bridge_0_in_reset_reset_n => pll_locked_stable, --This goes into a reset bridge in nios with deassert synced to output clock from pll
ninit_done_ninit_done => ninit_done,
h2f_reset_reset => h2f_reset
);Hi, thank you for answering, I have included your suggestions in my code.
Here is the top file of my project, I have removed everything not related to clk/reset.
Everything inside qsys including all HPS bridges is clocked from the pll_clk_100 and reset using the pll_locked_stable after it has been syncronized to pll_clk_100 so it has a syncronized deassert.
Do you see anything wrong with it?
How will the h2f_reset behave during a reconfiguration, do I need to include it in the reset of the pll?
How long do I need to wait for stable locked from pll?, I currently wait 1 second
I also wonder what will happen if I have any in flight transactions on any of the hps bridges when I start programming the FPGA, cause I use the f2sdram as a communication channel between niosV on the fpga and the HPS, do I need to shut this off manually before fpga programming or will the fpga-manager handle this automatically?
- TienFong_Altera2 months ago
New Contributor
Hi,
Thanks for sharing the top-level code, the nINIT_DONE and PLL-lock gating is on the right track. A few items stand out that likely explain why it is still intermittent.
1. Include h2f_reset in PLL reset
You gate fabric logic with h2f_reset, but PLL reset only uses ninit_done:
pll_reset_n <= fpga_reset_n and (not ninit_done) and (not h2f_reset);
During reconfiguration the HPS asserts h2f_reset as part of the bridge warm-reset handshake. The PLL should also be held in reset when h2f_reset is active, so bridge clocking stops cleanly before the fabric is wiped.
2. Avoid clocking HPS bridges from the fabric PLLYou mentioned all HPS bridges are clocked from pll_clk_100. This is the most likely root cause of the remaining intermittent failure.
During overlay programming the fabric PLL is destroyed and rebuilt while the HPS keeps running. nINIT_DONE gating protects logic after user mode is reached, but it cannot prevent the PLL clock from glitching or stopping during the programming window.
Recommended split:
fpga_clk_100 (pin clock) → HPS bridge infrastructure, reset synchronizers, handshake logic PLL outputs → application logic only (Nios, custom IP, derived clocks)
This matches your observation that direct pin clocking is always stable.
3. Connect h2f_reset to bridge AXI reset in Platform Designer
Ensure h2f_reset is connected to f2sdram_axi_reset (and other bridge resets as applicable). The HPS uses this handshake to freeze/reset bridges during reconfiguration.
4. PLL lock wait time
1 second is very conservative. IOPLL lock is typically well below 1 ms. The filter itself is fine, but the intermittent failure is unlikely due to insufficient wait time, it is more related to bridge clocking and in-flight transactions.
5. In-flight f2sdram transactions, manual quiesce required
The Linux fpga-manager disables/freezes bridges before programming, but it does not stop your Nios application or HPS-side protocol.
If either side has active f2sdram traffic when programming begins, in-flight AXI transactions can hang the system (consistent with SMMU timeout and cold reset).
Before each overlay apply:
• Stop HPS-side f2sdram access
• Signal Nios to stop and idle
• Wait until both sides confirm idle
• Apply overlay
• After reconfig (nINIT_DONE deasserted + PLL re-lock), restart communication
Suggested debug steps
• Apply the pll_reset_n fix above
• Move bridge clocking to fpga_clk_100; keep PLL for application logic only
• Add Signal Tap on ninit_done, h2f_reset, pll_locked, pll_clk_100 during overlay apply
• Test reconfig loop with all f2sdram traffic stopped
If you can confirm whether f2sdram is active during the reconfig attempts, that would help narrow this further.
Regards,
Tien Fong - KianHinT_altera1 month ago
Frequent Contributor
Hi,
As the case been idling for quite awhile and answer already provided, i will transition this case to community support.
Thanks
Regard
Kian