## Friday, 27 July 2012

### To Code a Stopwatch in Verilog

The stopwatch coded here will be able to keep time till 10 minutes. It will be a 4 digit stopwatch counting from 0:00:0 till 9:59:9. The right most digit will be incremented every 0.1 second, when it reaches 9 it will increment the middle two digits, which represent the second count. When it reaches 59 seconds it will increment the right most minute display. The stopwatch will be in the format M:SS:D.

### How to Create an Accurate Delay in Verilog:

To make the stop watch an accurate device we need to be able to produce an accurate 0.1 second delay. I have already explained how to do this before in my decimal counter in verilog post. But since it is of great importance to the design will be explained in more detail here.

Since we know that the BASYS2 (the one I am using, yours may be different) has a 50 MHz clock which means that the clock cycle is repeated 50M times in one second. So to create a 0.1 second delay we multiply the clock with the required time:

50MHz * 0.1 sec = 5000000

So the clock cycle is repeated 5M times in 0.1 second. The next step is to calculate the size of the register that will hold this count. This is done by using the log formulas. Here x is the unknown:

2exp(x) = 5000000

Taking log on both sides:

log 2exp(x) = log 5000000

(x) log (2) = log 5000000

x = log 5000000 / log 2

x = 22.3

Hence a 23 bit wide register will be able to hold a count of 5000000.

The code for the stopwatch is given below, as with all other posts involving the seven segment display LED multiplexing is performed here. I will not comment or explain it here as I have already made a detailed post regarding that here: Display LED Multiplexing in Verilog

```module stopwatch(
input clock,
input reset,
input start,
output a, b, c, d, e, f, g, dp,
output [3:0] an
);

reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
reg [22:0] ticker; //23 bits needed to count up to 5M bits
wire click;

//the mod 5M clock to generate a tick ever 0.1 second

always @ (posedge clock or posedge reset)
begin
if(reset)

ticker <= 0;

else if(ticker == 5000000) //if it reaches the desired max value reset it
ticker <= 0;
else if(start) //only start if the input is set high
ticker <= ticker + 1;
end

assign click = ((ticker == 5000000)?1'b1:1'b0); //click to be assigned high every 0.1 second

always @ (posedge clock or posedge reset)
begin
if (reset)
begin
reg_d0 <= 0;
reg_d1 <= 0;
reg_d2 <= 0;
reg_d3 <= 0;
end

else if (click) //increment at every click
begin
if(reg_d0 == 9) //xxx9 - the 0.1 second digit
begin  //if_1
reg_d0 <= 0;

if (reg_d1 == 9) //xx99
begin  // if_2
reg_d1 <= 0;
if (reg_d2 == 5) //x599 - the two digit seconds digits
begin //if_3
reg_d2 <= 0;
if(reg_d3 == 9) //9599 - The minute digit
reg_d3 <= 0;
else
reg_d3 <= reg_d3 + 1;
end
else //else_3
reg_d2 <= reg_d2 + 1;
end

else //else_2
reg_d1 <= reg_d1 + 1;
end

else //else_1
reg_d0 <= reg_d0 + 1;
end
end

//The Circuit for Multiplexing - Look at my other post for details on this

localparam N = 18;

reg [N-1:0]count;

always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end

reg [6:0]sseg;
reg [3:0]an_temp;
reg reg_dp;
always @ (*)
begin
case(count[N-1:N-2])

2'b00 :
begin
sseg = reg_d0;
an_temp = 4'b1110;
reg_dp = 1'b1;
end

2'b01:
begin
sseg = reg_d1;
an_temp = 4'b1101;
reg_dp = 1'b0;
end

2'b10:
begin
sseg = reg_d2;
an_temp = 4'b1011;
reg_dp = 1'b1;
end

2'b11:
begin
sseg = reg_d3;
an_temp = 4'b0111;
reg_dp = 1'b0;
end
endcase
end
assign an = an_temp;

reg [6:0] sseg_temp;
always @ (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000;
4'd1 : sseg_temp = 7'b1111001;
4'd2 : sseg_temp = 7'b0100100;
4'd3 : sseg_temp = 7'b0110000;
4'd4 : sseg_temp = 7'b0011001;
4'd5 : sseg_temp = 7'b0010010;
4'd6 : sseg_temp = 7'b0000010;
4'd7 : sseg_temp = 7'b1111000;
4'd8 : sseg_temp = 7'b0000000;
4'd9 : sseg_temp = 7'b0010000;
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g, f, e, d, c, b, a} = sseg_temp;
assign dp = reg_dp;

endmodule```

Test bench below:

```module test;

// Inputs
reg clock;
reg reset;
reg start;

// Outputs
wire [3:0] d0;
wire [3:0] d1;
wire [3:0] d2;

// Instantiate the Unit Under Test (UUT)
stopwatch uut (
.clock(clock),
.reset(reset),
.start(start),
.d0(d0),
.d1(d1),
.d2(d2)
);

initial
begin
clock = 0;
forever
#50 clock = ~clock;
end

initial begin
// Initialize Inputs
reset = 0;
start = 0;

// Wait 100 ns for global reset to finish
#100;
reset = 1;
#100;
reset = 0;
#100;
start = 1;
end
endmodule
```

