Hi guys, I'm trying to generate a clock signal that can be switched between 16MHz, 8MHz and 4MHz, and have a 50% duty cycle (for a data separator/ slicer). Just to make this difficult, I only have a 40MHz master clock to work from... which only has an even integer factor for 4MHz (divide-by- ten). Divide-by-five gets 8MHz, but doesn't give a 50:50 ratio. 16MHz isn't even possible (nearest I can get is 20MHz with a divide-by-two). This is on an Altera Cyclone II 2C20, FBGA484 package, on a Terasic DE1 (actually Altera Cyclone II Starter Board, but the Terasic board is essentially identical) development board. Software is Quartus 9.0. Originally, this seemed like a simple problem to solve -- create a PLL to generate a new set of clocks that were phase-locked to the original 40MHz master clock. Problem is, while I can get the PLL to generate a 16MHz clock, it won't go any lower -- 8MHz and 4MHz produce an alert to the effect of "division ratio not possible." So I figured I'd go about this a different way -- generate a 16MHz clock with the PLL, then divide it down to 8MHz and 4MHz with a pair of DQ flip-flops wired to toggle (or a binary counter, whatever worked). This worked fine when I tied the outputs of the clock divider straight to the clock input on the data separator. This is what I have now: // Instantiate a PLL to convert from 40MHz to 32MHz wire CLK_PLL16MHZ; DatasepClockGen dscg(CLK40MHZ, CLK_PLL16MHZ); // Divide down the 16MHz reference to get 8MHz and 4MHz reg CLK_PLL8MHZ; always @(posedge CLK_PLL16MHZ) CLK_PLL8MHZ = ~CLK_PLL8MHZ; reg CLK_PLL4MHZ; always @(posedge CLK_PLL8MHZ) CLK_PLL4MHZ = ~CLK_PLL4MHZ; wire DATASEP_MASTER_CLK; assign DATASEP_MASTER_CLK = CLK_PLL4MHZ; // Data separator wire SHAPED_DATA, DWIN; DataSeparator _datasep(DATASEP_MASTER_CLK, FD_RDDATA_IN, SHAPED_DATA, DWIN); // For debugging -- REMOVEME! assign debug[3:0] = { DATASEP_MASTER_CLK, FD_RDDATA_IN, SHAPED_DATA, DWIN }; debug[3:0] is a set of output pins, CLK40MHZ is the master clock, CLK_PLL16MHZ is the output from the PLL. I can post the data separator logic as well, but it's basically a Verilog implementation of the circuit shown here: <http://www.analog-innovations.com/SED/FloppyDataExtractor.pdf> And this works fine on its own. I'm aware that there are issues with glitches if I just use a straight multiplexer to switch between clock sources, so I'm using the parameterised "clock_mux" module from the Quartus manuals (<http://www.altera.com/literature/hb/qts/qts_qii51007.pdf>, chapter 6, page 48-50). I added it to my code like this (replacing the DATASEP_MASTER_CLK assignments in the code above): // Mux the clock wire DATASEP_MASTER_CLK; // Clock multiplexer wire [3:0] datasep_clock_selects = { (ACQCON_MFM_CLKSEL == 2'b00), (ACQCON_MFM_CLKSEL == 2'b01), (ACQCON_MFM_CLKSEL == 2'b10), (ACQCON_MFM_CLKSEL == 2'b11) }; wire [3:0] datasep_clocks = { (CLK_PLL16MHZ), // 3.5in ED (1Mbps) (CLK_PLL8MHZ), // 3.5in HD (500kbps) (CLK_PLL4MHZ), // 3.5in DD (250kbps) (CLK_PLL4MHZ) }; // Dummy entry for SEL=0b11 clock_mux #(.num_clocks(4)) _datasep_clock_mux( datasep_clocks, datasep_clock_selects, DATASEP_MASTER_CLK ); This results in a ton of timing violation warnings from the timing analyser, the most notable being these two: Warning: Can't achieve minimum setup and hold requirement DatasepClockGen:dscg|altpll:altpll_component|_clk0 along 9 path(s). See Report window for details. Critical Warning: Timing requirements for slow timing model timing analysis were not met. See Report window for details. Obviously the setup/hold violation is not a "Good Thing (tm)" and it needs resolving ASAP (assuming the design works at all as it is). The question is, how should I go about doing this? I can replace the clock multiplexer with a straight AND/OR multiplexer, which seems to resolve the timing issue (or it did last time I tried it), but this risks causing glitching issues (although the Datasep should reset within about 64 clock cycles). Can anyone suggest a possible solution? This is driving me nuts... probably because the errors from Quartus are about as clear as a pool of mud, and it seems the Quartus "help" file is only serving to make the mud thicker... Thanks, -- Phil. usenet09@philpem.me.uk http://www.philpem.me.uk/ If mail bounces, replace "09" with the last two digits of the current year.
Going mad trying to solve PLL setup/hold timing violation issues in Quartus
A developer encountered setup/hold timing violations in Altera Quartus while attempting to generate switchable 16MHz, 8MHz, and 4MHz clocks for a floppy disk data separator. The discussion highlights the common pitfalls of using ripple clocks and gated clocks in FPGA designs compared to traditional ASIC or discrete logic techniques.
Experienced users recommended transitioning to a fully synchronous design utilizing a single high-frequency master clock and clock enables instead of multiple generated clocks. This approach ensures more reliable timing analysis and hardware stability across different builds and environments.
- Avoid using ripple clocks or flip-flop outputs as clock sources because they introduce uncontrollable clock skew and complicate timing analysis.
- The preferred FPGA design pattern is to use a high-speed master clock combined with clock enable signals to achieve lower effective frequencies.
- Internal to the FPGA, a 50% duty cycle is usually unnecessary; focus instead on synchronous signal processing and proper timing constraints.
- While modern timing tools like Quartus and TRCE can analyze multiple clock domains, relying on asynchronous gated clocks makes designs fragile and thermally sensitive.
- Legacy circuits often require redesign for FPGA architectures to replace asynchronous state transitions with synchronous logic.
The solution is so simple it is not even funny. 1. clk_40Mhz => PLL => clk_32Mhz 2. clk_32Mhz => binary counter => (clk_4Mhz, clk_8Mhz, clk_16Mhz) 3. (clk_4Mhz, clk_8Mhz, clk_16Mhz) => regular mux (do not use clock_mux!) => clk_temp 4. clk_temp => DFF with clk=clk_32Mhz => clk_out
> So I figured I'd go about this a different way -- generate a 16MHz > clock with the PLL, then divide it down to 8MHz and 4MHz with a pair of > DQ flip-flops wired to toggle (or a binary counter, whatever worked).Noooooooo. Generate your 16 MHz clock then use this to drive everything with enable signals to give 8 and 4 MHz. You're then just selecting the active enable signal to get the clock you want. All nice and synchronous, don't generate ripple clocks etc. Nial.
On Wed, 25 Nov 2009 01:51:00 -0800, Michael S wrote:> The solution is so simple it is not even funny. 1. clk_40Mhz => PLL => > clk_32Mhz > 2. clk_32Mhz => binary counter => (clk_4Mhz, clk_8Mhz, clk_16Mhz) 3. > (clk_4Mhz, clk_8Mhz, clk_16Mhz) => regular mux (do not use clock_mux!) > => clk_temp > 4. clk_temp => DFF with clk=clk_32Mhz => clk_outThat works about as well as my original code... // Instantiate a PLL to convert from 40MHz to 32MHz wire CLK_PLL32MHZ; DatasepClockGen dscg(CLK40MHZ, CLK_PLL32MHZ); // Divide down the 32MHz reference to get 16MHz, 8MHz and 4MHz reg [2:0] DatasepClkDiv; always @(posedge CLK_PLL32MHZ) DatasepClkDiv <= DatasepClkDiv + 1; // Clock multiplexer reg DATASEP_CLK_pre; always @(ACQCON_MFM_CLKSEL or DatasepClkDiv) begin case (ACQCON_MFM_CLKSEL) 2'b00: DATASEP_CLK_pre = DatasepClkDiv [0]; 2'b01: DATASEP_CLK_pre = DatasepClkDiv [1]; 2'b10: DATASEP_CLK_pre = DatasepClkDiv [2]; default: DATASEP_CLK_pre = DatasepClkDiv [0]; endcase end // Sync clock against 32MHz master clock to remove glitches reg DATASEP_MASTER_CLK; always @(posedge CLK_PLL32MHZ) DATASEP_MASTER_CLK <= DATASEP_CLK_pre; produces: Warning: Can't achieve minimum setup and hold requirement DatasepClockGen:dscg|altpll:altpll_component|_clk0 along 1 path(s). See Report window for details. Critical Warning: Timing requirements for slow timing model timing analysis were not met. See Report window for details. So the same problem as before, basically... Thanks, -- Phil. usenet09@philpem.me.uk http://www.philpem.me.uk/ If mail bounces, replace "09" with the last two digits of the current year.
Sorted it... I found this article a few hours ago: <http://www.fpga-site.com/kiss.html> ... and just got around to reading it. That got me thinking... maybe it's the data-separator that's upsetting the timing analyser, not the clock divider. So I started looking for gated clocks in the separator -- turns out the Data Window flip-flop is wired to toggle (i.e. divide its clock by two; not-Q wired to D), and is clocked from the most significant bit of the DPLL shift register... module DataSeparator(MASTER_CLK, FD_RDDATA_IN, SHAPED_DATA, DWIN); input MASTER_CLK; // Master Clock -- Data rate * 16 input FD_RDDATA_IN; // L->H on flux transition output SHAPED_DATA; // Reshaped data pulses output DWIN; // Data Window ///////////////////////////////////////////////////////////////////////////// // "Phase-jerked loop" data separator // Designed by James Thompson, Analog Innovations, Phoenix AZ. // Verilog implementation by Phil Pemberton // Declare flipflops reg u2a, u2b; // U2A -- first synchroniser. wire u2a_nPreset = u2b; always @(posedge FD_RDDATA_IN or negedge u2a_nPreset) begin if (!u2a_nPreset) begin u2a <= 1'b1; end else begin u2a <= 1'b0; end end // U2B -- second synchroniser wire u2b_clk = !MASTER_CLK; always @(posedge u2b_clk) begin u2b <= u2a; end // U4A -- provides SHAPED_DATA reg SHAPED_DATA; always @(posedge u2b_clk or negedge u2b) begin if (!u2b) begin // clear SHAPED_DATA <= 1'b0; end else begin SHAPED_DATA <= u2b; // clock; D=u2b's output end end // PJL shift register reg [7:0] pjl_shifter; always @(posedge MASTER_CLK or negedge u2b) begin if (!u2b) begin // Asynchronous CLEAR pjl_shifter <= 8'b0000_0000; end else begin // Clock pjl_shifter <= {pjl_shifter[6:0], !pjl_shifter [7]}; end end // PJL output register reg DWIN; always @(posedge pjl_shifter[7]) begin DWIN <= ~DWIN; end endmodule A closer look in the timing report showed the path... clk0 output of the PLL to the MSB of the shifter. Hm. I've rewritten the last block like this: // Latch the state of the SR output reg srout; always @(posedge MASTER_CLK) begin srout <= pjl_shifter[7]; end // PJL output register reg DWIN; always @(posedge srout) begin DWIN <= ~DWIN; end So now the output is clocked from the master clock, thus making most of the data separator synchronous (the only exception I can see is the first input synchronisation FF, U2A), and eliminating the timing issue. But now I'm wondering if there's a better way to do this... I've got a design for a state machine based data separator from a Western Digital application note[1], but it suffers from a similar issue -- a DQ f/f wired to toggle, clocked from the MSB output of the state machine PROM. Making sense of the logic behind either the Analog Innovations "shift register DPLL" isn't too hard once you start stepping it through, but the WD one is an utter beast... And they very helpfully didn't bother documenting it beyond saying "figure 12 shows a data separator built around a state machine" and providing a ROM dump :-/ [1] "FD179x Application Notes". Western Digital, June 1980; p. 12, "Figure 12: 179x Data Separator." <http://www.bitsavers.org/pdf/ westernDigital/FD179X_Application_Notes_Jun80.pdf> Thanks, -- Phil. usenet09@philpem.me.uk http://www.philpem.me.uk/ If mail bounces, replace "09" with the last two digits of the current year.
On Nov 25, 4:24=A0pm, Philip Pemberton <usene...@philpem.me.uk> wrote:> Sorted it... > > So I started looking for gated clocks in the separator -- turns out the > Data Window flip-flop is wired to toggle (i.e. divide its clock by two; > not-Q wired to D), and is clocked from the most significant bit of the > DPLL shift register... >You're going about this all wrong, internal generated clocks do not (repeat that 50 times) in FPGA designs. There is an inherent clock skew that you can not control and will eventually doom your design. This skew is not unique to FPGAs, it happens if you design it with discrete parts, the difference is that inside the FPGA there is nothing you can do to compensate for it. Ias Nial suggested, the way to do this is to use one (count them...one) clock and generate clock enable signals. In your case, take the 40 MHz into a PLL to generate 80 MHz. The entire design runs off of the 80 MHz. One set of things that will run off of the 80 MHz will be a set of clock enable generators: - Count 0 to 4 to generate 16 MHz clock enable - Count 0 to 9 to generate 8 MHz clock enable - Count 0 to 19 to generate 4 MHz clock enable (Bonus points for noticing that a single counter from 0 to 19 can be used to generate all three clock enables) Your stated requirement of "..a 50% duty cycle (for a data separator/ slicer)." seem suspicious. All these timing errors that Quartus is (validly) complaining about are for internal signals. Internal to the device there will not be a requirement for any particular duty cycle. If you data separator/slicer does have such a requirement, then it needs to be redesigned to work in an FPGA environment.> > So now the output is clocked from the master clock, thus making most of > the data separator synchronous (the only exception I can see is the first > input synchronisation FF, U2A), and eliminating the timing issue. >See? Not that hard.> But now I'm wondering if there's a better way to do this... I've got a > design for a state machine based data separator from a Western Digital > application note[1], but it suffers from a similar issue -- a DQ f/f > wired to toggle, clocked from the MSB output of the state machine PROM. >There are all sorts of ASIC design technique that are not usable in FPGAs. They are different environments with different design constraints. Kevin Jennings
On Wed, 25 Nov 2009 19:19:45 -0800, KJ wrote:> Your stated requirement of "..a 50% duty cycle (for a data separator/ > slicer)." seem suspicious. All these timing errors that Quartus is > (validly) complaining about are for internal signals. Internal to the > device there will not be a requirement for any particular duty cycle. If > you data separator/slicer does have such a requirement, then it needs to > be redesigned to work in an FPGA environment.OK, I think I need to do a bit more of an explanation, but you're going to need the circuit diagram for the original version of the circuit for it to make much sense. This is on http://www.analog-innovations.com/SED/ FloppyDataExtractor.pdf. What the circuit does is take an MFM encoded stream from a floppy disc, then produce a Data Window signal from that. If a READ_DATA pulse is detected within the data window, a '1' is clocked into a 16-bit shift register elsewhere in the circuit. If no transition is detected, then a '0' is clocked in. The goal is to have a signal that looks like this when a data pulse occurs: ----+ +----- DWIN |______| -------++------- DATA || The three flip-flops on the left synchronise the read-data signal against the master clock and shape it -- SHAPED_DATA is READ_DATA, but processed so that it's low for exactly two MASTER_CLK cycles. Now back to the data separator. This consists of an 8-bit shift register which is wired to count up and down in a sequence of n=16 (that is, 16 possible states) -- I can't remember the exact sequence off hand, but running the SR+inverter for about 16 clock cycles with CLEAR wired inactive should be sufficient to list them. The sequence is basically a triangle-wave -- the SR outputs count up from 00 to FF, then down to 00 again. The Q7 (MSB) output from the SR is used to clock a DQ flip-flop (which is wired to toggle) and change the state of DWIN. When a RD_DATA pulse is detected, the shift register is cleared back to 0. Depending on where the pulse occurs, the DWIN edge is advanced or delayed by the value of the counter. This has the effect of compensating for any shift in the input (RD_DATA) signal that is caused by the speed of the disc drive motor varying over time. I doubt the DWIN flip-flop won't be affected if it's wired "as presented" (CLK=shiftreg[7], CLKE=1), but with the alterations (CLKE=shiftreg[7], CLK=MASTERCLK) I'm not so sure... Thanks, -- Phil. usenet09@philpem.me.uk http://www.philpem.me.uk/
> OK, I think I need to do a bit more of an explanation, but you're going > to need the circuit diagram for the original version of the circuit for > it to make much sense. This is on http://www.analog-innovations.com/SED/ > FloppyDataExtractor.pdf.Phil, You need to forget the original circuit apart from working out what it does. Then go and read up on synchronous FPGA design. YOU DO NOT WANT TO GENERATE AND USE RIPPLE CLOCKS IN AN FPGA. The tools aren't designed to handle/analyse them. Nial.
rOn Thu, 26 Nov 2009 12:05:24 -0000, "Nial Stewart" <nial*REMOVE_THIS*@nialstewartdevelopments.co.uk> wrote:>YOU DO NOT WANT TO GENERATE AND USE RIPPLE CLOCKS IN AN FPGA. >This maybe true to some extent>The tools aren't designed to handle/analyse them.but this is simple not true in general, especially for the analyse case. Here is what a timing report from Xilinx flow looks like: ========================================= Timing constraint: TS_clkdiv2 = PERIOD TIMEGRP "clkdiv2" TS_clk / 2 HIGH 50%; 9 paths analyzed, 9 endpoints analyzed, 8 failing endpoints 8 timing errors detected. (8 setup errors, 0 hold errors, 0 component switching limit errors) Minimum period is 3.108ns. -------------------------------------------------------------------------------- Slack (setup path): -0.608ns (requirement - (data path - clock path skew + uncertainty)) Source: datar1_6 (FF) Destination: dataout_6 (FF) Requirement: 2.500ns Data Path Delay: 0.971ns (Levels of Logic = 0) Clock Path Skew: -2.102ns (1.205 - 3.307) Source Clock: clk_BUFGP rising at 0.000ns Destination Clock: clkdiv2 rising at 2.500ns Clock Uncertainty: 0.035ns ... So TRCE is perfectly capable (I'm sure Quartus Timer is similarly so) of timing the source and target clock delays and reporting a path between the two clocks correctly. Whether you are interested/capable of fixing this issue is another problem but I don't think it's necessary to blame the tools, at least not anymore. -- Muzaffer Kal DSPIA INC. ASIC/FPGA Design Services http://www.dspia.com
> So TRCE is perfectly capable (I'm sure Quartus Timer is similarly so) > of timing the source and target clock delays and reporting a path > between the two clocks correctly. Whether you are interested/capable > of fixing this issue is another problem but I don't think it's > necessary to blame the tools, at least not anymore.Aye, that was badly worded, although I wouldn't fancy having to get a design working with a multitude of ripple clocks driving between clock domains! Nial





