(I would post this in EE, but there seem to be even more VHDL questions here ...)
Background: I am using Xilinx Spartan-6LX9 FPGA with Xilinx ISE 14.4 (webpack).
I came across the scary warning "PhysDesignRules: 372 - Gated clock" today, and I see there a lot of discussion about this in general. The consensus seems to be to use one of the DCMs on the FPGA to do the clock separation, but ... my DCM doesn't seem to be able to switch from 32 MHz to 4.096 kHz (it goes to each master at 5 MHz based on 32 MHz ... and it seems absurd to try to bind multiple DCMs for this low-frequency purpose).
My current project uses clk_in to count to the specified value (15265), resets this value to zero and switches the clk_out bit (so I finish the 50% duty cycle, FWIW). It does the job, and I can easily use the cutting edge clk_out to control the next phase of my project. It seems that everything works fine, but ... closed hours (even if it is not in the range where the skew time will be very important). (Note: All watch tests are performed using the rising_edge () function in processes sensitive to that watch.)
So my questions are:
If we are talking about inferring a relatively slow clk_out from a faster clk_in, is gating still considered bad? Or is it the type of “count to x and send the pulse”, which is pretty typical for FPGAs to generate “clocks” in the KHz band, and instead some other unnecessary side effect can cause this warning instead?
Is there a better way to create a low kHz clock from the main MHz clock, bearing in mind that using multiple DCMs seems to be excessive (if possible with a very low output frequency)? I understand that a 50% duty cycle may be superfluous, but assuming that there is one clock input and no use of built-in DCMs, how else can you perform basic clock division using FPGA?
Edit: given the following (where CLK_MASTER is the 32 MHz input clock, and CLK_SLOW is the desired slow cycle, and LOCAL_CLK_SLOW is the way to save the clock state for the entire duty cycle), I found out that this configuration triggers a warning:
architecture arch of clock is constant CLK_MASTER_FREQ: natural := 32000000; -- time := 31.25 ns constant CLK_SLOW_FREQ: natural := 2048; constant MAX_COUNT: natural := CLK_MASTER_FREQ/CLK_SLOW_FREQ; shared variable counter: natural := 0; signal LOCAL_CLK_SLOW: STD_LOGIC := '0'; begin clock_proc: process(CLK_MASTER) begin if rising_edge(CLK_MASTER) then counter := counter + 1; if (counter >= MAX_COUNT) then counter := 0; LOCAL_CLK_SLOW <= not LOCAL_CLK_SLOW; CLK_SLOW <= LOCAL_CLK_SLOW; end if; end if; end process; end arch;
While this configuration does NOT raise a warning:
architecture arch of clock is constant CLK_MASTER_FREQ: natural := 32000000; -- time := 31.25 ns constant CLK_SLOW_FREQ: natural := 2048; constant MAX_COUNT: natural := CLK_MASTER_FREQ/CLK_SLOW_FREQ; shared variable counter: natural := 0; begin clock_proc: process(CLK_MASTER) begin if rising_edge(CLK_MASTER) then counter := counter + 1; if (counter >= MAX_COUNT) then counter := 0; CLK_SLOW <= '1'; else CLK_SLOW <= '0'; end if; end if; end process; end arch;
So, in this case everything was due to the lack of another (as I said, the 50% duty cycle was initially interesting, but in the end it was not a requirement, and the switch of the “local” clock bit seemed pretty smart at that time ...) I was mostly on the right track, he appears.
What is not clear to me at the moment is why using a counter (which stores many bits) does not cause warnings, but a stored and output bit of the output causes warnings. Thoughts