CLK net warning for stopwatch code on FPGA nexys2 board

7segmentdisplayfpgaverilog

I'm coding for a stopwatch which displays 10ths of a second on the rightmost two displays and seconds on the left two displays. The synthesis completes properly but after I make the UCF file and try to implement the design the following two warnings occur.

WARNING:CLK Net: check

WARNING:CLK Net: carry

I tried ignoring the warnings and went to generate the programming file but this warning came up and nothing happened on the FPGA kit and all the displays had 8 on them.

WARNING:PhysDesignRules:372 – Gated clock. Clock net check is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.

I have no idea what any of these warnings even mean and I tried searching for them online but I found nothing from which I could understand my problem. I figured that there is something wrong with the check and carry variables but I'm having no luck fixing the problem as it seems all fine to me logic wise. And also I'm having a hard time being trying to figure out how to start and pause the stopwatch. Here's my code:

module stopwatch(clk,rst,a,b,c,d,e,f,g,dot,an);

input clk,rst;
output a,b,c,d,e,f,g,dot;
output [3:0] an;

reg [22:0] count_time;
reg [3:0] first,second,third,fourth;
reg check;
reg carry;

//counting 1 second and producing a tick at every 1 second

always @ (posedge clk or posedge rst)
begin
    if(rst)
      begin
      count_time <=0;
      check<=0;
      end
    else
      begin
      count_time<=count_time+1;
        if(&count_time==1)
         check<=1;
        else
         check<=0;
      end
end

//counting on last two SSDs

always @ (posedge check or posedge rst)
begin
    if (rst)
      begin
      third<=0;
      fourth<=0;
      end
    else if(fourth==9)
      begin
        if(third==1)
         begin
         third<=0;
         fourth<=0;
         carry<=1;
         end
        else
         begin
         third<=third+1;
         fourth<=0;
         carry<=0;
         end
      end
    else
      fourth<=fourth+1;
end

//counting one First two SSDs

always @ (posedge carry or posedge rst)
begin
   if (rst)
     begin
     first<=0;
     second<=0;
     end
   else if(second==9)
     begin
       if(first==9)
         begin
         first<=0;
         second<=0;
         end
       else
         begin
         first<=first+1;
         second<=0;
         end
     end
   else
     second<=second+1;
end

//multiplexing of 4 SSDs using the 'an' bits

parameter X = 18; //we will use the top 2 bits (since 4 SSDs) for multiplexing and the lower X-2 bits for frequency control
reg [X-1:0] counter;

always @ (posedge clk or posedge rst) //counter to produce multiplexing
begin
 if(rst)
   counter<=0;
 else
   counter<=counter+1;
end 

reg [3:0] an_temp;
reg [6:0] out;

always @ *
begin
case(counter[X-1:X-2])

   2'b00:
    begin
     out = fourth;
     an_temp = 4'b1110;
    end

   2'b01:
    begin
     out = third;
     an_temp = 4'b1101;
    end

   2'b10:
    begin
     out = second; //dont care
     an_temp = 4'b1011;
    end

   2'b11:
    begin
     out = first; //dont care
     an_temp = 4'b0111;
    end

endcase
end

assign an = an_temp;

//sending digits to SSDs for each muliplexing interval

reg [6:0] temp;
always @ *
begin
case(out)
   4'd0 : temp = 7'b0000001; 
   4'd1 : temp = 7'b1001111; 
    4'd2 : temp = 7'b0010010; 
   4'd3 : temp = 7'b0000110; 
   4'd4 : temp = 7'b1001100; 
   4'd5 : temp = 7'b0100100; 
   4'd6 : temp = 7'b0100000; 
   4'd7 : temp = 7'b0001111; 
   4'd8 : temp = 7'b0000000; 
   4'd9 : temp = 7'b0000100; 
   default : temp = 7'b1001000; // H
  endcase
end 

assign {a,b,c,d,e,f,g} = temp;
assign dot = 1'b1; //dots are off

endmodule

Best Answer

Firstly I'm assuming the signal clk is a nice clean clock signal driven from outside the FPGA, maybe by crystal oscillator, LVDS clock source or similar, preferably on a dedicated clock pin?

Your code creates a roll-over counter stored in count_time that overflows to zero after 22-bits, where cycle with all-1's sets signal check high for one cycle. So far all fine.

always @ (posedge clk or posedge rst) begin
    if (rst) begin
      count_time <=0;
      check <=0;
    end else begin
      count_time <= count_time+1;
      check      <= &count_time;
    end
end

The problem is how you use the signal check. You have added it to the sensitivity list of the process //counting on last two SSDs. Since this signal is the output from a flip flop, rather than a nice clean external clock signal, the tools are warning you. This arrangement (logic from one stage feeding the CLOCK of a subsequent register) is called a "gated clock". It is popular in ASIC design but not good synchronous design practice for targeting FPGAs.

The way to solve this is to re-write your code so that all processes are sensitive only to the clk and rst signals. The signal check will be promoted to become the CLOCK ENABLE input for all the logic within the process, I'll do one to get you started:

//counting on last two SSDs

always @ (posedge clk or posedge rst) begin
    if (rst) begin
      third <= 0;
      fourth <= 0;
    end else if (check) begin
        if (fourth==9) begin
           fourth<=0;
           if (third==1) begin
              third <= 0;
              carry <= 1;
           end else begin
              third <= third + 1;
              carry <= 0;
           end
        end else begin
          fourth <= fourth+1;
        end
    end
end

This probably isn't why the design doesn't work, but it should clear up those warnings and put you on the right path. It would be advisable to get this running in a simulator like Icarus Verilog to see if the design has any fundamental problems.

You also should:

  • register the output of a,b,c,d,e,f,g,dot and anodes an so they reveal to the outside world on a common clock edge, rather than after arbitary logic/routing delays. The reg will be absorved into the pin I/O pads so don't worry about 'extra' logic usage, you'll have it anyway

  • Depending on what the source (clk) clock rate is, you might want to massively reduce the base frequency of the multiplexed outputs (using enables again) - it won't work effectively if the active time for each display is just hundreds of nanoseconds before switching. To get flicker free visual aliasing aim for a redraw of about 25-50Hz on each digit, so with four displays you want to switch the output at 200-500hz. I would add many more bits to counter and use the upper bits to drive the multiplexer.