Catalin-Ioan Narita
Catalin-Ioan Narita

Reputation: 11

Gated clock warning

I'm new in everything that involves VHDL physical description code, I have a university project to finish (four different text animations on a Nexys2 or Nexys3 board) and I keep getting this warning messages:

WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg1_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg3_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg2_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg4_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.

Here is the link to all of the source files (I'm working in Ise Design Suite 14.7) http://www.fileshare.ro/e31590660

Edit: Unfortunately, I've spent almost half a day and I'm still not able to pinpoint precisely where the problem lies. I can only say very roughly though that it's in the process that's in the code below(line 73 and on).

 library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Folosim mai jos pachetul nostru
use work.Constante_si_componente.all;          

entity Optiune1 is   
    port(
    clk_50M:in std_logic;
    reset:in std_logic;
    catozi: out std_logic_vector(0 to 6);
    anozi: out std_logic_vector(0 to 3);
    opt1, opt2, opt3, opt4: in std_logic);
end entity;

architecture Behavioral of Optiune1 is   

-- Instantierea semnalelor locale
signal local_clk_1Hz: std_logic;
signal local_clk_1Khz: std_logic;  
signal adresa: integer range 0 to nr_cuvinte_distincte-1;       
signal sec_4: integer range 0 to limita_sup:=0; -- Numara exact 5 secunde
signal cuvant: std_logic_vector(lungime_cuvinte-1 downto 0);   
signal reg1, reg2, reg3, reg4: std_logic_vector(0 to 6):=(others=>'0');  
signal temp_reg1, temp_reg2, temp_reg3, temp_reg4: std_logic_vector(0 to 6) := (others=> '0');

-- Declarare componente   
component ROM 
    port (addr : in integer range 0 to nr_cuvinte_distincte-1;
          data: out std_logic_vector(lungime_cuvinte-1 downto 0));
end component ROM;      
component numarator 
    port(reset: in std_logic;
         clk: in std_logic; 
         limita_numarare: in integer;
         count: out integer range 0 to limita_sup);

end component; 
component registru
    port(clk_1Hz: in std_logic;
         reset: in std_logic;
         write_mode: in std_logic;
         input: in std_logic_vector(0 to 6);
         output: out std_logic_vector(0 to 6));
end component; 
component RRate 
    port(clk_1KHz: in std_logic;
    reg1, reg2, reg3, reg4: in std_logic_vector(0 to 6);
    catozi: out std_logic_vector(0 to 6);
    b:out std_logic_vector(0 to 3));
end component;

begin               
    -- Instantiem divizoarele de tact
    COMP_CLOCK_tat: divizor port map(clk_50M=>clk_50M, reset => reset, clk_1Hz => local_clk_1Hz, clk_1KHz=>local_clk_1KHz);


    -- Instantiem numaratorul
    Numarator_1: numarator port map(reset => reset, clk => local_clk_1Hz, limita_numarare => nr_cuvinte_distincte-1, count => adresa);      
    Numarator_2: numarator port map(reset => reset, clk => local_clk_1Hz, limita_numarare => 4, count => sec_4);

    -- Instantiem memoria
    Memorie1: ROM port map(addr => adresa, data => cuvant);

    -- Instantiem registrul
    Registrul_1: registru port map(local_clk_1Hz, reset, '1', temp_reg1, reg1);   
    Registrul_2: registru port map(local_clk_1Hz, reset, '1', temp_reg2, reg2);
    Registrul_3: registru port map(local_clk_1Hz, reset, '1', temp_reg3, reg3);
    Registrul_4: registru port map(local_clk_1Hz, reset, '1', temp_reg4, reg4);  

    -- Instantiem refresh rate-ul de la anozi
    Refresh_Rate: RRate port map (local_clk_1KHz, reg1, reg2, reg3, reg4, catozi, anozi);

    process(opt1, opt2, opt3, opt4, local_clk_1Hz, temp_reg1, temp_reg2, temp_reg3, temp_reg4, cuvant, sec_4) 
    begin
        if(opt1='1')and(opt2='0')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then     
            temp_reg1 <= cuvant;
            temp_reg2 <= temp_reg1;
            temp_reg3 <= temp_reg2;
            temp_reg4 <= temp_reg3;         
        elsif(opt1='0')and(opt2='1')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then
            temp_reg4 <= cuvant;
            temp_reg3 <= temp_reg4;
            temp_reg2 <= temp_reg3;
            temp_reg1 <= temp_reg2; 
        elsif(opt1='0')and(opt2='0')and(opt3='1')and(opt4='0')and(local_clk_1Hz='1') then 
            if sec_4 = 0 then 
                temp_reg1 <= cuvant;
            elsif sec_4 = 1 then 
                temp_reg2 <= cuvant;
            elsif sec_4 = 2 then
                temp_reg3 <= cuvant;
            elsif sec_4 = 3 then
                temp_reg4 <= cuvant;
            elsif sec_4 = 4 then
                temp_reg1 <= "1111111"; 
                temp_reg2 <= "1111111";
                temp_reg3 <= "1111111";
                temp_reg4 <= "1111111";
            end if;
       elsif(opt1='0')and(opt2='0')and(opt3='0')and(opt4='1')and(local_clk_1Hz='1') then 
            if sec_4 = 0 then 
                temp_reg1 <= cuvant;
            elsif sec_4 = 1 then            
                temp_reg2 <= cuvant;
                temp_reg1<="1111111";
            elsif sec_4 = 2 then
                temp_reg3 <= cuvant;
                temp_reg2<="1111111";
            elsif sec_4 = 3 then
            temp_reg4 <= cuvant;
            temp_reg3<="1111111";
            elsif sec_4 = 4 then
                temp_reg1 <= "1111111"; 
                temp_reg2 <= "1111111";
                temp_reg3 <= "1111111";
                temp_reg4 <= "1111111";
            end if;
        else
            temp_reg1 <= (others => '0');
            temp_reg2 <= (others => '0');
            temp_reg3 <= (others => '0');
            temp_reg4 <= (others => '0');           
        end if;
    end process;

end architecture Behavioral;

Last EDIT: I had to turn in the project yesterday and it worked as intended on the Nexys2 FPGA board, and i added David Koontz's multiplexer code to the "Future development" section of the project's documentation.

Thank you vey much for your help :)

