M
Mr.CRC
Guest
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
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