Search code examples
vhdlfpgaxilinxvivadoregister-transfer-level

How to resolve "Register/latch pins with no clock driven by root clock pin" error in Vivado?


As a learning exercise I am doing some HDMI experiments on an FPGA using VHDL. When coming to implement it in Vivado (2017.1) I am encountering the following warning in the timing report:

There are 11 register/latch pins with no clock driven by root clock pin: Hsync_i_reg/Q (HIGH)

I have opened the implemented schematic and looked for the pin in question. It seems to be connected to the same clock that everything else is connected to (and those are not flagged in the timing report), so I am confused as to what the errors above are referring to. Here are some shots from the schematics:

enter image description here enter image description here

Here is the VHDL code of the offending design:

library ieee;
use ieee.std_logic_1164.all;

entity ctrl_gen is
    generic (
        ha: integer := 96; --hpulse
        hb: integer := 144; --hpulse+hbp
        hc: integer := 784; --hpulse+hbp+hactive
        hd: integer := 800; --hpulse+hbp+hactive+hfp
        va: integer := 2; --vpulse
        vb: integer := 35; --vpulse+vbp
        vc: integer := 515; --vpulse+vbp+vactive
        vd: integer := 525 --vpulse+vbp+vactive+vfp
    );
    port (
        clk25: in std_logic; --tmds clock (25mhz)
        hsync: out std_logic; --horizontal sync
        vsync: out std_logic; --vertical sync
        hactive: out std_logic; --active portion of hsync
        vactive: out std_logic; --active portion of vsync
        dena: out std_logic --display enable
    );
end entity;

architecture behavioral of ctrl_gen is
    signal hsync_i, hactive_i, vactive_i, vsync_i : std_logic;
begin
    -- horizontal signals generation
    hproc : process (clk25)
        variable hcount: integer range 0 to hd := 0;
    begin
        if rising_edge(clk25) then
            hcount := hcount + 1;

            if (hcount=ha) then
                hsync_i <= '1';
            elsif (hcount=hb) then
                hactive_i <= '1';
            elsif (hcount=hc) then
                hactive_i <= '0';
            elsif (hcount=hd) then
                hsync_i <= '0';
                hcount := 0;
            end if;
        end if;
    end process;

    -- vertical signals generation
    vproc : process (hsync_i)
        variable vcount: integer range 0 to vd := 0;
    begin
        if falling_edge(hsync_i) then
            vcount := vcount + 1;

            if (vcount=va) then
                vsync_i <= '1';
            elsif (vcount=vb) then
                vactive_i <= '1';
            elsif (vcount=vc) then
                vactive_i <= '0';
            elsif (vcount=vd) then
                vsync_i <= '0';
                vcount    := 0;
            end if;
        end if;
    end process;

    dena <= hactive_i and vactive_i;
    hsync <= hsync_i;
    vactive <= vactive_i;
    hactive <= hactive_i;
end behavioral;

On reflection, I think that the warning is telling me that Hsync_i_reg/Q is the clock used for the Vcount registers, not that Hsync_i_reg itself if not connected to the root clock pin?

Is the method I have used bad practice and unlikely to work? The overall design is not working and I'm trying to understand whether this is the cause.

Thanks.


Solution

  • I see potential design issues. First being the use of variable for objects that are actually clocked signals. Secondly, you're using a generated signal as a clock input. That's also not nice.

    I would modify your code to the following (not tested if it completely does what your code did before)

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity ctrl_gen is
        generic (
            ha: integer := 96; --hpulse
            hb: integer := 144; --hpulse+hbp
            hc: integer := 784; --hpulse+hbp+hactive
            hd: integer := 800; --hpulse+hbp+hactive+hfp
            va: integer := 2; --vpulse
            vb: integer := 35; --vpulse+vbp
            vc: integer := 515; --vpulse+vbp+vactive
            vd: integer := 525 --vpulse+vbp+vactive+vfp
        );
        port (
            clk25: in std_logic; --tmds clock (25mhz)
            hsync: out std_logic; --horizontal sync
            vsync: out std_logic; --vertical sync
            hactive: out std_logic; --active portion of hsync
            vactive: out std_logic; --active portion of vsync
            dena: out std_logic --display enable
        );
    end entity;
    
    architecture behavioral of ctrl_gen is
        signal hsync_i, hactive_i, vactive_i, vsync_i : std_logic;
    
        signal hcount: integer range 0 to hd-1 := 0;
        signal vcount: integer range 0 to vd-1 := 0;
    begin
        -- horizontal signals generation
        hproc : process (clk25)
        begin
            if rising_edge(clk25) then
                if hcount < hd-1 then
                    hcount <= hcount + 1;
                else
                    hcount <= 0;
                end if;
    
                if (hcount=ha-1) then
                    hsync <= '1';
                end if;
                if (hcount=hb-1) then
                    hactive_i <= '1';
                end if;
                if (hcount=hc-1) then
                    hactive_i <= '0';
                end if;
                if (hcount=hd-1) then
                    hsync <= '0';
                end if;
            end if;
        end process;
    
        -- vertical signals generation
        vproc : process (clk25)
        begin
            if rising_edge(clk25) then
                if hcount = hd-1 then -- moment of falling_edge hsync.
                    if vcount < vd-1 then
                        vcount <= vcount + 1;
                    else
                        vcount <= 0;
                    end if;
    
                    if (vcount=va-1) then
                        vsync <= '1';
                    end if;
                    if (vcount=vb-1) then
                        vactive_i <= '1';
                    end if;
                    if (vcount=vc-1) then
                        vactive_i <= '0';
                    end if;
                    if (vcount=vd-1) then
                        vsync <= '0';
                    end if;
                end if;
            end if;
        end process;
    
        dena <= hactive_i and vactive_i;
        vactive <= vactive_i;
        hactive <= hactive_i;
    end behavioral;