Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17266 Discussions

Programmable watchdog in FPGA

Altera_Forum
Honored Contributor II
2,914 Views

Hi all..I am trying to implment a programmable (by microcontoller) watchdog using FPGA..I am using the Altera Megafunction lpm_counter for this purpose. However, my watchdog is generating a lot of warmings ('barking') some of them I don't understand how to fix... 

 

Description: I am using the 50MHz onboard oscillator (DE2) as my clock input and put it through a PLL to generate a 10MHz clock (the lowest one can get from these buildin PLL)..then I am using counter1 to further divide this down to approximately 32787Hz (10,000,000/305) which should give me about 2 second if I am counting down from 65535 to 0 (16bit)...so here is my code... 

 

The warming I am getting is: 

 

Warning: Found combinational loop of 2 nodes 

Warning: Node "inst1|COUNTDOWN_COUNTER|auto_generated|latch_signal[9]~995|combout" 

Warning: Node "inst1|COUNTDOWN_COUNTER|auto_generated|latch_signal[9]~995|dataa" 

 

and there are many of this kind...I am attaching the whole project zipped file to this post as well...any recommendataions are welcomed! 

-------------------------------------------------------------------------------------------------------- 

library ieee; 

use ieee.std_logic_1164.all; 

 

 

LIBRARY lpm; 

USE lpm.all; 

 

entity WDT is  

Generic  

add_WDT: std_logic_vector (15 downto 0) := X"0044" 

); 

port 

reset : in std_logic; -- Hardware reset line from ColdFire 

timeout : out std_logic := '0'; 

datain : in std_logic_vector (15 downto 0); 

dataout : out std_logic_vector (15 downto 0); 

address : in std_logic_vector (15 downto 0); 

CS : in std_logic; 

RW : in std_logic; 

TA : out std_logic := '1'; 

oe : out std_logic; 

q_out : out std_logic_vector (15 downto 0); 

clkin : in std_logic -- 10MHz input clock 

); 

end entity WDT; 

 

architecture sys of WDT is 

 

signal counter1: integer range 304 downto 0; 

 

 

signal WDT: std_logic_vector (15 downto 0); 

 

signal Timer: std_logic_vector (15 downto 0); 

 

signal stop, flag, flag2, load: std_logic; 

 

signal intclk: std_logic; 

 

 

type STATE_TYPE is (S0, S1, S2, S3, S4, S5); -- Delay 

signal SC, NS: STATE_TYPE; 

 

 

component lpm_counter 

generic  

lpm_direction : STRING; 

lpm_port_updown : STRING; 

lpm_type : STRING; 

lpm_width : NATURAL 

); 

PORT  

aload : IN STD_LOGIC; 

cnt_en : IN STD_LOGIC; 

clock : IN STD_LOGIC ; 

q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); 

data : IN STD_LOGIC_VECTOR (15 DOWNTO 0) 

); 

END COMPONENT; 

 

 

begin 

 

clock_divider: process -- this process will divide the 10MHz clock downto approximately 32787Hz  

begin -- therefore, 65536 cycles corresponding to about 2 seconds. 

wait until clkin'event and clkin='1'; 

counter1 <= counter1 + 1; 

if counter1 = 304 then 

intclk <= intclk xor '1'; 

counter1 <= 0; 

end if; 

end process; 

 

 

SYNC_PROC: process -- These following processes take care of ColdFire writes/reads from the watchdog 

begin -- to set and read the countdown time 

wait until clkin'event and clkin = '1'; 

SC <= NS; -- move to next state 

end process;  

 

STATE_PROC: process (SC) 

begin 

case SC is 

when S0 => -- S0 is generally a wait state 

if CS = '0' and RW = '1' then -- ColdFire reads 

NS <= S1; 

elsif CS = '0' and RW = '0' then -- ColdFire writes 

NS <= S3; 

else 

NS <= S0; 

end if; 

 

-- ColdFire reads (S1-S2) 

when S1 => 

if (address = add_WDT ) then 

NS <= S2; 

else 

NS <= S5; 

end if; 

when S2 => 

NS <= S5; 

 

-- ColdFire writese (S3-S6) 

when S3 => 

if (address = add_WDT) then 

NS <= S4; 

else 

NS <= S5; 

end if;  

when S4 => 

NS <= S5;  

 

when S5 => 

if CS = '1' then 

NS <= S0; 

else 

NS <= S5; 

end if; 

end case; 

end process; 

 

READ_PROC: process 

begin 

wait until clkin'event and clkin='1'; 

case SC is  

when S1=> -- ColdFire reads 

TA <= '1'; 

oe <= '1'; 

when S2=> 

dataout <= WDT; 

TA <= '0'; 

oe <= '1'; 

 

when S3=> -- ColdFire writes 

TA<= '1'; 

