[GA]Verilog 60s stopwatch timer (maximum timetable up to 9 min)

Keywords: Verilog Programming

[GA]Verilog 60s stopwatch timer

1. Citation

This experiment is based on an optional topic during my undergraduate course Number of Junctions.Since the upload was post-perception and the school had recycled the toe plates, it was impossible to post an effect picture of the code results in this article, but the final effect has been tested and can be safely eaten.Then the code will be pasted and explained for your reference.

2. Frequency division module

We want to implement a stopwatch. Naturally, we want to divide the clk frequency of the clock pulse in the experimental board into a pulse with a period of 1s, and the crystal vibration of the lamb is known to be 12MHz.Paste the code of the crossover module below.

module divide #
(                            //parameter yes verilog Definition of internal parameters
parameter WIDTH    =    24,    //The number of bits in the counter, with a maximum count of 2**(WIDTH-1)
parameter N        =    12_000_000 //Crossover factor, make sure N<2**(WIDTH-1),Otherwise the count will overflow
)
(
input clk, //clk Frequency 12 MHz
input rst_n, //Reset signal, low effective,
output clkout //Output signal, which can be connected to LED Clock for frequency division
);
reg    [WIDTH-1:0]    cnt_p,cnt_n; //cnt_p For the counter when the rise edge is triggered, cnt_n Counter when triggered for descent edge
reg    clk_p,clk_n; //clk_p To trigger a time-frequency clock for the rising edge, clk_n Time-frequency clock triggered for drop edge
//Control of counter when rise edge triggers
always @(posedge clk or negedge rst_n)    
    begin        
        if(!rst_n)
            cnt_p <= 1'b0;
        else if(cnt_p == (N-1))
            cnt_p <= 1'b0;
        else 
            cnt_p <= cnt_p + 1'b1; //The counter keeps counting and clears when it reaches N-1, which is a counter of modulo N
    end
//Rise-edge triggered crossover clock output,If N Clock duty cycle for odd number is not 50%;If N Clock Duty Cycle for Even Number is 50%
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            clk_p <= 1'b0;
        else if(cnt_p < (N>>1)) //N>>1 Means to move one bit to the right, equal to dividing by two to take a quotient
            clk_p <= 1'b0;
        else 
            clk_p <= 1'b1; //The positive cycle of the crossover clock is one more clk clock than the negative cycle
    end
