FPGA学习之数字钟的实现

简单的数字钟的实现还是很easy的。至少思路很简单。
但是正是这个简单的数字钟就能很好的体现出了硬件设计思想和软件设计思想之间的差别。

整个系统运用全局时钟,对于一些分频的处理采用使能信号控制。这样能避免出现时序的不满足。
整个系统分为五个模块进行实现:
  gen_en : 产生使能信号,使能1HZ的分频和数码管的扫描
  sec,min,hour模块:当然是实现时分秒的处理
  data_con:对数码管显示数据的预译码处理,并进行动态扫描

整个系统已经经过了初步的测试,基本的功能达到满足,但是没有设置时间的功能,还有就是小时的显示部分并没有做处理,仍然按照60进制进行显示.这部分等到有机会进行时间设置功能的补充后再进行相应的更改。

整个系统的顶层文件为:
   //////////////////////////////////////////////////////////////////////////////////
// Company: NEU
// Engineer: zxqwolf
//
// Create Date:    12:00:10 02/02/2013
// Design Name:    clock
// Module Name:    clock
// Project Name:   clock
// Target Devices:  EP2C5Q208C8
// Tool versions:     Quartus II 11.1
// Description:       top file
// Revision 0.01 - File Created
// Additional Comments: 实现了基本的数字钟的功能,但是小时部分的显示仍然按照分秒的显示的处理,
//                               采用了60进制,而没有采用24进制,主要是因为暂时无法对此部分进行调试,
//                               等需要补充时再进行更改
//
//////////////////////////////////////////////////////////////////////////////////
module clock(                                       //top  module
    input clk,
    input rst_n,
   
  output [7:0]smg_bit,                       //smg bit select
    output [7:0]clock_smg                    //smg data disp
);

///reg [7:0] clock_smg_r;
///wire clock_smg = clock_smg_r;

wire en,en_data_con;
wire cy_hour,cy_min;

wire [3:0] sec_H,sec_L,min_H,min_L,hour_H,hour_L;

gen_en U0(                                         //generate en signal
  .clk(clk),
  .rst_n(rst_n),
  .en_clk(en),
  .en_data_con(en_data_con)
);

hour  U1(                                            //disp hour
  .clk(clk),
  .rst_n(rst_n),

  .en(cy_hour),

  .cy(),
  .hour_H(hour_H),
  .hour_L(hour_L)
  );

min U2(                                             //disp minute
  .clk(clk),
  .rst_n(rst_n),

  .en(cy_min),

  .cy(cy_hour),
  .min_H(min_H),
  .min_L(min_L)
);

sec U3(                                           ////disp second
  .clk(clk),
  .rst_n(rst_n),

  .en(en),

  .cy(cy_min),
  .sec_H(sec_H),
  .sec_L(sec_L)
);

data_con U4(                                    ///smg control module
  .clk(clk),
  .rst_n(rst_n),
 
  .en_data_con(en_data_con),
 
  .sec_H(sec_H),
  .sec_L(sec_L),
  .min_H(min_H),
  .min_L(min_L),
  .hour_H(hour_H),
  .hour_L(hour_L),
 
  .smg_bit(smg_bit),
  .timedata(clock_smg)
);


endmodule
 
gen_en 模块实现如下:

 module gen_en(
  input clk,
  input rst_n,
 
  output en_clk,
  output en_data_con
);


reg [25:0] en_cnt;
reg [21:0] en_data_con_cnt;

reg en_r,en_data_con_r;
assign en_clk = en_r;
assign en_data_con = en_data_con_r;