Upvotes: 0

Views: 4865

Answers (2)

user1155120
user1155120

Reputation:

After translating all the Romanian names and comments and noting that temp_reg1 - temp_reg4are inputs to registers it doesn't appear you intended latches.

The unintentionally inferred latches are due to a lack of full conditional assignment coverage and there is no guarantee the combinatorial clock (or latch enable) is glitch free due to differences in delay through varying number of 'gate' equivalents in the target device, 'wire' delays due to placement and differences in rise and fall times. Preventing latches requires an assignment under every condition or choice in a case statement, essentially a reachable else or others.

Jonathan notes a loop in simulation caused by the sensitivity list affecting simulation. Getting rid of the sensitivity list issue can be done by breaking up the process into separate multiplexers.

This is an example solution to both of issues. It's implemented with concurrent signal assignment statements.

I added a declaration for component divizor for analysis (it's possible it's located in the non-include package Constante_si_componente).

After genning the three necessary declarations (nr_cuvinte_distincte, limita_sup, and lungime_cuvinte) into a dummy package constante_si_componente and I replaced the process statement.

I added the following local signal instantiations as architecture declarative items:

-- added declarations

    component divizor is
        port (
            clk_50M:    in  std_logic;
            reset:      in  std_logic;
            clk_1Hz:    out std_logic;
            clk_1KHz:   out std_logic
        ) ;
    end component;

    signal some_cond0:     std_logic;
    signal some_cond1:     std_logic;
    signal some_cond2:     std_logic;
    signal some_cond3:     std_logic;

begin

These take the place of the outer if statement conditions specified in the unlabelled process:

-- new concurrent signal assignment statements:

    some_cond0 <= opt1 and not opt2 and not opt3 and not opt4 and local_clk_1Hz;

    some_cond1 <= not opt1 and opt2 and not opt3 and not opt4 and local_clk_1Hz;

    some_cond2 <= not opt1 and not opt2 and opt3 and not opt4 and local_clk_1Hz;

    some_cond3 <= not opt1 and not opt2 and not opt3 and opt4 and local_clk_1Hz;

These could be named to reflect what the conditions represent. It also looks like you could have binary encoded opt1 through opt4 into two signals, they are exclusive.

