Design and Implementation of a Digital Clock Module on FPGA

Digital Clock Functionality

The design implements a digital clock module with reset and pause capabilities, featuring a 6-digit display for hundredths of seconds, seconds, and minutes.

Module Structure

Top-Level Module

module dcmk(clk, clr, pause, seg1, seg2, com);
  input clk, clr;
  input pause;
  output [7:0] seg1, seg2, com;

  wire [3:0] msl, msh, sl, sh, ml, mh;

  szmk u4 (
    .clk(clk),
    .clr(clr),
    .pause(pause),
    .msl(msl),
    .msh(msh),
    .sl(sl),
    .sh(sh),
    .ml(ml),
    .mh(mh)
  );

  segmk u5 (
    .clk(clk),
    .clr(clr),
    .msl(msl),
    .msh(msh),
    .sl(sl),
    .sh(sh),
    .ml(ml),
    .mh(mh),
    .seg1(seg1),
    .seg2(seg2),
    .com(com)
  );

endmodule

Clock Control Module

module szmk(clk, clr, pause, msl, msh, sl, sh, ml, mh);
  input clk, clr;
  input pause;
  output [3:0] msl, msh, sl, sh, ml, mh;

  wire cn1, cn2;

  msmk u1 (
    .clk(clk),
    .clr(clr),
    .pause(pause),
    .cn1(cn1),
    .msl(msl),
    .msh(msh)
  );

  smk u2 (
    .clk(cn1),
    .clr(clr),
    .pause(pause),
    .cn2(cn2),
    .sl(sl),
    .sh(sh)
  );

  mmk u3 (
    .clk(cn2),
    .clr(clr),
    .pause(pause),
    .ml(ml),
    .mh(mh)
  );

endmodule

Hundredths Second Counter

module msmk(clk, clr, pause, cn1, msl, msh);
  input clk, clr;
  input pause;
  output reg cn1;
  output [3:0] msl, msh;

  reg [3:0] cnt;
  reg [3:0] tens;

  always @(posedge clk or posedge clr) begin
    if (clr) begin
      cnt <= 0;
      tens <= 0;
    end else if (!pause) begin
      cnt <= cnt + 1;
      if (cnt == 9) begin
        cnt <= 0;
        tens <= tens + 1;
        if (tens == 9) begin
          tens <= 0;
          cn1 <= 1;
        end else begin
          cn1 <= 0;
        end
      end else begin
        cn1 <= 0;
      end
    end else begin
      cn1 <= 0;
    end
  end

  assign msl = cnt;
  assign msh = tens;

endmodule

Seconds Counter

module smk(clk, clr, pause, cn2, sl, sh);
  input clk, clr;
  input pause;
  input cn1;
  output reg cn2;
  output [3:0] sl, sh;

  reg [3:0] sec;
  reg [3:0] tens_sec;

  always @(posedge clk or posedge clr) begin
    if (clr) begin
      sec <= 0;
      tens_sec <= 0;
    end else if (!pause) begin
      if (cn1) begin
        sec <= sec + 1;
        if (sec == 9) begin
          sec <= 0;
          tens_sec <= tens_sec + 1;
          if (tens_sec == 5) begin
            tens_sec <= 0;
            cn2 <= 1;
          end else begin
            cn2 <= 0;
          end
        end else begin
          cn2 <= 0;
        end
      end else begin
        cn2 <= 0;
      end
    end else begin
      cn2 <= 0;
    end
  end

  assign sl = sec;
  assign sh = tens_sec;

endmodule

Minutes Counter

module mmk(clk, clr, pause, ml, mh);
  input clk, clr;
  input pause;
  input cn2;
  output [3:0] ml, mh;

  reg [3:0] min;
  reg [3:0] tens_min;

  always @(posedge clk or posedge clr) begin
    if (clr) begin
      min <= 0;
      tens_min <= 0;
    end else if (!pause) begin
      if (cn2) begin
        min <= min + 1;
        if (min == 9) begin
          min <= 0;
          tens_min <= tens_min + 1;
          if (tens_min == 5) begin
            tens_min <= 0;
          end
        end
      end
    end
  end

  assign ml = min;
  assign mh = tens_min;

endmodule

Segment Display Driver

module segmk(clk, clr, msl, msh, sl, sh, ml, mh, seg1, seg2, com);
  input clk, clr;
  input [3:0] msl, msh, sl, sh, ml, mh;
  output [7:0] seg1, seg2, com;

  wire [7:0] digit1, digit2, digit3, digit4, digit5, digit6;

  // Convert BCD to 7-segment codes
  bcd_to_seg b1 (.bcd(msl), .seg(digit1));
  bcd_to_seg b2 (.bcd(msh), .seg(digit2));
  bcd_to_seg b3 (.bcd(sl), .seg(digit3));
  bcd_to_seg b4 (.bcd(sh), .seg(digit4));
  bcd_to_seg b5 (.bcd(ml), .seg(digit5));
  bcd_to_seg b6 (.bcd(mh), .seg(digit6));

  // Multiplex display
  reg [2:0] sel;
  always @(posedge clk) begin
    sel <= sel + 1;
  end

  assign seg1 = (sel == 0) ? digit1 : 
               (sel == 1) ? digit2 : 
               (sel == 2) ? digit3 : 
               (sel == 3) ? digit4 : 
               (sel == 4) ? digit5 : 
               digit6;

  assign seg2 = (sel == 0) ? digit2 : 
               (sel == 1) ? digit3 : 
               (sel == 2) ? digit4 : 
               (sel == 3) ? digit5 : 
               (sel == 4) ? digit6 : 
               digit1;

  assign com = (sel == 0) ? 3'b110 : 
               (sel == 1) ? 3'b101 : 
               (sel == 2) ? 3'b011 : 
               (sel == 3) ? 3'b110 : 
               (sel == 4) ? 3'b101 : 
               3'b011;

endmodule

BCD to 7-Segment Converter

module bcd_to_seg(bcd, seg);
  input [3:0] bcd;
  output reg [7:0] seg;

  always @(*) begin
    case (bcd)
      4'd0: seg = 8'b10000000;
      4'd1: seg = 8'b11110010;
      4'd2: seg = 8'b10011000;
      4'd3: seg = 8'b10001000;
      4'd4: seg = 8'b11000010;
      4'd5: seg = 8'b10100000;
      4'd6: seg = 8'b10100000;
      4'd7: seg = 8'b10000010;
      4'd8: seg = 8'b10000000;
      4'd9: seg = 8'b10000000;
      default: seg = 8'b11111111;
    endcase
  end

endmodule

Operation Details

The system operates using a 50MHz clock signal. The design includes three cascaded counters for hundredths of seconds, seconds, and minutes. Each counter uses a 4-bit BCD representation.

The pause signal halts the counting process while maintaining current values. The reset signal initializes all counters to zero.

Display multiplexing cycles through six digits to create a visual representation of time.

Verification

Simulation confirms correct operation of each counter stage and proper segment encoding. Hardware testing verifies funcsionality on the target FPGA board.

Tags: FPGA digital-clock Verilog hdl embedded-systems

Posted on Fri, 26 Jun 2026 17:33:31 +0000 by shadow-x