//Counter control when drop edge triggers            
always @(negedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_n <= 1'b0;
        else if(cnt_n == (N-1))
            cnt_n <= 1'b0;
        else 
            cnt_n <= cnt_n + 1'b1;
    end
//Decrease the frequency division clock output along the trigger, and clk_p Half difference clk Clock
always @(negedge clk or negedge rst_n)
    begin
        if(!rst_n)
            clk_n <= 1'b0;
        else if(cnt_n < (N>>1))  
            clk_n <= 1'b0;
        else 
            clk_n <= 1'b1;    //The positive cycle of the crossover clock is one more clk clock than the negative cycle
    end
wire    clk1 = clk; //When N=1 When, direct output clk
wire    clk2 = clk_p; //When N Even number means N The lowest bit is 0, N[0]=0,output clk_p
wire    clk3 = clk_p & clk_n; //When N For odd numbers that is N The lowest bit is 1, N[0]=1,output clk_p&clk_n. Positive periods are many, so they are phase and
assign clkout = (N==1)? clk1:(N[0]? clk3:clk2);    //Conditional judgment expression
endmodule

3.8-digit tube display module

There are two eight-digit digital tubes on the little foot yam board, which are used to display the display from 00s to 59s in this experiment.Paste the code of the display module of the digital tube below.

module segment
(
input  wire [3:0] seg_data_1, //Four-bit Input Data Signal
input  wire [3:0] seg_data_2, //Four-bit Input Data Signal
output wire [8:0] segment_led_1, //Digital tube 1, MSB~LSB = SEG,DP,G,F,E,D,C,B,A
output wire [8:0] segment_led_2  //Digital Control 2, MSB~LSB = SEG,DP,G,F,E,D,C,B,A
);
reg[8:0] seg [15:0]; //Store 7 segments of digital tube decoding data
initial 
    begin
        seg[0] = 9'h3f;   //  0
        seg[1] = 9'h06;   //  1
        seg[2] = 9'h5b;   //  2
        seg[3] = 9'h4f;   //  3
        seg[4] = 9'h66;   //  4
        seg[5] = 9'h6d;   //  5
        seg[6] = 9'h7d;   //  6
        seg[7] = 9'h07;   //  7
        seg[8] = 9'h7f;   //  8
        seg[9] = 9'h6f;   //  9
        seg[10]= 9'h77;   //  A
        seg[11]= 9'h7C;   //  b
        seg[12]= 9'h39;   //  C
        seg[13]= 9'h5e;   //  d
        seg[14]= 9'h79;   //  E
        seg[15]= 9'h71;   //  F
    end
   assign segment_led_1 = seg[seg_data_1];
   assign segment_led_2 = seg[seg_data_2];
endmodule

4. Functional explanation

In the main module, in addition to instantiating the above two modules, you need to add some bricks to this stopwatch!It is mentioned in the title that this is a 60s stopwatch, and our digital tube display only goes from 00 to 59, but the maximum time range reaches 9 minutes. What can I do about it?Here we use a row of eight-bit LED lights on the little foot. When 59s is counted, the next second the digital tube returns to 00 and lights up one of the eight-bit LED lights to indicate that one minute has been counted.There are eight LED lights. When all eight lights are on, the tube has another chance to display from 00 to 59, so we get a stopwatch with a maximum timer of 9 minutes!Paste the code for the display part of the eight-digit LED light below.

always@(posedge clk)
     if(cnt1==4'b0)
         LED[7:0]<=8'b11111111;
     else if(cnt1==4'b0001)
         LED[7:0]<=8'b11111110;
     else if(cnt1==4'b0010)
         LED[7:0]<=8'b11111100;
     else if(cnt1==4'b0011)
         LED[7:0]<=8'b11111000;
     else if(cnt1==4'b0100)
         LED[7:0]<=8'b11110000;
     else if(cnt1==4'b0101)
         LED[7:0]<=8'b11100000;
     else if(cnt1==4'b0110)
         LED[7:0]<=8'b11000000;
     else if(cnt1<=4'b0111)
         LED[7:0]<=8'b10000000;
     else if(cnt1<=4'b1000)
         LED[7:0]<=8'b00000000;

In addition, as a stopwatch you naturally have the ability to pause and start the timer (and of course the zeroing function is also!The main module is implemented by rst reset key, which is not described here.)Pause and start timing I use the same key here.There are also two RGB tricolor lights on the little foot lamp board. Now that such good resources exist, we should make the most of them!When the start key is pressed, the stopwatch starts to time and the display on the digital tube starts to change. Here we let one of the RGB tricolor lights turn green equally to indicate that it is in the normal timing state. When the start key is pressed again, the stopwatch pauses and we let the other RGB tricolor light turn red to indicate that it is in the pausing state.Paste the code below which contains the three-color lights.

always @(posedge clk1h or negedge rst) //Generate a 60-bit counter
    begin    //Digital tube display should be displayed in decimal mode
        if(!rst)
        begin
            cnt <= 8'h00; //Reset Initial Display 00
            cnt1<=4'b0;
        end
        else if(flag)
            begin
            G_LED2<=1'b0;
            R_LED1<=1'b1;
                if(cnt[3:0] == 4'd9) //Nine seats full?
                    begin
                        cnt[3:0] <= 4'd0; //Bit Zeroing
                        if(cnt[7:4] == 4'd5 ) //Ten to five?
                        begin
                            cnt[7:4] <= 4'd0; //Ten-digit Zeroing
                            cnt1<=cnt1+1;
                        end
                        else
                        begin
                            cnt[7:4] <= cnt[7:4] + 1'b1; //Ten plus one
                            cnt1<=cnt1;
                        end
                    end
                else cnt[3:0] <= cnt[3:0] + 1'b1; //Bits plus one
            end
        else
        begin
            cnt <= cnt;
            G_LED2<=1'b1;
            R_LED1<=1'b0;
        end
    end

5. Main Module

Finally, paste the code of the main module to complete the implementation of the entire stopwatch.

module counter60 
(
input clk,rst, //Clock and Reset Input
input key, //Start pause button
output wire [8:0] segment_led_1,segment_led_2, //Digital tube output
output reg [7:0] LED, //Eight digits LED lamp
output reg R_LED1,G_LED2 //RGB Tri-color light, where red means paused and green means normal timing
);
wire clk1h;    //1 Seconds clock
reg    [7:0] cnt;    //Timing Counter
reg [3:0] cnt1; //Minute counter
reg    flag; //Start pause flag
 
divide #  //Instantiate frequency divider to generate 1 second clock signal
(
.WIDTH(24),
.N(12_000_000)
) u1
(
.clk(clk),
.rst_n(rst),
.clkout(clk1h)
);
segment u2 //Instantiate Digital Tube Display Module
(
.seg_data_1        (cnt[7:4]),  //seg_data input
.seg_data_2        (cnt[3:0]),  //seg_data input
.segment_led_1    (segment_led_1),  //MSB~LSB = SEG,DP,G,F,E,D,C,B,A
.segment_led_2    (segment_led_2)   //MSB~LSB = SEG,DP,G,F,E,D,C,B,A
);
always @(posedge clk or negedge rst) //Generate a flag signal
begin
if(!rst)
        flag = 1'b0;
else if(!key)
     begin
        flag = ~flag;
        end
    else
    begin
        flag = flag;
        end
end
always @(posedge clk1h or negedge rst) //Generate a 60-bit counter
    begin    //Digital tube display should be displayed in decimal mode
        if(!rst)
        begin
            cnt <= 8'h00; //Reset Initial Display 00
            cnt1<=4'b0;
        end
        else if(flag)
            begin
            G_LED2<=1'b0;
            R_LED1<=1'b1;
                if(cnt[3:0] == 4'd9) //Nine seats full?
                    begin
                        cnt[3:0] <= 4'd0; //Bit Zeroing
                        if(cnt[7:4] == 4'd5 ) //Ten to five?
                        begin
                            cnt[7:4] <= 4'd0; //Ten-digit Zeroing
                            cnt1<=cnt1+1;
                        end
                        else
                        begin
                            cnt[7:4] <= cnt[7:4] + 1'b1; //Ten plus one
                            cnt1<=cnt1;
                        end
                    end
                else cnt[3:0] <= cnt[3:0] + 1'b1; //Bits plus one
            end
        else
        begin
            cnt <= cnt;
            G_LED2<=1'b1;
            R_LED1<=1'b0;
        end
    end
always@(posedge clk)
     if(cnt1==4'b0)
         LED[7:0]<=8'b11111111;
     else if(cnt1==4'b0001)
         LED[7:0]<=8'b11111110;
     else if(cnt1==4'b0010)
         LED[7:0]<=8'b11111100;
     else if(cnt1==4'b0011)
         LED[7:0]<=8'b11111000;
     else if(cnt1==4'b0100)
         LED[7:0]<=8'b11110000;
     else if(cnt1==4'b0101)
         LED[7:0]<=8'b11100000;
     else if(cnt1==4'b0110)
         LED[7:0]<=8'b11000000;
     else if(cnt1<=4'b0111)
         LED[7:0]<=8'b10000000;
     else if(cnt1<=4'b1000)
         LED[7:0]<=8'b00000000;
endmodule

module divide #
(                            //parameter yes verilog Definition of internal parameters
parameter WIDTH    =    24,    //The number of bits in the counter, with a maximum count of 2**(WIDTH-1)
parameter N        =    12_000_000 //Crossover factor, make sure N<2**(WIDTH-1),Otherwise the count will overflow
)
(
input clk, //clk Frequency 12 MHz
input rst_n, //Reset signal, low effective,
output clkout //Output signal, which can be connected to LED Clock for frequency division
);
reg    [WIDTH-1:0]    cnt_p,cnt_n; //cnt_p For the counter when the rise edge is triggered, cnt_n Counter when triggered for descent edge
reg    clk_p,clk_n; //clk_p To trigger a time-frequency clock for the rising edge, clk_n Time-frequency clock triggered for drop edge
//Control of counter when rise edge triggers
always @(posedge clk or negedge rst_n)    
    begin        
        if(!rst_n)
            cnt_p <= 1'b0;
        else if(cnt_p == (N-1))
            cnt_p <= 1'b0;
        else 
            cnt_p <= cnt_p + 1'b1; //The counter keeps counting and clears when it reaches N-1, which is a counter of modulo N
    end
//Rise-edge triggered crossover clock output,If N Clock duty cycle for odd number is not 50%;If N Clock Duty Cycle for Even Number is 50%
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            clk_p <= 1'b0;
        else if(cnt_p < (N>>1)) //N>>1 Means to move one bit to the right, equal to dividing by two to take a quotient
            clk_p <= 1'b0;
        else 
            clk_p <= 1'b1; //The positive cycle of the crossover clock is one more clk clock than the negative cycle
    end
//Counter control when drop edge triggers            
always @(negedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_n <= 1'b0;
        else if(cnt_n == (N-1))
            cnt_n <= 1'b0;
        else 
            cnt_n <= cnt_n + 1'b1;
    end
//Decrease the frequency division clock output along the trigger, and clk_p Half difference clk Clock
always @(negedge clk or negedge rst_n)
    begin
        if(!rst_n)
            clk_n <= 1'b0;
        else if(cnt_n < (N>>1))  
            clk_n <= 1'b0;
        else 
            clk_n <= 1'b1;    //The positive cycle of the crossover clock is one more clk clock than the negative cycle
    end
wire    clk1 = clk; //When N=1 When, direct output clk
wire    clk2 = clk_p; //When N Even number means N The lowest bit is 0, N[0]=0,output clk_p
wire    clk3 = clk_p & clk_n; //When N For odd numbers that is N The lowest bit is 1, N[0]=1,output clk_p&clk_n. Positive periods are many, so they are phase and
assign clkout = (N==1)? clk1:(N[0]? clk3:clk2);    //Conditional judgment expression
endmodule

module segment
(
input  wire [3:0] seg_data_1, //Four-bit Input Data Signal
input  wire [3:0] seg_data_2, //Four-bit Input Data Signal
output wire [8:0] segment_led_1, //Digital tube 1, MSB~LSB = SEG,DP,G,F,E,D,C,B,A
output wire [8:0] segment_led_2  //Digital Control 2, MSB~LSB = SEG,DP,G,F,E,D,C,B,A
);
reg[8:0] seg [15:0]; //Store 7 segments of digital tube decoding data
initial 
    begin
        seg[0] = 9'h3f;   //  0
        seg[1] = 9'h06;   //  1
        seg[2] = 9'h5b;   //  2
        seg[3] = 9'h4f;   //  3
        seg[4] = 9'h66;   //  4
        seg[5] = 9'h6d;   //  5
        seg[6] = 9'h7d;   //  6
        seg[7] = 9'h07;   //  7
        seg[8] = 9'h7f;   //  8
        seg[9] = 9'h6f;   //  9
        seg[10]= 9'h77;   //  A
        seg[11]= 9'h7C;   //  b
        seg[12]= 9'h39;   //  C
        seg[13]= 9'h5e;   //  d
        seg[14]= 9'h79;   //  E
        seg[15]= 9'h71;   //  F
    end
   assign segment_led_1 = seg[seg_data_1];
   assign segment_led_2 = seg[seg_data_2];
endmodule

 

6. Summary

The whole stopwatch is done here.Finally, I apologize to the readers again for not being able to attach the experimental results.Readers with lab boards can burn code into the board to see the phenomenon.I have limited programming level and time, this article is about to end here, welcome readers to comment on the message, and more welcome you to point out my shortcomings, I hope to improve through communication.Finally, thank you for your patience!

Posted by kruahsohr on Sun, 15 Dec 2019 00:44:15 -0800