The idea is primarily to simplify multiplexer description.

The multiplexers are implemented using conditional signal assignments:

MUX1: 
    temp_reg1 <= cuvant    when  some_cond0 = '1' else
                 temp_reg2 when  some_cond1 = '1' else 
                 cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                 sec_4 < 4                                 else
                 "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                 sec_4 = 4                                 else
                 (others => '0');
MUX2:                
    temp_reg2 <= temp_reg1 when  some_cond0 = '1' else
                 temp_reg3 when  some_cond1 = '1' else 
                 cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                 sec_4 < 4                                 else
                 "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                 sec_4 = 4                                 else
                 (others => '0');
MUX3:                
     temp_reg3 <= temp_reg2 when  some_cond0 = '1' else
                  temp_reg4 when  some_cond1 = '1' else 
                  cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                  sec_4 < 4                                 else
                  "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                  sec_4 = 4                                 else
                  (others => '0');  
MUX4:                 
    temp_reg4 <= temp_reg3 when  some_cond0 = '1' else
                 cuvant    when  some_cond1 = '1' else 
                 cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                  sec_4 < 4                                 else
                 "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                  sec_4 = 4                                 else
                 (others => '0');    

With the multiplexers separated there are no sensitivity lists items causing fall through and there's always an assignment - that final else in each multiplexer.

There are various optimizations you could make in the conditional assignment statements, this example is meant to be traceable to the original process.

If op1 through op4 were encoded on two signals as selects and local_clk_1Hz used as an enable you could instantiate four 4:1 multiplexers lungime_cuvinte wide instead.

After modifying your design it analyzed but without the entity/architecture pairs for divizor, ROM, numarator, registru and RRate I couldn't elaborate or simulate your design.

Addendum

I broke down and downloaded your RAR, cleaned up my modified copy of your question code to work with your header package. It all analyzed, though I knocked out a few unneeded use clauses.

It elaborated but there was a run time simulation error in numarator, caused by inter incrementing beyond the bounds of count, which also says you didn't simulate this first.

The default value for an integer (inter in numarator) is the left bound (typically –2147483647). During initialization there will be an assignment to count (range 0 to limita_sup) which will have a bound check failure.

signal inter: integer; -- acest semnal chiar e intermediar fiindca nu prea

should be type positive instead of integer so the default value falls within the bounds of count, or it should be supplied with a default value within count' bounds (0`).

Upvotes: 1

Jonathan Drolet
Jonathan Drolet

Reputation: 3388

process(opt1, opt2, opt3, opt4, local_clk_1Hz, temp_reg1, temp_reg2, temp_reg3, temp_reg4, cuvant, sec_4) 
begin
    if(opt1='1')and(opt2='0')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then     
        temp_reg1 <= cuvant;
        temp_reg2 <= temp_reg1;
        temp_reg3 <= temp_reg2;
        temp_reg4 <= temp_reg3; 

This is likely wrong. Since your process is combinational, the assignment to temp_reg1 will trigger the process again, which will assign the new value of temp_reg1 to temp_reg2 and so forth. Basically, this assigns cuvant to all 4 temp_regs, but I'm not sure XST can handle the combinational loopback appropriately.

This is probably not what you want anyways. Normally, this sort of process would use assign the regx to temp_regx, this is probably what you want:

temp_reg1 <= cuvant;
temp_reg2 <= reg1;
temp_reg3 <= reg2;
temp_reg4 <= reg3;

As David Koontz pointed out, this code is responsible for the latches:

if sec_4 = 0 then 
    temp_reg1 <= cuvant;
elsif sec_4 = 1 then            
    temp_reg2 <= cuvant;
    temp_reg1<="1111111";
elsif sec_4 = 2 then
    temp_reg3 <= cuvant;
    temp_reg2<="1111111";
elsif sec_4 = 3 then
temp_reg4 <= cuvant;
temp_reg3<="1111111";
elsif sec_4 = 4 then
   temp_reg1 <= "1111111"; 
   temp_reg2 <= "1111111";
   temp_reg3 <= "1111111";
   temp_reg4 <= "1111111";
end if;

In a combinational process, every signals assigned in the process must be assigned in every path through the process, otherwise you will get a latch. In this case, temp_reg2 is not assigned when sec_4 = 0 for example.

Upvotes: 1

Related Questions