Video demonstration below:

1. This comment has been removed by the author.

1. It doesnt work how? Can you tell me the error you are getting? Also did you change the ucf file for your board. If you use my ucf it wont work.

2. yes. i changed the frequency according to nexys3 board. and i have also changed the .ucf file according to the board. when i program the board, it does not start counting, and only the right most 7seg led lighted up showing 0.

3. Interesting.. Do you get any warnings when implementing? Most probably the ISE is truncating some signals where it shouldnt

2. can i get a test bench for this?

2. HOw does the test bench show 'outputs': d0,d1,d2 when you've not assigned them as outputs in the main program?

3. ^i have the same exact question

3. hey, and you pleace then me the vhdl code as a zip file so i can open it directly on vhdl(+ufc so i can try it on my board) ... my email: Sweet_sahar91@hotmail.com

i also wanna ask if you have a vhdl code for up/down stopwatch, it will be so great if you have! :)

thanx!

1. hi Sahar.

I do not have this in VHDL also I don't know how to code in VHDL. All my projects are in Verilog.

As for the up and down, you can easily add a down version to this code my coding another block that decrements instead of increments.

4. Could you provide a UCF file for the BASYS2?

1. Here you go: http://simplefpga.blogspot.com/2012/06/user-constraint-file-ucf-for-basys2.html

5. Sir I had learn from many of your tutorial about delay generation but none of your tutorial contain delay generation and call in any line ...Actually sir I want to call a delay in any line of Verilog..
like
a=1'b0;
a=1'b1;

1. You are missing the point. This is not C or C++. This is not how Verilog works.

In Verilog you cannot "call" anything. It just doesn't work like that.

2. sir can I mail/post you my Verilog code and show you the point of error in my code for delay generation........please allow me sir......I know you definitely have the answer please sir...

3. Sorry Shrikant but I cannot give out my email for the purpose of error finding in codes but like I said before you cannot "call" a delay function like you do in other languages. If you want to produce a delay during execution the easiest method is to generate a counter and only let the other always block activate when the counter reaches its desired value, like I did in the code in this post with "ticker". You can also make a module out of this and instantiate it into your main code.

6. Hello How can i assign pin..i mean which pin goes for output...?

1. Hi Seajan,

For actual pin assignment of your code to your board you will have to use the .ucf file of YOUR board. Read more on it here: http://simplefpga.blogspot.co.uk/2012/06/user-constraint-file-ucf-for-basys2.html

The ucf given there is for my BASYS 2 board, if thats not the one you have then it wont work for you

7. I am stuck. I want a stop watch using LCD on Spartan 3E. i have done the LCD coding while i cannot understand the logic of implementing the stop watch or its coding.

1. Which board are you trying to implement this on?

1. To implement this on the NEXYS2 all you have to do is to change your .ucf file which you have for your board to the inputs and outputs of this code.

Have a look at the ucf file configuration of my BASYS2 board to get an idea: http://simplefpga.blogspot.co.uk/2012/06/user-constraint-file-ucf-for-basys2.html

9. can i implement this code in nexys 2 board

10. can you please upload a ucf file of nexys 3? I am a beginner and am not aware of the creation of ucf files..also please advise if we also need to make a bitfile after the generation of ucf file

1. I don't know the pin layout for nexys3, but you should be able to find its ucf file online via a simple google search. And yes you will need a bit file in order to program your board.

11. hey , can send the project with all codes on a rar file to this email ggadeag@gmail.com is thank you in advance .

12. Hi, i am doing doing stop watch in verilog using SPARTAN-3 FPGA_XC3S400 board. i dont no how to program lcd which displays the stop watch...pls help me.... its urgent.....

1. Is it an LCD or the seven segment led?

2. Is it an LCD or the seven segment led?

13. Hi, i am doing doing stop watch in verilog using SPARTAN-3 FPGA_XC3S400 board. i dont no how to program lcd which displays the stop watch...pls help me.... its urgent.....

14. How to include stop functionality in this code.

15. helllo, why in the sentence case used (count[N-1:N-2]) (the 2 MSB's of the counter) for generate a frecuency of Multiplexing the 1000HZ? tanks

16. Hi Mauricio, Please read my post on the seven segment display to understand the reasoning behind that: http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html

17. have you added debouncing in it?

18. Why is local parameter N = 18?

19. Hello, do you have this code in vhdl?

20. Could you explain why it is case(count[N-1:N-2]) won't that always make it reference 17:16? How is this right?

21. I got the error in test bench code line

#50 clock = ~clock;

Error (10119): Verilog HDL Loop Statement error at DE1_SOC_golden_top.v(313): loop with non-constant loop condition must terminate within 250 iterations

How do i get out of this error