Hi: I'm using a Xilinx Spartan 3E FPGA (on the Digilent NEXYS2 500k board) to implement a quadrature encoder simulator, among other things. The qep_sim.v code is shown below. The clock input to qep_sim() is multiplexed from one of two buffered and isolated external world inputs. The problem is that when the multiplexer selects one clock input, the qep_sim() occasionally counts on a negedge. While, if the other input is used, it never glitches like this and performs correctly. The 288kHz clocks at the point where they enter the NEXYS2 board have been probed and are clean, including when the counting glitch occurs. What is stranger is that if I try to send a copy of the multiplexed clock out to an IO pin to scope it, then the glitching goes away no matter which clock source is selected. Thanks for ideas on what might be wrong. I suspect it has something to do with non-ideal choices of IO pins for the clock inputs. I didn't have time to test this today, but I suspect if I simply move the ext_sim_clk to a different pin, the problem will go away. I wouldn't be satisfied with this however, as I wish to understand the real cause of the problem. Here is the multiplexing code (excerpted from a longer module): module shaft ( // Begin QEP related ports // Switch SW0 selects: 0 = ext_sim_clk, 1 = dsp_sim_clk input clk_mux_sel, // Note: signal dsp_sim_clk is being temporarily supplied for // troubleshooting from an identical external buffer circuit // as the ext_sim_clk: input dsp_sim_clk, // sim clk generated by DSP. input ext_sim_clk, // external sim clk input // diagnostic sim clk output. Problem goes away if this is used: // output sim_clk_o, [edited out many lines] ); wire sim_clk; // muxed sim clk to feed to qep_sim.v // Select the simulation clock source: assign sim_clk = clk_mux_sel ? dsp_sim_clk : ext_sim_clk; // Instantiate the QEP simulator. Source for qep_maxcnt is not shown // here for brevity, and since this isn't being used in qs1 at present. qep_sim qs1( .clk(sim_clk), .maxcnt(qep_maxcnt), .a(qep_a_sim), .b(qep_b_sim), .m(qep_mex_sim) ); // The outputs of qs1 go to another mux, to select the simulator vs. // a real encoder to send to the DSP's QEP counter peripheral. This // code is not shown. endmodule Here's the relevant excerpt from my .ucf file (the sim_clk_o is commented out when the problem is happening): NET "dsp_sim_clk" LOC = "R18" | IOSTANDARD = LVCMOS33; # JB-2 NET "sim_clk_o" LOC = "G15" | IOSTANDARD = LVCMOS33 | SLEW = FAST; # JC-1 NET "ext_sim_clk" LOC = "H16" | IOSTANDARD = LVCMOS33; # JC-4 ------------------------------------------------------------------------ // This module simulates the outputs of a BEI incremental // (quadrature) encoder module qep_sim( input clk, input [15:0] maxcnt, // not used at present, until problem diagnosed output a, output b, output m ); parameter MAX_CNT = 31; // using fixed period during troubleshooting reg [15:0] cnt; always @ (posedge clk) begin if (cnt == MAX_CNT) cnt = 0; else cnt = cnt + 1; end assign a = ~cnt[1]; assign b = cnt[1] ^ cnt[0]; assign m = ~b & (cnt == 0 || cnt == MAX_CNT); // index pulse m is high // straddling max count and zero. Why the redundant '&' with ~b is // performed? I forget. Maybe this is unnecessary. endmodule ------------------------------------------------------------------------ -- _____________________ Mr.CRC crobcBOGUS@REMOVETHISsbcglobal.net SuSE 10.3 Linux 2.6.22.17
Counter clocks on both edges sometimes, but not when different IO pin is used
Started by ●May 14, 2011
Reply by ●May 14, 20112011-05-14
> Thanks for ideas on what might be wrong. I suspect it has something to > do with non-ideal choices of IO pins for the clock inputs. I didn't > have time to test this today, but I suspect if I simply move the > ext_sim_clk to a different pin, the problem will go away.Rather than using these signals as clocks, why not sample the incoming signal with the Nexys2's 50 MHz clock? Register the input and check for rising edges: reg [1:0] ext_clk; always @(posedge clk50) ext_clk[1:0] <= {ext_clk[0], sim_clk}; wire rising_edge = ext_clk[1] & ~ext_clk[0]; and then count these: always @(posedge clk50) if (rising_edge) if (cnt == MAX_CNT) ... Joel
Reply by ●May 14, 20112011-05-14
"Mr.CRC" <crobcBOGUS@REMOVETHISsbcglobal.net> wrote in message news:iqkvcv01c5r@news6.newsguy.com...> Hi: > > I'm using a Xilinx Spartan 3E FPGA (on the Digilent NEXYS2 500k board) > to implement a quadrature encoder simulator, among other things. > > The qep_sim.v code is shown below. The clock input to qep_sim() is > multiplexed from one of two buffered and isolated external world inputs. > > The problem is that when the multiplexer selects one clock input, the > qep_sim() occasionally counts on a negedge. While, if the other input > is used, it never glitches like this and performs correctly. > > The 288kHz clocks at the point where they enter the NEXYS2 board have > been probed and are clean, including when the counting glitch occurs. > > What is stranger is that if I try to send a copy of the multiplexed > clock out to an IO pin to scope it, then the glitching goes away no > matter which clock source is selected. > > Thanks for ideas on what might be wrong. I suspect it has something to > do with non-ideal choices of IO pins for the clock inputs. I didn't > have time to test this today, but I suspect if I simply move the > ext_sim_clk to a different pin, the problem will go away. > > I wouldn't be satisfied with this however, as I wish to understand the > real cause of the problem. > > > Here is the multiplexing code (excerpted from a longer module): > > module shaft ( > // Begin QEP related ports > // Switch SW0 selects: 0 = ext_sim_clk, 1 = dsp_sim_clk > input clk_mux_sel, > // Note: signal dsp_sim_clk is being temporarily supplied for > // troubleshooting from an identical external buffer circuit > // as the ext_sim_clk: > input dsp_sim_clk, // sim clk generated by DSP. > input ext_sim_clk, // external sim clk input > // diagnostic sim clk output. Problem goes away if this is used: > // output sim_clk_o, > [edited out many lines] > ); > > wire sim_clk; // muxed sim clk to feed to qep_sim.v > > // Select the simulation clock source: > assign sim_clk = clk_mux_sel ? dsp_sim_clk : ext_sim_clk; > > // Instantiate the QEP simulator. Source for qep_maxcnt is not shown > // here for brevity, and since this isn't being used in qs1 at present. > qep_sim > qs1( .clk(sim_clk), .maxcnt(qep_maxcnt), > .a(qep_a_sim), .b(qep_b_sim), .m(qep_mex_sim) ); > > // The outputs of qs1 go to another mux, to select the simulator vs. > // a real encoder to send to the DSP's QEP counter peripheral. This > // code is not shown. > > endmodule > > > Here's the relevant excerpt from my .ucf file (the sim_clk_o is > commented out when the problem is happening): > > > NET "dsp_sim_clk" LOC = "R18" | IOSTANDARD = LVCMOS33; # JB-2 > NET "sim_clk_o" LOC = "G15" | IOSTANDARD = LVCMOS33 | SLEW = FAST; # JC-1 > NET "ext_sim_clk" LOC = "H16" | IOSTANDARD = LVCMOS33; # JC-4 > > > > ------------------------------------------------------------------------ > // This module simulates the outputs of a BEI incremental > // (quadrature) encoder > module qep_sim( > input clk, > input [15:0] maxcnt, // not used at present, until problem diagnosed > output a, > output b, > output m > ); > > parameter MAX_CNT = 31; // using fixed period during troubleshooting > > reg [15:0] cnt; > > always @ (posedge clk) begin > if (cnt == MAX_CNT) > cnt = 0; > else > cnt = cnt + 1; > end > > assign a = ~cnt[1]; > assign b = cnt[1] ^ cnt[0]; > assign m = ~b & (cnt == 0 || cnt == MAX_CNT); > // index pulse m is high > // straddling max count and zero. Why the redundant '&' with ~b is > // performed? I forget. Maybe this is unnecessary. > endmoduleThis module qep_sim will have glitches in the middle of the high pulse on output b when cnt[1] changes picoseconds before cnt[0] as it can do, depending on internal routing.
Reply by ●May 14, 20112011-05-14
Andrew Holme wrote:> "Mr.CRC" <crobcBOGUS@REMOVETHISsbcglobal.net> wrote in message > news:iqkvcv01c5r@news6.newsguy.com... >> reg [15:0] cnt; >> >> always @ (posedge clk) begin >> if (cnt == MAX_CNT) >> cnt = 0; >> else >> cnt = cnt + 1; >> end >> >> assign a = ~cnt[1]; >> assign b = cnt[1] ^ cnt[0]; >> assign m = ~b & (cnt == 0 || cnt == MAX_CNT); >> // index pulse m is high >> // straddling max count and zero. Why the redundant '&' with ~b is >> // performed? I forget. Maybe this is unnecessary. >> endmodule > > > This module qep_sim will have glitches in the middle of the high pulse on > output b when cnt[1] changes picoseconds before cnt[0] as it can do, > depending on internal routing.Yes, I see. Not sure why I didn't think of that. Now this reminds me that the reason why m includes the & ~b is to prevent a glitch on m when the cnt goes from MAX_CNT->0. But of course, that presumes b doesn't have glitches... I will try to work this out. BTW, the potential glitching you describe has never actually been observed from this module. Though with my slow slew rate outputs, it may have just been unobservable externally. So this is a seperate issue from the original problem, which is that cnt changes on the wrong edge of the clock sometimes. This results in shortened pulses for a, b, and less frequently, m, since the phenomenon is random so only in 2/(1+MAX_CNT) of cases does it overlap with m. It is also true that when the clocking glitch occurs, the correct phase of the a and b signals is preserved, So the encoder "speeds up" effectively by half a clock cycle. Thanks for the reply. -- _____________________ Mr.CRC crobcBOGUS@REMOVETHISsbcglobal.net SuSE 10.3 Linux 2.6.22.17
Reply by ●May 14, 20112011-05-14
Joel Williams wrote:>> Thanks for ideas on what might be wrong. I suspect it has something to >> do with non-ideal choices of IO pins for the clock inputs. I didn't >> have time to test this today, but I suspect if I simply move the >> ext_sim_clk to a different pin, the problem will go away. > > Rather than using these signals as clocks, why not sample the incoming > signal with the Nexys2's 50 MHz clock? > > Register the input and check for rising edges: > > reg [1:0] ext_clk; > > always @(posedge clk50) > ext_clk[1:0] <= {ext_clk[0], sim_clk}; > > wire rising_edge = ext_clk[1] & ~ext_clk[0]; > > and then count these: > > always @(posedge clk50) > if (rising_edge) > if (cnt == MAX_CNT) ...I could probably do something like this. BTW, doesn't the above produce 20ns pulses on "rising_edge" when sim_clk goes H->L, ie. on the falling edge? Also, I wonder about the use of a once-registered asynchronous input signal. Shouldn't the sim_clk be registered at least twice before engaging in combinatorial functions? Ie, it seems that if ext_clk[0] waffles for a few extra ns due to metastability, then the pulse on "rising_edge" could be shorter than 20ns and not reliable. Wouldn't it make more sense to simply use: wire rising_edge = ext_clk[1] & ext_clk[0]; // ??? In which case I think it is safe even employing the once-registered ext_clk[0] ? There is still an unresolved engineering principles question here though. Do FPGA logic designers ALWAYS sync asynchronous inputs to the internal clock? If there is a circuit which is to be clocked by an external source, and it is not going to interact with other process on different clocks, then why bother syncing this clock input to the 50MHz on-board clock? Ie, my qep_sim.v exists in its own clock domain, albeit there is still the mux to choose which external clock to use. This also doesn't answer the question of why the behavior changes vs. input pin. I have gathered that when clocks are to be brought in to the FPGA, it is highly recommended to use a GCLK IO pin, so the signal may be buffered onto a global clock routing line. I have to see if I can rearrange my IOs to get these external inputs onto GCLK IOs, but there are two of them and the NEXYS2 isn't very liberal about providing GCLKs on the pin headers. Some other GCLKs are available on another connector, but I don't yet have the mating for that. Of course, when muxing external clock sources, if there are a lot of them, one could eat into the supply of GCLKs quickly, so this is undesirable. A more interesting question is then, is it possible to take a GP IO input pin, and internally buffer it onto an internal clock routing line? Thanks for input and clarification. -- _____________________ Mr.CRC crobcBOGUS@REMOVETHISsbcglobal.net SuSE 10.3 Linux 2.6.22.17
Reply by ●May 14, 20112011-05-14
"Mr.CRC" <crobcBOGUS@REMOVETHISsbcglobal.net> wrote in message news:iqm4ri02prr@news4.newsguy.com...> Andrew Holme wrote: >> "Mr.CRC" <crobcBOGUS@REMOVETHISsbcglobal.net> wrote in message >> news:iqkvcv01c5r@news6.newsguy.com... >>> reg [15:0] cnt; >>> >>> always @ (posedge clk) begin >>> if (cnt == MAX_CNT) >>> cnt = 0; >>> else >>> cnt = cnt + 1; >>> end >>> >>> assign a = ~cnt[1]; >>> assign b = cnt[1] ^ cnt[0]; >>> assign m = ~b & (cnt == 0 || cnt == MAX_CNT); >>> // index pulse m is high >>> // straddling max count and zero. Why the redundant '&' with ~b is >>> // performed? I forget. Maybe this is unnecessary. >>> endmodule >> >> >> This module qep_sim will have glitches in the middle of the high pulse on >> output b when cnt[1] changes picoseconds before cnt[0] as it can do, >> depending on internal routing. > > > Yes, I see. Not sure why I didn't think of that. Now this reminds me > that the reason why m includes the & ~b is to prevent a glitch on m when > the cnt goes from MAX_CNT->0. But of course, that presumes b doesn't > have glitches... > > I will try to work this out. > > BTW, the potential glitching you describe has never actually been > observed from this module. Though with my slow slew rate outputs, it > may have just been unobservable externally. > > > So this is a seperate issue from the original problem, which is that cnt > changes on the wrong edge of the clock sometimes.If it's an external clock, slow rise and fall times plus additive noise can cause multiple counts if it slews too slowly through the logic threshold. If the external clock rate is low, the best solution is to sample it at a rate comparable to the rise/fall time.
Reply by ●May 14, 20112011-05-14
On May 14, 11:27=A0am, "Mr.CRC" <crobcBO...@REMOVETHISsbcglobal.net> wrote:> Joel Williams wrote: > >> Thanks for ideas on what might be wrong. =A0I suspect it has something=to> >> do with non-ideal choices of IO pins for the clock inputs. =A0I didn't > >> have time to test this today, but I suspect if I simply move the > >> ext_sim_clk to a different pin, the problem will go away. > > > Rather than using these signals as clocks, why not sample the incoming > > signal with the Nexys2's 50 MHz clock? > > > Register the input and check for rising edges: > > > reg [1:0] ext_clk; > > > always @(posedge clk50) > > =A0 ext_clk[1:0] <=3D {ext_clk[0], sim_clk}; > > > wire rising_edge =3D ext_clk[1] & ~ext_clk[0]; > > > and then count these: > > > always @(posedge clk50) > > =A0 if (rising_edge) > > =A0 =A0 if (cnt =3D=3D MAX_CNT) ... > > I could probably do something like this. > > BTW, doesn't the above produce 20ns pulses on "rising_edge" when sim_clk > goes H->L, ie. on the falling edge?Yes. The expression should be ~ext_clk[1] & ext_clk[0] for a rising edge detect.> Also, I wonder about the use of a once-registered asynchronous input > signal. =A0Shouldn't the sim_clk be registered at least twice before > engaging in combinatorial functions? =A0Ie, it seems that if ext_clk[0] > waffles for a few extra ns due to metastability, then the pulse on > "rising_edge" could be shorter than 20ns and not reliable.Are you using rising_edge as a pulse with a defined width or is it an enable to the next FF? You can resolve metastability anywhere along this chain, as long as you do it before the signal branches out to more than one place.> Wouldn't it make more sense to simply use: > > wire rising_edge =3D ext_clk[1] & ext_clk[0]; // ???No, this does not detect an edge. This resolves metastability and eliminates glitches, but you still need to detect the edge of the clock signal. The idea of detecting the edge is to both bring the signal into the clk50 domain and also create a one clock period wide enable to use in place of a separate clock.> In which case I think it is safe even employing the once-registered > ext_clk[0] ?No, this doesn't even resolve metastability unless you provide more slack time to the next FF.> There is still an unresolved engineering principles question here > though. =A0Do FPGA logic designers ALWAYS sync asynchronous inputs to the > internal clock? =A0"Always" is a big statement. I nearly always pick one fast clock domain as the "internal" clock and sync slow clocks to this fast one. Each "external" clock becomes a clock enable internally. There are times when I use the external clock directly, for example the serial clock on an SPI port directly clocks the shift register in a recent SPI design. Then I have lots of time to sync the parallel word to the internal clock. But this could be done either way. Sometimes it depends on the relative rate of the two clocks. The closer in speed they are the harder it can be to fully analyze the timing.> If there is a circuit which is to be clocked by an > external source, and it is not going to interact with other process on > different clocks, then why bother syncing this clock input to the 50MHz > on-board clock? =A0Ie, my qep_sim.v exists in its own clock domain, albei=t> there is still the mux to choose which external clock to use.If it is completely independent as if it were being done on a separate chip, then yes, there is no reason to sync it to the internal clock as long as you can get the clock to a clock input and even that is not essential. The tools have to do less work to make a clock on a clock tree meet setup and hold times.> This also doesn't answer the question of why the behavior changes vs. > input pin.I suspect that has to do with your clock signal. Does it have a slow rise/fall time? I suspect a bit of noise is making it double clock. When you route it differently (since it is not on a clock IO pin) the glitch can get filtered out depending on how it is routed. It only takes a very tiny glitch to cause this sort of double clocking and such a tiny glitch can be filtered by the random routing. Putting it on a global clock tree should make it fail more often.> I have gathered that when clocks are to be brought in to the FPGA, it is > highly recommended to use a GCLK IO pin, so the signal may be buffered > onto a global clock routing line. =A0I have to see if I can rearrange my > IOs to get these external inputs onto GCLK IOs, but there are two of > them and the NEXYS2 isn't very liberal about providing GCLKs on the pin > headers. =A0Some other GCLKs are available on another connector, but I > don't yet have the mating for that.Don't try to fix a problem if you don't understand the cause. Why would a GLK IO pin eliminate your problem?> Of course, when muxing external clock sources, if there are a lot of > them, one could eat into the supply of GCLKs quickly, so this is > undesirable.Bingo! That is a big reason for treating slow clocks as clock enables on an internal clock.> A more interesting question is then, is it possible to take a GP IO > input pin, and internally buffer it onto an internal clock routing line?Isn't that what is already happening in your case?> Thanks for input and clarification.Let us know what you find. It is hard to analyze problems like this without doing tests. I may be completely off base in this case. Rick
Reply by ●May 14, 20112011-05-14
On May 14, 11:27=A0am, "Mr.CRC" <crobcBO...@REMOVETHISsbcglobal.net> wrote:> > There is still an unresolved engineering principles question here > though. =A0Do FPGA logic designers ALWAYS sync asynchronous inputs to the > internal clock? =A0They do if they want to guarantee it will work and be maintainable and/ or reusable. Either that or they come back here posting about a design that 'used to work just fine when...blah, blah, and now it does not'> If there is a circuit which is to be clocked by an > external source, and it is not going to interact with other process on > different clocks, then why bother syncing this clock input to the 50MHz > on-board clock?You wouldn't. The point of synchronizing to a clock is when you're *changing* clock domains.> =A0Ie, my qep_sim.v exists in its own clock domain, albeit > there is still the mux to choose which external clock to use. >The output of the clock mux is a new clock domain, different than either of the two input clock domains. Thinking that the selected input clock and the 'output of the mux clock' are the same clock domain is a mistake that will come back to bite you.> This also doesn't answer the question of why the behavior changes vs. > input pin. >Because sometimes you get 'lucky'. There are probably lots of things (such as moving pins, hand routing, etc.) that you can do to appear to 'fix' the problem. If you're lucky you'll find that none of these things really works well and that you still occasionally get glitches. If you're not lucky you won't find this out until much later when it will get more and more difficult and expensive to fix if you've deployed many of these boards. If you'd rather be smart than lucky you'll stop using gated internal clocks and adopt synchronous design practices.> I have gathered that when clocks are to be brought in to the FPGA, it is > highly recommended to use a GCLK IO pin, so the signal may be buffered > onto a global clock routing line. =A0It is even more recommended that you not generate your own internal clocks with logic.> I have to see if I can rearrange my > IOs to get these external inputs onto GCLK IOs, but there are two of > them and the NEXYS2 isn't very liberal about providing GCLKs on the pin > headers. =A0Some other GCLKs are available on another connector, but I > don't yet have the mating for that. >This would be some of the tricks that I mentioned earlier that, if you're lucky, you'll find are not robust without spending too much time. Or maybe your luck will run out, the design will appear to work, you'll think you're home free...until a couple of months later when you're handed a stack of boards that aren't qute working and you need to fix them.> Of course, when muxing external clock sources, if there are a lot of > them, one could eat into the supply of GCLKs quickly, so this is > undesirable. >Yep...you shouldn't do that.> A more interesting question is then, is it possible to take a GP IO > input pin, and internally buffer it onto an internal clock routing line? >I may be an interesting question...but you'll get to the end line much sooner if you use strictly synchronous practices and only cross clock domains either with dual clock fifos or proper synchronization logic. Kevin Jennings
Reply by ●May 14, 20112011-05-14
>> BTW, doesn't the above produce 20ns pulses on "rising_edge" when sim_clk >> goes H->L, ie. on the falling edge? > > Yes. The expression should be ~ext_clk[1]& ext_clk[0] for a rising > edge detect.My mistake, sorry! I'm just glad that everyone agreed with me about the method :D Joel
Reply by ●May 15, 20112011-05-15
Andrew Holme wrote:> > If it's an external clock, slow rise and fall times plus additive noise can > cause multiple counts if it slews too slowly through the logic threshold. > If the external clock rate is low, the best solution is to sample it at a > rate comparable to the rise/fall time.Thanks for the reply. Ugh. I could have sworn a few minutes ago I found a spec of 500ns for the min slew rate of an input in the hideous ds312.pdf "Spartan-3E FPGA Family: Data Sheet" but now I can't find it again. Anyway, getting a clean enough clock to a logic device really isn't that hard. I'll scope it again Monday and see if I can't put it up somewhere. -- _____________________ Mr.CRC crobcBOGUS@REMOVETHISsbcglobal.net SuSE 10.3 Linux 2.6.22.17






