Verilog /DIP Switch Question....

G

G

Guest
Is it possible to implement a "pause" function for a counter using a
DIP switch? i.e. where it counts, you press the DIP switch it stops
counting holding the current value until you press the DIP switch again
in which it counts again starting from its stopped value?

Right now, the DIP switch is used as a "reset" zeroing out the
counter...you press it, the counter immediately goes to 00 and once you
release it starts counting...01,02, etc.

I have tried all the obvious things, but I am wondering if this is even
possible at all with a DIP switch and I am wasting my time...with a DIP
switch, you only have a "known" state when it is pressed...when not
pressed it is an open circuit, right? It seems like I would need a
switch that is tied to ground when open, right? Or am I missing
something?

FYI, this a board with an FPGA, LCD and DIP Switch.
Thanks for any help you can offer.
 
First of all, this isn't a HW problem...I have been out of school a few
years... I am trying to bridge the gap between the simulated world that
academia covers well and the actual real world HW that academia does a
poor job at covering, imo.

Anyway....Like I mentioned in my first post, I have done all the
obvious things to no avail...it simulates as expected, but once in
hardware, it doesn't, which makes me think it is something with the DIP
switch.

I can cut and paste the necessary code if you are willing to help....
 
Have you tried using the DIP switch as an enable signal instead of a
reset signal? I'm interesetd in reading the code if you would like to
post it.
 
I apologize for suggesting it might be a homework problem. It's
actually not school time and so the suggestion was unwarranted. (I
might have missed your first post also (or atleast not connected it).)

If it is a mismatch between simulation and physical implementation,
perhaps there is something in the physical implementation your model
doesn't account for. For example, perhaps the dip switch "Bounces".
What you are trying to build, where the switch acts as a toggle would
be susceptible to that. Using the dip as a reset wouldn't have the
same tempermentalness, as if one sees two (or more) rests in a row,
one isn't going to "notice", since in the end the signal still gets
reset. Tow toggles in a row are a different story.

If you could tie an indicator (e.g. an led) to the "state" part of the
design, so that the led would indicate which state the toggle is in,
you might see that it doesn't actually toggle (or toggles more than
once per push). Of course, if the problem is too quick, it might go
by to quick for you to see it.

Assuming that bounce is the problem, you could then ask how to
de-bounce your circuit (i.e. make it less sensitive to bounce). I
don't know what solutions are available there, but one possibility is
to make the circuit insensitive to a 2nd button push until a specific
amount of time (say a specific number of clock cycles) after the
first. Iamgine how you would change your circuit model so that the
dip button could only cause one change of the toggle per cycle.
Implement that and see if it effects your problem. If bounce is the
problem, whether that change will help depends on how fast your cycle
is relatively to how fast bounces settle.

If bounce isn't the problem, you need to keep looking until you can
find out what is. You're right about the differences between
unrealistic "academic" models and the real-world implementation.
Verilog models are a simplification of the real world and do not model
it completely faithfully. There are things which can happen in the
real world that your model is likely to miss and vice-versa: sometimes
the model can have artifacts that can never heppen in the real world.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
G wrote:
Is it possible to implement a "pause" function for a counter using a
DIP switch? i.e. where it counts, you press the DIP switch it stops
counting holding the current value until you press the DIP switch
again
in which it counts again starting from its stopped value?

You want to use the DIP switch to toggle a Count Enable flip-flop. This
would be trivial if there were no contact bounce. In reality, the
toggling flip-flop is about a million times faster than the contact
bounce activity, so you must somehow make sure that the whole bounce
sequence ( lasting 100 ms?) is seen as only one clock input to the
control flip-flop.
With a two-pole switch this is trivial, but with only one pole, you
have to introduce a delay that masks the bounce.
A clean digital solution uses an extra multibit resettable "dead-ended"
counter that stops counting when its MSB is a 1. Needs a reasonably
slow clock to make it longer than 100 ms.
Depressing the DIP switch resets the whole counter, and keeps it reset
as long as you hold the DIP switch down.
Use the MSB going 1-to-0 as the clock for your toggling count enable
signal.

There are many variations on this theme, but none is trivial.
There are neat tricks you can play with R and C, but that gets you an
outcry of contempt from the digital design community...
Peter Alfke
 
Peter Alfke wrote:
G wrote:

Is it possible to implement a "pause" function for a counter using a
DIP switch? i.e. where it counts, you press the DIP switch it stops
counting holding the current value until you press the DIP switch

again

in which it counts again starting from its stopped value?


You want to use the DIP switch to toggle a Count Enable flip-flop. This
would be trivial if there were no contact bounce. In reality, the
toggling flip-flop is about a million times faster than the contact
bounce activity, so you must somehow make sure that the whole bounce
sequence ( lasting 100 ms?) is seen as only one clock input to the
control flip-flop.
SNIP

I'm possibly missing something here, but seems to me that it really
doesn't matter whether the switch bounces or not.

If the switch is changing from "count" to "don't count" at the time the
counter is trying to figure out whether to count or not, the worst that
can happen is that it will make an extra count or maybe a few.

Assume the switch debounces in 100 ms, and during the 100 ms it's in the
wrong state for 50% of the time. If the counter is counting at 1 Hz,
then there's a 5% chance that it will make one extra count.

If you're counting faster than 10 Hz, then you'll probably never know if
there are one or two extra counts that happen while the switch is
debouncing.

If you're interested in switch bounce time, Jack Ganssle did a column
about it a few months ago, in Embedded Systems Magazine. He went out and
bought about 20 switches and measured debounce time using an
oscilloscope. I don't remember the results, but it's still an
interesting read. Here's a link to the article:

http://www.embedded.com//showArticle.jhtml?articleID=18400810
 
