+ Post New Thread
Results 1 to 7 of 7
  1. #1
    Newbie level 4
    Points: 33, Level: 1

    Join Date
    Mar 2020
    Location
    Orlando, Fla
    Posts
    5
    Helped
    0 / 0
    Points
    33
    Level
    1

    Verilog alarm clock time advancing not working correctly ..

    Hello. I am new to verilog and to this forum, and have been trying to get an alarm clock working on the BASYS 3 FPGA board using Vivado 2019. All the code is working correctly except for the part that advances the time. The problem is that both the seconds and minutes advance together .. so essentially the seconds display as minutes and the minutes as hours. I have included a code snippet below.

    The input clock is at a .1 sec rate. The first part of the code is used to set the min and sec and works correctly. The second part causes the decimal point of the 7-segment display and an LED to blink at a one second rate and also works correctly. The third part steps the second and minutes together. I have tried using blocking and non-blocking code (as here) with the same results. The problem has been verified both on the Vivado simulator and on the BASYS board.

    I'll be happy to be embarrassed by what is obviously a newly mistake!

    Thanks for the help. Jim

    Code:
     /************* Clock operation**************/
    
    always @(posedge first_toggle)  //toggle every .1 sec
     
    begin 
           if (reset)
                   begin                // reset counters
                     tmp_chour = 4'b0000;
                     tmp_cmin  = 4'b0000;
                     tmp_csec  = 4'b0000;
                   end 
                
    //set alarm/clock min
    
            if (set_min)        // set  minutes
                 begin
                     if ((min_del == 0) || (min_del >= 15 ))  // first toggle on key press or 1.5 sec delay
                           begin
                              if (set_alarm)              // Set alarm ?
                                  if(tmp_amin >= 59)      // Min >= 59 ?
                                      tmp_amin = 0;       // Yes - Zero alarm min
                                  else                          
                                      tmp_amin = tmp_amin + 1; //No - bump alarm min
                              else if(tmp_cmin >= 59)     // Min >= 59 ?
                                      tmp_cmin = 0;       // Yes - Zero clock min
                                   else                          
                                      tmp_cmin = tmp_cmin + 1; //No - bump clock min
                              if (min_del <= 14)          // 1.5 sec delay for fast speed
                                  min_del <= min_del +1;  // Bump delay tenths of a sec        
                           end
                     else if (min_del <= 14)              // 1.5 sec delay for fast speed
                              min_del <= min_del +1;      // Bump delay tenths of a sec
                  end
             else
                  min_del = 0; // Clear min delay             
               
    //set alarm/clock hours
    
            if (set_hour)        // set  hour
                 begin
                     if ((hour_del == 0) || (hour_del >= 15 )) // first toggle on key press or 1.5 sec delay
                           begin
                              if (set_alarm && mode == 1)  // Set alarm and 24 hour ?
                                  if(tmp_ahour >= 23)      // 24 hour mode?
                                      tmp_ahour = 0;       // Yes - Zero ahour
                                  else                          
                                      tmp_ahour = tmp_ahour + 1; // No - bump ahour
                              else if (set_alarm && mode == 0)   // Set alarm and 12 hour ?
                                  if(tmp_ahour >= 12)      // 12 hour mode?                       
                                      tmp_ahour = 0;       // Yes - Zero ahour
                                  else
                                      tmp_ahour = tmp_ahour + 1; // No - bump ahour
                              else if (!set_alarm && mode == 1)  // Set clock and 24 hour ?
                                  if(tmp_chour >= 23)      // 24 hour mode?
                                      tmp_chour = 0;       // Yes - Zero clock hour
                                  else                          
                                      tmp_chour = tmp_chour + 1; // No - bump clock hour
                              else if (!set_alarm && mode == 0)  // Set clock and 12 hour ?
                                  if(tmp_chour >= 12)      // 12 hour mode?                       
                                      tmp_chour = 0;       // Yes - Zero clock hour
                                  else
                                      tmp_chour = tmp_chour + 1; // No - bump clock hour
                              if (hour_del <= 14)          // Fast delay up?
                              hour_del <= hour_del +1;     // No - Bump fast delay   
                           end
                     else if (hour_del <= 14)              // 1.5 sec delay for fast speed
                              hour_del <= hour_del +1;     // Bump delay tenths of a sec
                  end
             else
                  hour_del = 0; // Clear hour delay       
     
    //Normal clock operation
    
    // This code is entered once every tenth second
    
    // Turn decimal point and LED #1 on for approx .5 sec
    
            if (tenth_counter >= 5)
                 begin
                     dp_tmp <= 1;    // Turn decimal point off
                     LED16 <= 0;     // Turn LED off
                 end
             else
                 begin
                     dp_tmp <= 0;    // Turn decimal point on
                     LED16 <= 1;     // Turn LED on
                 end
    
    // Advance count on ninth of ten "tenth counts"
    // tmp_csec, cmin, chour > clock second, minuter, hours
    
             if (tenth_counter >= 9)                  //advance time if tenth count is 9
                   begin
                     tenth_counter <= 0;              // Reset tenth counter
                     
                     if(tmp_csec >= 59)               // second > 59 then minute increases
                         begin 
                             tmp_csec <= 0;            // clear second count
                             tmp_cmin <= tmp_cmin + 1; // bump the minute count
                         end
                     else 
                         begin    
                             tmp_csec <= tmp_csec + 1; //bump the second count  
                         end
                     if(tmp_cmin >= 59)                // minute > 59 then hour increases
                         begin 
                             tmp_cmin <= 0;            // clear the minute count
                             tmp_chour <= tmp_chour + 1;// bump the hour count
                         end
                      else
                         begin
                             tmp_cmin <= tmp_cmin + 1;  // bump the minute count
                         end
                             
                     if(mode == 1 && tmp_chour >= 24)   // 24 hour mode = 1 12 hour = 0
                             tmp_chour <= 0;            // 24 hours 0-23
                     else  if (mode == 0 && tmp_chour >= 13)
                             tmp_chour <= 1;            // 12 hour mode 1-12
                   end
              else
                   tenth_counter <= tenth_counter + 1;  // Bump tenth counter
      end

    •   AltAdvertisement

        
       

  2. #2
    Super Moderator
    Points: 81,996, Level: 69
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    16,642
    Helped
    3771 / 3771
    Points
    81,996
    Level
    69

    Re: Verilog alarm clock time advancing not working correctly ..

    Hi,

    I expect:
    At the same time when
    * tenth_counter is reset to zero
    * you also need to increment the seconds counter.
    Allways.

    But in your code both lines are far apart and one is behind an additional "IF".

    Could you show us your flow chart? If you didn't draw already, then do it now.
    Did you run a simulation of your code? Or at least take a piece of paper and a pencil to do the same by hand.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  3. #3
    Super Moderator
    Points: 32,398, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,489
    Helped
    1758 / 1758
    Points
    32,398
    Level
    43

    Re: Verilog alarm clock time advancing not working correctly ..

    Don't mix blocking and non-blocking assignments in a edge triggered always block. Only use non-blocking assignments in clocked logic and blocking in combonational always blocks.

    Using blocking assignments with code like this:
    Code:
                                  if(tmp_chour >= 23)      // 24 hour mode?
                                      tmp_chour = 0;       // Yes - Zero clock hour
                                  else                          
                                      tmp_chour = tmp_chour + 1; // No - bump clock hour
    causes synthesis to generate a FF -> add_1 -> compare code increasing the combinational logic path between flip-flops. Occasionally you might want to take advantage of this, but with a Verilog newbie you want to avoid anything like this.

    The structure of this code seems somewhat convoluted for the task.

    Seems to me you aren't generating a 10th sec counter enable to run the sec/min/hr counters. Try looking up pipelined counters and structure the code like those types of counters, the only difference between a clock counter and a binary pipelined counter is the rollover conditions of each stage.

    Typical pipelined counter (for a clock) with enable would be:

    1. 1/10 sec counter, rolls over every 1 sec.
    2. enable code to generate a pulse every 1 sec (can use the 1/10 sec counter rollover condition)
    3. sec counter, counts on every 1 sec enable, rolls over on a count of 59
    4. min counter, counts on the sec counter equal to 59 on a 1 sec enable
    5. hr counter, counts on the min counter equal to 59 on a 1 sec enable



    •   AltAdvertisement

        
       

  4. #4
    Newbie level 4
    Points: 33, Level: 1

    Join Date
    Mar 2020
    Location
    Orlando, Fla
    Posts
    5
    Helped
    0 / 0
    Points
    33
    Level
    1

    Re: Verilog alarm clock time advancing not working correctly ..

    Thank you for the reply! I just noticed that I got a Synthesis warning message ..

    "[Synth 8-6014] Unused sequential element tmp_csec_reg was removed. ["C:/Verilog/AlarmClock/AlarmClock.srcs/sources_1/imports/Alarm Clock/AlarmClockMod.v":98]"
    This refers to the line marked with <<< below. Maybe this has something to do with my problem? This is how the reg is identified.

    code snip...

    Code:
     reg [24:0] first_counter;          // .1 sec counter for rapid time set
     reg [3:0] tenth_counter;           // 1 sec counter
     reg [5:0] tmp_chour, tmp_cmin, tmp_csec;                 <<<<<<<<<<<<<<<<
     reg [5:0] tmp_ahour, tmp_amin, tmp_asec;


    Code:
    /************* Clock operation**************/
    
    always @(posedge first_toggle)  //toggle every .1 sec
     
    begin 
           if (reset)
                   begin                // reset counters
                     tmp_chour <= 4'b0000;
                     tmp_cmin  <= 4'b0000;
                     tmp_csec  <= 4'b0000;                 <<<<<<<<< line 98
                   end 
                
    //set alarm/clock min
    
            if (set_min)        // set  minutes
                 begin
                     if ((min_del == 0) || (min_del >= 15 ))  // first toggle on key press or 1.5 sec delay
    Thanks. Jim



  5. #5
    Newbie level 4
    Points: 33, Level: 1

    Join Date
    Mar 2020
    Location
    Orlando, Fla
    Posts
    5
    Helped
    0 / 0
    Points
    33
    Level
    1

    Re: Verilog alarm clock time advancing not working correctly ..

    ads-ee Thank you! I have changed all the code to non_blocking. The tenth counter is a 4 bit counter initialized to 0.
    All this code is executes every .1 sec.

    Code:
        first_counter = 0;
        tenth_counter = 0;
        first_toggle = 0;
    .....and is tested for a "nine" count before the time code and incremented after the time code.

    Code:
             if (tenth_counter >= 9)                  //advance time if tenth count is 9  <<<<<<<<<
                   begin
                     tenth_counter <= 0;              // Reset tenth counter                           <<<<<<<<<<
                     
                     if(tmp_csec >= 59)               // second > 59 then minute increases
                         begin 
                             tmp_csec <= 0;            // clear second count
                             tmp_cmin <= tmp_cmin + 1; // bump the minute count
                         end
                     else 
                         begin    
                             tmp_csec <= tmp_csec + 1; //bump the second count  
                         end
                     if(tmp_cmin >= 59)                // minute > 59 then hour increases
                         begin 
                             tmp_cmin <= 0;            // clear the minute count
                             tmp_chour <= tmp_chour + 1;// bump the hour count
                         end
                      else
                         begin
                             tmp_cmin <= tmp_cmin + 1;  // bump the minute count
                         end
                             
                     if(mode == 1 && tmp_chour >= 24)   // 24 hour mode = 1 12 hour = 0
                             tmp_chour <= 0;            // 24 hours 0-23
                     else  if (mode == 0 && tmp_chour >= 13)
                             tmp_chour <= 1;            // 12 hour mode 1-12
                   end
              else
                   tenth_counter <= tenth_counter + 1;  // Bump tenth counter          <<<<<<<<<<<<
    Thanks. Jim

    - - - Updated - - -

    Well, I seem to have found the problem.

    Code:
            if (tenth_counter >= 9)                  //advance time if tenth count is 9
                   begin
                     tenth_counter <= 0;              // Reset tenth counter
                     
                     if(tmp_csec >= 59)               // second > 59 then minute increases
                         begin 
                             tmp_csec <= 0;            // clear second count
                             tmp_cmin <= tmp_cmin + 1; // bump the minute count    <<<<<<<<<<<<<<<<<<<
                         end
                     else 
                         begin    
                             tmp_csec <= tmp_csec + 1; //bump the second count  
                         end
                     if(tmp_cmin >= 59)                // minute > 59 then hour increases
                         begin 
                             tmp_cmin <= 0;            // clear the minute count
                             tmp_chour <= tmp_chour + 1;// bump the hour count
                         end
                      else
                         begin
                             tmp_cmin <= tmp_cmin + 1;  // bump the minute count           <<<<<<<<<<<<<<<<<<
                         end
    The Synthesis was not happy with two "tmp_cmin <= tmp_cmin + 1" statements ... which also caused the min to advance incorrectly. Why it caused the "[Synth 8-6014] Unused sequential element tmp_csec_reg was removed. ["C:/Verilog/AlarmClock/AlarmClock.srcs/sources_1/imports/Alarm Clock/AlarmClockMod.v":98]" error of the prior post, I don't know.

    Anyway, I have revised this part of the code to fix a glitch .. "min unit digit reseting to zero before the tens digit" .. to this...

    Code:
    // Advance count on ninth of ten "tenth counts"
    // tmp_csec, cmin, chour > clock second, minuter, hours
    
             if (tenth_counter >= 9)                         // advance time if tenth count is 9
                   begin
                     tenth_counter <= 0;                     // Reset tenth counter
                     
                      if(tmp_csec >= 59)                     // second > 59 then minute increases
                         begin
                            tmp_csec <= 0;                   // clear second count
                            if(tmp_cmin >= 59)
                                begin                        // minute > 59 then hour increases
                                   tmp_cmin <= 0;            // clear the minute count
                                   if(mode == 1 && tmp_chour >= 23)   // 24 hour mode = 1 hours 0-23
                                       tmp_chour <= 0;       // set the hour count to 0
                                   else
                                       tmp_chour <= tmp_chour +1;// bump the hour count 
                                   if (mode == 0 && tmp_chour >= 12) // 12 hour mode = 0 hours 1-12
                                       tmp_chour <= 1;       // set the hour count to 1
                                   else
                                       tmp_chour <= tmp_chour +1;// bump the hour count 
                                end
                            else                            
                                tmp_cmin <= tmp_cmin + 1; // bump the minute count
                         end
                      else
                            tmp_csec <= tmp_csec + 1;     // bump the second count    
                  
                 end
              else
                   tenth_counter <= tenth_counter + 1;    // Bump tenth counter
      end
    ....and now all works correctly.

    Thanks guys for your time!

    Jim



  6. #6
    Super Moderator
    Points: 32,398, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,489
    Helped
    1758 / 1758
    Points
    32,398
    Level
    43

    Re: Verilog alarm clock time advancing not working correctly ..

    Your code is difficult to read with all the extra indents and there are too many nested if's. IMO coding in HDLs you should limit both the nesting and the indenting along with not combining a bunch of different signals into a single always block. e.g.

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    
    `timescale 1ns/1ps
     
    module pipe_cntr (
      input clk,
      input rst,
      output [8:0] cntr
    );
     
      reg  [2:0]  cnt_hi;
      reg  [2:0]  cnt_mi;
      reg  [2:0]  cnt_lo;
      wire        tc_lo;
      wire        tc_mi;
     
     
      assign cntr = {cnt_hi, cnt_mi, cnt_lo};
     
      // terminal count of the lower two stages
      assign tc_lo = cnt_lo == 3'h 7;
      assign tc_mi = cnt_mi == 3'h 7;
     
     
      // lower counter, increments continuously
      always @(posedge clk, posedge rst) begin
        if (rst) begin
          cnt_lo <= 0;
        end else if (cnt_lo < 3'h 7) begin
          cnt_lo <= cnt_lo + 1;
        end else begin
          cnt_lo <= 0;
        end
      end
     
      // middle counter only counts if we are at the terminal count of the
      // lower counter
      always @(posedge clk, posedge rst) begin
        if (rst) begin
          cnt_mi <= 0;
        end else if (tc_lo) begin
          if (cnt_mi < 3'h 7) begin
            cnt_mi <= cnt_mi + 1;
          end else begin
            cnt_mi <= 0;
          end
        end
      end
     
      // high counter only counts if we are at the terminal count of both
      // the lower and middle counter
      always @(posedge clk, posedge rst) begin
        if (rst) begin
          cnt_hi <= 0;
        end else if (tc_lo && tc_mi) begin
          if (cnt_hi < 3'h 7) begin
            cnt_hi <= cnt_hi + 1;
          end else begin
            cnt_hi <= 0;
          end
        end
      end
     
     
    endmodule
     
     
    module tb;
     
      reg clk, rst;
      wire [8:0] cntr;
     
      initial clk = 0;
      always #10 clk = ~clk;
     
      pipe_cntr  uut (
        .clk    (clk),
        .rst    (rst),
        .cntr   (cntr)
      );
     
     
      initial begin
        rst = 1;
        #100;
        rst = 0;
        #10000;
        $stop;
      end
     
     
    endmodule

    Is an example of how I would write a pipelined counter with different counters for each stage (3 stages), being broken up into each stage makes it easy to see how the counters interact.

    You can run the simulation and see how the counters work with the terminal counts letting the next stage know when to count.
    Last edited by ads-ee; 4th March 2020 at 01:34. Reason: fixed typo


    1 members found this post helpful.

    •   AltAdvertisement

        
       

  7. #7
    Newbie level 4
    Points: 33, Level: 1

    Join Date
    Mar 2020
    Location
    Orlando, Fla
    Posts
    5
    Helped
    0 / 0
    Points
    33
    Level
    1

    Re: Verilog alarm clock time advancing not working correctly ..

    ads-ee. Thank you much! I will check out the pipelined counter technique. Phew..a lot to learn!

    Jim



--[[ ]]--