oe <= '0'; 

when S4=> 

WDT <= datain; 

TA <= '0'; 

oe <= '0'; 

 

when others => 

TA <= '1'; 

oe <= '0'; 

end case; 

end process; 

 

L0AD_PROC: process 

begin 

wait until clkin'event and clkin='1'; 

flag <= reset; 

end process; 

 

LOAD_PROC2: process  

begin 

wait until clkin'event and clkin='0'; 

flag2 <= flag; 

end process; 

 

load <= flag xor flag2; -- Create pulses when reset change states 

 

 

COUNTDOWN_COUNTER : lpm_counter 

generic map  

lpm_direction => "DOWN", 

lpm_port_updown => "PORT_UNUSED", 

lpm_type => "LPM_COUNTER", 

lpm_width => 16 

PORT MAP ( 

aload => load, -- Use the previously created pulse as asynload signal to the counter. 

clock => intclk, 

q => Timer, 

cnt_en => stop, 

data => WDT 

); 

 

q_out <= timer; 

stop <= '0' when timer = X"0000" else '1'; -- If counter reaches 0, stop the count down and 

timeout <= not (stop); -- rise the timeout flag 

 

end architecture;
0 Kudos
14 Replies
Altera_Forum
Honored Contributor II
1,728 Views

Hi, 

 

just a quick glance for now. 

If your state_proc is supposed to be combinatorial ,you must contain all signals read inside process in sensitivity list to avoid trouble. 

 

your intclk must be made global(through assignment editor) 

 

kaz
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

Because the latches are in the COUNTDOWN_COUNTER instance of lpm_counter, I wonder if they result from the asynchronous load. Try setting the top-level entity on the "General" page of the "Settings" dialog box to lpm_counter to see whether you get the warnings for the counter compiled by itself. If you don't, then maybe the problem is somehow in the way you are instantiating the counter and driving it with your logic. 

 

See http://www.alteraforum.com/forum/showthread.php?t=2388 for cautions about the way you are dividing down your clock. 

 

 

General comments I wrote about latches before I saw that yours might be inside the lpm_counter megafunction: 

 

Do not use latches if they are avoidable. 

 

If you have a legitimate use for latches (something that has no suitable clock available, latching data off an asynchronous processor bus, etc.), then check the coding style guidelines in the Quartus handbook to find the correct way to code latches for proper recognition by Quartus integrated synthesis. Also see my post at http://www.alteraforum.com/forum/showthread.php?t=4208.
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

clock constrains as following: 

create_clock -period 20 -name 50MHz [get_ports {50MHz}] 

create_generated_clock -name 10MHz -source [get_ports {50MHz}] -divide_by 5 [get_pins {inst|altpll_component|pll|clk[0]}] 

create_generated_clock -name counter_clock -source [get_pins {inst|altpll_component|pll|clk[0]}] -divide_by 305 [get_registers {WDT:inst1|intclk}] 

 

Does the last constrain make intclk a global? 

Meanwhile, this is only part of the FPGA functionality, so if I make this global clock..What if I have some other clocks for other functionality which is 'more global'?  

 

 

--- Quote Start ---  

Hi, 

 

just a quick glance for now. 

If your state_proc is supposed to be combinatorial ,you must contain all signals read inside process in sensitivity list to avoid trouble. 

 

your intclk must be made global(through assignment editor) 

 

kaz 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

look also at: 

 

stop <= '0' when timer = X"0000" else '1';  

 

the counter enable depends on counter output . Wouldn't the above statement lead to a freeze? 

 

kaz
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

The thread I referred you to at http://www.alteraforum.com/forum/showthread.php?t=2388 discusses the need for a clock to use global routing. 

 

SDC clock constraints have nothing to do with whether a clock will use global routing. Global routing is determined by the combination of the "Auto Global *" settings in the "More Fitter Settings" dialog box and "Global Signal" assignments in the Assignment Editor.
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

Microcontroller suppose to toggle the reset signal which will trigger the counter to load a new value from register WDT everytime reset change state (from 1 to 0 or from 0 to 1)..Once loaded, counter will reflect this new value on timer, therefore timer won't be all 0s..then the counter will start count down... 

 

 

Could be the reason why there're latches? 

 

 

--- Quote Start ---  

look also at: 

 

stop <= '0' when timer = X"0000" else '1';  

 

the counter enable depends on counter output . Wouldn't the above statement lead to a freeze? 

 

kaz 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

 

--- Quote Start ---  

Because the latches are in the COUNTDOWN_COUNTER instance of lpm_counter, I wonder if they result from the asynchronous load. Try setting the top-level entity on the "General" page of the "Settings" dialog box to lpm_counter to see whether you get the warnings for the counter compiled by itself. 

 

... 

 

