• 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

    这个世界不会怜悯那些被屠宰者,而会尊敬那些一直在战斗着的人们
  • 相关阅读:
    手机端阻止页面滑动-模板
    window.location各个属性-笔记
    面向对象的编程思想
    异步执行原理
    移动端rem布局实现(vw)
    用css3实现摩天轮旋转的动画效果
    js如何从一个数组中随机取出n个不同且不重复的值
    js数组中如何去除重复值?
    各大主流流浪器的内核是什么?
    javascript数组常用方法
  • 原文地址:https://www.cnblogs.com/zxqwolf/p/2941685.html
Copyright © 2020-2023  润新知