The original posting asked for a design where the first depression of
the DIP stops the counter, the second depression starts it again, like
an old-fashioned lamp next to your bed.

"where it counts, you press the DIP switch it stops
counting holding the current value until you press the DIP switch again
in which it counts again starting from its stopped value"

That toggle action is the problem, and it needs switch debouncing.
Peter Alfke, on a rainy California Sunday afternoon...
 
The original posting asked for a design where the first depression of
the DIP stops the counter, the second depression starts it again, like
an old-fashioned lamp next to your bed.

"where it counts, you press the DIP switch it stops
counting holding the current value until you press the DIP switch again
in which it counts again starting from its stopped value"

That toggle action is the problem, and it needs switch debouncing.
Peter Alfke, on a rainy California Sunday afternoon...
 
"div_16M.v" generates a count that enables both "cnt_10.v" and
subsequently "cnt_10_tens.v" when its(div_16M.v)
count reaches all 1s.

To do the pause/start/stop function, I moved the "clr" function out of
the two counter modules and into a module
"cnt_pause.v" to enable/disable the master counter enabler
"div_16M.v"...this makes the most sense(I thought)

Initially, "clr" was used to reset the counter to zero...this was tied
to the DIP switch on the PCB.(this code is commented out)

This is my last shot at what I thought was "trivial"...I have changed
it around a lot, but settled on this approach...I feel it is close, but
I have begun to think otherwise...Please excuse the messiness and
somewhat disarray.



// module: counter.v

// This is the top level module that ties all sub-modules together

module counter(clk,reset,lcd_com,one_dp,ten_dp,one_out,ten_out);
input clk;
input reset;
output lcd_com;
output one_dp;
output ten_dp;
output [6:0] one_out;
output [6:0] ten_out;

wire nreset;
wire pause;
wire lcd_clk;
wire tc;
wire ce_tens;
wire [23:0] ce_1s;
wire [3:0] cnt_1s;
wire [3:0] cnt_10s;
wire [6:0] lcd1_out;
wire [6:0] lcd10_out;

cnt_pause PAUSE(
..clk(clk),
..clr(nreset),
..start_stop(pause)
);

div_500K DIV_500K(
..clk(clk),
..clk_60(lcd_clk)
);

div_16M DIV_16M(
..clk(clk),
..start_stop(pause),
..enable(ce_1s)
);

cnt_10 ONES(
..clk(clk),
//.clr(nreset),
..enable(ce_1s),
..tc(tc),
..qout(cnt_1s)
);

cnt_10_tens TENS(
..clk(clk),
//.clr(nreset),
..ce_tens(ce_tens),
..qout_tens(cnt_10s)
);

hex2lcd ONES_LCD(
..hex(cnt_1s),
..lcd(lcd1_out)
);

hex2lcd TENS_LCD(
..hex(cnt_10s),
..lcd(lcd10_out)
);

lcd_mux ONES_MUX(
..clk(clk),
..cnt(lcd_clk),
..data_in(lcd1_out),
..lcd_seg(one_out),
..lcd_com(lcd_com),
..lcd_dp(one_dp)
);


lcd_mux TENS_MUX(
..clk(clk),
..cnt(lcd_clk),
..data_in(lcd10_out),
..lcd_seg(ten_out),
..lcd_com(),
..lcd_dp(ten_dp)
);

assign nreset = ~reset;
assign ce_tens = tc & (ce_1s == 24'hFFFFFF);

endmodule


// module: cnt_pause.v

// This module ties the DIP switch function to counter enable.Pauses
the //counter.
// Continues counting toggled by user DIP and at last count value.

module cnt_pause(clk,clr,start_stop);
input clk;
input clr;
output start_stop;

reg pause = 0;

always @ (posedge clk)
begin
if (clr)
pause <= 1; //Pauses counter at present count value
else if (clr && pause == 1) //Resumes counting at pause state and upon
//user DIP input
pause <= 0;
end

assign start_stop = pause;

endmodule



// module: div_16M.v

// This module divides the incoming 30 MHz clock by 2^24 and is used to
enable //the counter.

module div_16M(clk,start_stop,enable);
input clk;
input start_stop;
output [23:0] enable;

reg [23:0] count = 0; //Current count value
reg start_stop = 0; //pause function

always @ (posedge clk)
begin
if (start_stop == 1) //Pause count
else if (start_stop == 0) //Count or resume counting from pause state
count <= count + 1;
end

assign enable = count;

endmodule





// Module: cnt_10.v

// This module counts from 0 to 15 and then rolls over. Ones Digit.

module cnt_10(clk,enable,tc,qout);
input clk;
//input clr;
input [23:0] enable; //enables the counter to count at slower
clockrate
output tc;
output [3:0] qout;

reg [3:0] count = 0; //Current count value


always @(posedge clk)
begin
//if (clr) //asynchronous RESET active High
//count <= 4'b0;
//else if (enable == 24'hFFFFFF)
//count <= count + 1;
if (enable == 24'hFFFFFF)
count <= count + 1;
end

assign qout = count;
assign tc = (count == 4'hF); //Terminal count flag for ones
digit/tens counter enable


endmodule





// Module: cnt_10_tens.v

// This module counts from 0 to 15 and then rolls over. Tens Digit.


module cnt_10_tens(clk,ce_tens,qout_tens);
input clk;
//input clr;
input ce_tens;
output [3:0] qout_tens;

reg [3:0] count = 0; //Current count value


always @(posedge clk)
begin
//if (clr) //asynchronous RESET active High
//count <= 4'b0;
//else if (ce_tens == 1)
//count <= count + 1;
if (ce_tens == 1)
count <= count + 1;
end

assign qout_tens = count;

endmodule
 

Welcome to EDABoard.com

Sponsor

Back
Top