If you have a legitimate use for latches (something that has no suitable clock available, latching data off an asynchronous processor bus, etc.), then check the coding style guidelines in the Quartus handbook to find the correct way to code latches for proper recognition by Quartus integrated synthesis. 

--- Quote End ---  

 

 

 

I did essentially this with a counter configured the way you configured yours. I got the combinational loops too. I will report this to Altera. If the asynchronous load is going to use latches, it should be done with proper latches. 

 

If you can change to a synchronous load, that would have less risk of timing hazards.
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

OK Zhangy the counter wouldn't freeze.  

If you got same problem as Brad may be you can try infer a counter just like your first one(assuming quartus wouldn't infer the same lpm). 

 

kaz
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

Hello Brad...According to your post on ripper/gated clock, by counting the rising edge of the fast clock 305 times and generate a toggle and use this as a clock signal to feed the counter is a bad idea...so I should rather use this as a clock enable and feed the fast clock directly to the counter? Also, I am better off to use a nonglobal routing for this clock enable signal...Am I right?  

Thanks 

 

 

 

--- Quote Start ---  

Because the latches are in the COUNTDOWN_COUNTER instance of lpm_counter, I wonder if they result from the asynchronous load. Try setting the top-level entity on the "General" page of the "Settings" dialog box to lpm_counter to see whether you get the warnings for the counter compiled by itself. If you don't, then maybe the problem is somehow in the way you are instantiating the counter and driving it with your logic. 

 

See http://www.alteraforum.com/forum/showthread.php?t=2388 for cautions about the way you are dividing down your clock. 

 

 

General comments I wrote about latches before I saw that yours might be inside the lpm_counter megafunction: 

 

Do not use latches if they are avoidable. 

 

If you have a legitimate use for latches (something that has no suitable clock available, latching data off an asynchronous processor bus, etc.), then check the coding style guidelines in the Quartus handbook to find the correct way to code latches for proper recognition by Quartus integrated synthesis. Also see my post at http://www.alteraforum.com/forum/showthread.php?t=4208

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

Yes, the clock enable is better. My other thread says that you can safely use a divided ripple clock by using global routing and having no synchronous cross-domain paths, but a fast PLL clock with a clock enable is still better (for example, the PLL might have less duty cycle distortion than a clock driven by a register). Instead of doing a divide by 305 to create a clock signal, create a clock enable signal that is asserted every 305th period of the fast clock. Note that the clock enable is asserted for just the 305th period--the assertion lasts for one fast-clock period. The registers using the clock enable are clocked by the fast clock. You can use a multicycle setup of 305 and multicycle hold of 305-1=304 for the paths that use the clock enable for both source and destination registers (see http://www.altera.com/support/examples/timequest/exm-tq-clock-enable.html). 

 

The primary reason to use globals is to minimize skew, which usually matters only for clock signals and does not matter for clock enables. Another reason to use globals is for very high fan-out signals to avoid using up lots of nonglobal routing resources; that's why high-fan-out reset signals typically use global routing. 

 

If there are no timing violations for clock enable paths and you do not run out of global resources, then it does not matter whether the clock enable uses global routing. The global buffer has a big delay that can make setup timing worse than it would be with nonglobal routing. If you have setup violations for clock enable paths, then set "Global Signal" to "Off" for the clock enable in the Assignment Editor or turn off automatic global control signals in the "More Fitter Settings" dialog box. Also, synthesis might take your single divide-by-305 clock enable from your RTL and make lots of different smaller clock enable signals that include additional logic from the RTL; if this happens, you'll see multiple clock enables in the "Control Signals" table in the Fitter report. If synthesis creates multiple clock enable signals without a very large fan-out on any individual signal, then there would be no reason to use a global routing resource for any of these just to cut down on the amount of nonglobal routing used.
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

Thanks Brad for your reply. 

 

It doesn't look like the multicycle statment in sdc file has any effects (don't know why)..However, if this clk_en is NOT set as global routing, I ended up glitches in my output (see timeout signal in the attached waveform). If clk_en is set as global routing. I got no problem..plus..If I look at the Fitter--->Control Signals..I don't see this clk_en listed as global signal.. 

Any comments? 

 

 

 

--- Quote Start ---  

Yes, the clock enable is better. My other thread says that you can safely use a divided ripple clock by using global routing and having no synchronous cross-domain paths, but a fast PLL clock with a clock enable is still better (for example, the PLL might have less duty cycle distortion than a clock driven by a register). Instead of doing a divide by 305 to create a clock signal, create a clock enable signal that is asserted every 305th period of the fast clock. Note that the clock enable is asserted for just the 305th period--the assertion lasts for one fast-clock period. The registers using the clock enable are clocked by the fast clock. You can use a multicycle setup of 305 and multicycle hold of 305-1=304 for the paths that use the clock enable for both source and destination registers (see http://www.altera.com/support/examples/timequest/exm-tq-clock-enable.html). 

 

The primary reason to use globals is to minimize skew, which usually matters only for clock signals and does not matter for clock enables. Another reason to use globals is for very high fan-out signals to avoid using up lots of nonglobal routing resources; that's why high-fan-out reset signals typically use global routing. 

 

If there are no timing violations for clock enable paths and you do not run out of global resources, then it does not matter whether the clock enable uses global routing. The global buffer has a big delay that can make setup timing worse than it would be with nonglobal routing. If you have setup violations for clock enable paths, then set "Global Signal" to "Off" for the clock enable in the Assignment Editor or turn off automatic global control signals in the "More Fitter Settings" dialog box. Also, synthesis might take your single divide-by-305 clock enable from your RTL and make lots of different smaller clock enable signals that include additional logic from the RTL; if this happens, you'll see multiple clock enables in the "Control Signals" table in the Fitter report. If synthesis creates multiple clock enable signals without a very large fan-out on any individual signal, then there would be no reason to use a global routing resource for any of these just to cut down on the amount of nonglobal routing used. 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

It is normal for a timing simulation to have glitches on signals if any combinational logic is involved. (I would not expect a glitch on a signal that is driven directly by a register.) As long as the signal is used only synchronously (as is the case for a clock enable) and there are no setup or hold violations, the glitches don't matter. 

 

Are you saying that the clock enable signal is listed correctly as a clock enable in the "Control Signals" table but just not listed as a global? If you are saying it was not listed at all, then did you look only for the name you expected? The name might be different from what you expect. If you are using HDL, you need to code in a style that enables synthesis to recognize the signal in the HDL that you intended to be a clock enable. The Quartus handbook has a chapter on coding guidelines that shows the correct way to code the registers that use the clock enable. If you are saying the signal was identified by the Fitter as a clock enable but just wasn't listed as global when you expected it to be global, then there might be a problem with your "Global Signal" assignment if that's what you are using (verify that the Assignment Editor doesn't have a question mark by the signal name). In TimeQuest you can do something like "report_timing -setup -from [get_registers <name_of_register_driving_clock_enable>]" to see the clock enable paths. For one of these, look at the data arrival path. If you are using global routing, there will be a clock control block in the path.
0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

The lpm_counter was configured as aload, therefore, the clk_en wasn't fed directly into any register..therefore it doesn't show up on the global signal list...funny thing is that if I don't use this clk_en, but using it directly as a divided down clock to fed to this lmp_counter. I have timing issues (setup time/removal time violations)...now it's not used as a clock anymore (rather, it is used as a clock_en) and I am trouble free? 

 

 

 

--- Quote Start ---  

It is normal for a timing simulation to have glitches on signals if any combinational logic is involved. (I would not expect a glitch on a signal that is driven directly by a register.) As long as the signal is used only synchronously (as is the case for a clock enable) and there are no setup or hold violations, the glitches don't matter. 

 

Are you saying that the clock enable signal is listed correctly as a clock enable in the "Control Signals" table but just not listed as a global? If you are saying it was not listed at all, then did you look only for the name you expected? The name might be different from what you expect. If you are using HDL, you need to code in a style that enables synthesis to recognize the signal in the HDL that you intended to be a clock enable. The Quartus handbook has a chapter on coding guidelines that shows the correct way to code the registers that use the clock enable. If you are saying the signal was identified by the Fitter as a clock enable but just wasn't listed as global when you expected it to be global, then there might be a problem with your "Global Signal" assignment if that's what you are using (verify that the Assignment Editor doesn't have a question mark by the signal name). In TimeQuest you can do something like "report_timing -setup -from [get_registers <name_of_register_driving_clock_enable>]" to see the clock enable paths. For one of these, look at the data arrival path. If you are using global routing, there will be a clock control block in the path. 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
1,728 Views

I'm not sure what you're doing, but I repeat my earlier recommendation to change the asynchronous load to a synchronous load if a synchronous load would be suitable for your design. Another possibility is to replace your lpm_counter instantiation with a counter inferred from RTL similar to what you did for your counter that does the divide by 305, but an instantiated lpm_counter with a clock enable port should be fine. 

 

If you really need an asynchronous load, maybe you can use an lpm_latch megafunction (or a latch coded in RTL following the recommended coding style for latches) to capture the asynchronous data and feed the latch output to the synchronous load of lpm_counter. The lpm_latch megafunction will have a proper latch implementation in Quartus unlike the combinational feedback loops you are getting with the lpm_counter asynchronous load. (I did report this lpm_counter design deficiency for asynchronous load to Altera.) 

 

If you still have problems with a synchronous load, try configuring the counter with the MegaWizard in case you did something wrong when you instantiated lpm_counter directly without using the MegaWizard.
0 Kudos
Reply