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.
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
Test bench below:
Video demonstration below:
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; // Add stimulus here end endmodule
Video demonstration below:
This comment has been removed by the author.
ReplyDeleteIt 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.
Deleteyes. 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.
DeleteInteresting.. Do you get any warnings when implementing? Most probably the ISE is truncating some signals where it shouldnt
Deletecan i get a test bench for this?
ReplyDeleteTest bench added
DeleteHOw does the test bench show 'outputs': d0,d1,d2 when you've not assigned them as outputs in the main program?
Delete^i have the same exact question
Deletehey, 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
ReplyDeletei also wanna ask if you have a vhdl code for up/down stopwatch, it will be so great if you have! :)
thanx!
hi Sahar.
DeleteI 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.
Could you provide a UCF file for the BASYS2?
ReplyDeleteHere you go: http://simplefpga.blogspot.com/2012/06/user-constraint-file-ucf-for-basys2.html
DeleteSir 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..
ReplyDeletelike
a=1'b0;
delay(); //maybe task or function
a=1'b1;
sir my question is how to do this using task or counter I already tried this using counter but it not works for me......please help and mail me if you know about this-shrikantvaishnav@hotmail.com or publish any post related to it......
You are missing the point. This is not C or C++. This is not how Verilog works.
DeleteIn Verilog you cannot "call" anything. It just doesn't work like that.
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...
DeleteSorry 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.
DeleteHello How can i assign pin..i mean which pin goes for output...?
ReplyDeleteHi Seajan,
DeleteFor 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
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.
ReplyDeleteWhich board are you trying to implement this on?
Deleteplease help me to implement it in NEXYS 2 board
ReplyDeleteTo 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.
DeleteHave 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
can i implement this code in nexys 2 board
ReplyDeletecan 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
ReplyDeleteI 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.
Deletehey , can send the project with all codes on a rar file to this email ggadeag@gmail.com is thank you in advance .
ReplyDeleteHi, 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.....
ReplyDeleteIs it an LCD or the seven segment led?
DeleteIs it an LCD or the seven segment led?
DeleteHi, 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.....
ReplyDeleteHow to include stop functionality in this code.
ReplyDeletehelllo, 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
ReplyDeleteHi 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
ReplyDeletehave you added debouncing in it?
ReplyDeleteWhy is local parameter N = 18?
ReplyDeleteHello, do you have this code in vhdl?
ReplyDeleteCould you explain why it is case(count[N-1:N-2]) won't that always make it reference 17:16? How is this right?
ReplyDeleteI got the error in test bench code line
ReplyDelete#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
Hey, can you please give the .ucf code for this verilog code.
ReplyDeleteI'm using xilinx Nexys 3, Spartan 6 family.
Please mail it to me ASAP :)
guptak994@gmail.com
Hello! This is very helpful. I would like to incorporate this into a project using a register file. Perhaps something where the times when it is stopped it loaded into a write address and then saved and can be shown? If you have any advice on this, I would appreciate it! Thank you!
ReplyDeleteWARNING:Xst:2725 - "prooject.v" line 126: Size mismatch between case item and case selector.
ReplyDeleteWARNING:Xst:2725 - "prooject.v" line 127: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 128: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 129: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 130: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 131: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 132: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 133: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 134: Size mismatch between case item and case selector.
WARNING:Xst:2725 - "prooject.v" line 135: Size mismatch between case item and case selector.
i m facing these errors please help me its urgent
This code isn't working. May be there is problem in ucf file. How to get correct ucf file of stopwatch code in verliog.
ReplyDelete