always @(posedge clk or negedge rst_n)
 if(!rst_n)
  begin
   en_r <= 1'b0;
 en_cnt <= 26'd0;
 en_data_con_cnt <= 22'd0;
  end
 else
  begin
   en_cnt <= en_cnt + 1'b1;
 en_data_con_cnt <= en_data_con_cnt + 1'b1;
 if(en_cnt == 26'h2FAF080)
   begin
         en_cnt <= 26'd0;  
     en_r <= 1'b1; 
       //en_data_con_r <= 1'b0;  
  end     // 1HZ = 1s
  else
    en_r <= 1'b0;
  
  if(en_data_con_cnt == 22'h1E848)
     begin
        en_data_con_r <= 1'b1;
          en_data_con_cnt <= 22'd0;    
   end   
  else        
   en_data_con_r <= 1'b0;

end

endmodule
  

时分秒的模块实现代码类似,由于小时部分没有做更改,故小时部分也是一样的实现

 module sec(
  input clk,
  input rst_n,

  input en,

  output cy,
  output [3:0]sec_H,
  output [3:0]sec_L
);

//reg [3:0] sec_H_r,sec_L_r;
//assign sec_H_r = sec_H;
//assign sec_L_r  = sec_L;

wire cy_L;

counter10 U0(
  .clk(clk),
  .rst_n(rst_n),
 
  .en(en),                                  //////
 
  .cy(cy_L),
  .counter_out(sec_L)
  );

 
  counter6 U1(
  .clk(clk),
  .rst_n(rst_n),
 
  .en(cy_L),                                  //////
 
  .cy(cy),
  .counter_out(sec_H)
  );
endmodule

module min(
  input clk,
  input rst_n,

  input en,

  output cy,
  output [3:0]min_H,
  output [3:0]min_L
  );
 
  wire cy_L;
 
  counter10 U0(
  .clk(clk),
  .rst_n(rst_n),
 
  .en(en),                                  //////
 
  .cy(cy_L),
  .counter_out(min_L)
  );

 
  counter6 U1(
  .clk(clk),
  .rst_n(rst_n),
 
  .en(cy_L),                                  //////
 
  .cy(cy),
  .counter_out(min_H)
  );
 
  endmodule
  

module hour(
  input clk,
  input rst_n,

  input en,

  output cy,
  output [3:0]hour_H,
  output [3:0]hour_L
  );
 
  wire cy_L;
 
  counter10 U0(
  .clk(clk),
  .rst_n(rst_n),
 
  .en(en),                                  //////
 
  .cy(cy_L),
  .counter_out(hour_L)
  );

 
  counter6 U1(
  .clk(clk),
  .rst_n(rst_n),
 
  .en(cy_L),                                  //////
 
  .cy(cy),
  .counter_out(hour_H)
  );
 
  endmodule
  
 其中时分秒的实现是通过一个一个十进制的计数器和六进制的计数器进行实现的。通过产生进位脉冲向前进位实现进位。

module counter10(
  input clk,
  input rst_n,
 
  input en,
 
  output cy,
  output [3:0]counter_out
);

reg [3:0]counter_out_r;          //output data
assign counter_out = counter_out_r;

reg en_r;
reg cy_r;                         // carry chain
assign cy = cy_r;

//reg cnt_sta;
always @(posedge clk or negedge rst_n)
  if(!rst_n)
   begin
  cy_r <= 1'b0;
    counter_out_r <= 4'd0;
  //cnt_sta <= 1'b0;
 end
  else 
   begin
   en_r <= en;
   if(!en && en_r)                                                    //检测上升沿脉冲
    begin
    counter_out_r <= counter_out_r + 1'b1;
    if(counter_out_r == 4'b1001)
    begin
     cy_r <= 1'b0;
     counter_out_r <= 4'b0000;
    end
   else if(counter_out_r == 4'b1000)
         begin
//此处是为了产生上升沿进位脉冲,因为进位是同步的,
//所以要等到下一个时钟到来时才能有进位有效信号,故此处提前了一个周期产生进位信号
      cy_r <= 1'b1;
     end
   else
     begin
      cy_r <= 1'b0;
      //cnt_sta <= 1'b0;
     end
    end
 end
 
 
  endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module counter6(
  input clk,
  input rst_n,
 
  input en,
 
  output cy,
  output [3:0]counter_out
);

reg [3:0]counter_out_r;          //output data
assign counter_out = counter_out_r;

reg en_r;
reg cy_r;                         // carry chain
assign cy = cy_r;

//reg cnt_sta;
always @(posedge clk or negedge rst_n)
  if(!rst_n)
   begin
  cy_r <= 1'b0;
    counter_out_r <= 4'd0;
  //cnt_sta <= 1'b0;
 end
  else
   begin
   en_r <= en;
   if(!en && en_r)                                          //检测上升沿脉冲
    begin
    counter_out_r <= counter_out_r + 1'b1;
    if(counter_out_r == 4'b0101)
       begin
     counter_out_r <= 4'b0000;
     //cnt_sta <= 1'b0;
     cy_r <= 1'b0;
    end
   else if(counter_out_r == 4'b0100)
    begin
     cy_r <= 1'b1;  
//此处是为了产生上升沿进位脉冲,因为进位是同步的,
//所以要等到下一个时钟到来时才能有进位有效信号,故此处提前了一个周期产生进位信号
     //cnt_sta <= 1'b0;
    end
   else
    begin
     cy_r <= 1'b0;
     //cnt_sta <= 1'b0;
    end
   end
  end 
  endmodule

 

module data_con(
  input clk,
  input rst_n,
 
  input en_data_con,
 
  input [3:0]sec_H,
  input [3:0]sec_L,
  input [3:0]min_H,
  input [3:0]min_L,
  input [3:0]hour_H,
  input [3:0]hour_L,
 
  output [7:0]smg_bit,
  output [7:0]timedata
);

reg [7:0] timedata_r,smg_bit_r;
reg [7:0] disp_state;
reg [3:0] time_4bit;
assign timedata = timedata_r;
assign smg_bit  = smg_bit_r;

parameter disp0  = 8'b1111_1110,
                disp1  = 8'b1111_1101,
      disp2  = 8'b1111_1011,
      disp3  = 8'b1111_0111,
      disp4  = 8'b1110_1111,
      disp5  = 8'b1101_1111,
      disp6  = 8'b1011_1111,
      disp7  = 8'b0111_1111;
     
always @(posedge clk or negedge rst_n)
 if(!rst_n)
   begin
   disp_state <= 8'b0000_0000;
   smg_bit_r    <= 8'b1111_1111;
   time_4bit <= 4'b0000;
 end

else
 if(en_data_con)
   begin
      case(disp_state)
      disp0:begin time_4bit <= sec_L;     smg_bit_r <= disp0;  disp_state <= disp1;end
    disp1:begin time_4bit <= sec_H;     smg_bit_r <= disp1;  disp_state <= disp2;end
    disp2:begin time_4bit <= 4'b1010;  smg_bit_r <= disp2;  disp_state <= disp3;end
    disp3:begin time_4bit <= min_L;     smg_bit_r <= disp3;  disp_state <= disp4;end
    disp4:begin time_4bit <= min_H;     smg_bit_r <= disp4; disp_state <= disp5;end
    disp5:begin time_4bit <= 4'b1010;   smg_bit_r <= disp5; disp_state <= disp6;end
    disp6:begin time_4bit <= hour_L;     smg_bit_r <= disp6; disp_state <= disp7;end
    disp7:begin time_4bit <= hour_H;    smg_bit_r <= disp7; disp_state <= disp0;end
    default : begin time_4bit <= 4'b1111;smg_bit_r<= disp0; disp_state <= disp0;end
      endcase
 end
 

always @(time_4bit or  rst_n)                           //combinational logic
  if(!rst_n)
   begin
   timedata_r <= 8'hff;                                     //bu xian shi
 end
  else
   begin
   case(time_4bit)
     4'b0000 :  timedata_r <= 8'hC0;                   //0
   4'b0001 :  timedata_r  <= 8'hF9;                   //1
   4'b0010 :  timedata_r  <= 8'hA4;                   //2
   4'b0011 :  timedata_r   <= 8'hB0;                   //3
   4'b0100 :  timedata_r  <= 8'h99;                    //4
   4'b0101 :  timedata_r  <= 8'h92;                     //5
   4'b0110 :  timedata_r  <= 8'h82;                     //6
   4'b0111 :  timedata_r   <= 8'hF8;                    //7
   4'b1000 :  timedata_r  <= 8'h80;                    //8
   4'b1001 :  timedata_r <=  8'h90;                      //9
   4'b1010 :  timedata_r <=  8'hBF;                     //-
   default   : timedata_r  <=  8'hff;
  endcase
 end


endmodule

 

 

posted on 2013-03-03 17:06  展翅的小鸟  阅读(1672)  评论(0编辑  收藏  举报

导航