数字时钟——FPGA

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

 

 


设计要求

用FPGA实现一个数字时钟——用veirlog语言


一、如何分频(即生成想要频率的时钟信号)?

  • 源时钟信号 clk 的频率为:f=50MHz
  • 假设想要得到时钟信号 clk_1 频率为:f1
  • 用一个寄存器变量 count 记录 clk 的 x 个时钟上升沿
  • 此时,clk 进行了 x 个周期
  • 令 clk_1 反转(即clk_1<=~clk_1),相当于 clk_1 进行了二分之一个周期
  • 所以可以得出: x=f/(2*f1)

二、利用视觉暂留

来自百科:物体在快速运动时, 当人眼所看到的影像消失后,人眼仍能继续保留其影像0.1-0.4秒左右的图像,这种现象被称为视觉暂留现象。是人眼具有的一种性质。人眼观看物体时,成像于视网膜上,并由视神经输入人脑,感觉到物体的像。但当物体移去时,视神经对物体的印象不会立即消失,而要延续0.1 -0.4秒的时间,人眼的这种性质被称为"眼睛的视觉暂留"。

也就是说,只要使FPGA上的六个数码管轮流亮起(并且同一个数码管亮起的时间间隔小于视觉暂留时间),就可以实现“动态”。


三、数码管显示数字原理

 


其中,高位到低位依次是:DP_G F E _D C B A, 共阴极数码管——输入为高电平亮!

下图为,共阴极数码管的编码表

共阴极数码管的编码表

 


四、设计流程

  1. 所需端口以及变量定义
    input clk;   //系统时钟频率50MHz
    output [5:0]wei;    //片选数码管
    output [7:0]duan;   //段选发光二极管
    reg[5:0]wei;
    reg[7:0]duan;
    
    integer count;  //计数实现1Hz的时钟clk_1hz
    reg clk_1hz;    //计时时钟
    integer count2; //计数实现扫描时钟clk_scan->利用视觉暂留实现动态
    reg clk_scan;  //扫描时钟
    reg [2:0]select;   //用于扫描时选择显示位码
    
    reg[3:0]sec_ge;     //秒的个位BCD码 0~9
    reg[2:0]sec_shi;    //秒的十位BCD码 0~5
    reg[3:0]min_ge;     //分的个位BCD码 0~9
    reg[2:0]min_shi;    //分的十位BCD码 0~5
    //reg[1:0]hour_ge;    //时的个位 0~3
    reg[3:0] hour_ge;   //时的十位 0~9  (也表达0~3)
    reg[1:0]hour_shi;   //时的十位 0~2

     

  2. 产生频率为1的累计时钟信号
    //生成1Hz的时钟clk_1hz
    always@(posedge clk)
    begin
        if(count==25000000)
            begin
                count<=0;
                clk_1hz<=~clk_1hz;
            end
        else
            count<=count+1'b1;   
    end    

     

  3. 秒、分、时 各个位数的累加
    用Draw.io画的秒时分各位累加流程图
    //秒、分、时 各个位数的累加
    always @(posedge clk_1hz)//秒分时各位累加功能进程
    begin
        if(sec_ge==4'b1001)   //秒的个位等于9
        begin
                 sec_ge<=4'b0000;
                 if(sec_shi==3'b101)  //秒的十位等于5
                 begin
                         sec_shi<=3'b000;
                         if(min_ge==4'b1001)    //分的个位等于9
                         begin
                                min_ge<=4'b0000;
                                if(min_shi==3'b101)     //分的十位等于5
                                begin
                                    min_shi<=3'b000;
                                    if(hour_shi==2'b00)     //时的十位等于0
                                    begin
                                         if(hour_ge==4'b1001)       //时的个位等于9
                                            begin
                                                hour_ge<=0;
                                                hour_shi<=hour_shi+1'b1;
                                            end
                                         else 
                                             hour_ge<=hour_ge+1'b1;                                  
                                    end
                                    else
                                        if(hour_shi==2'b01)     //判断 时的十位等于1
                                        begin
                                            if(hour_ge==4'b1001)       //判断 时的十位等于9
                                            begin
                                                hour_ge<=0;
                                                hour_shi<=hour_shi+1'b1;
                                            end
                                        end
                                        else    //时的十位不等于0,也不等于1, 即等于2
                                            if(hour_ge==4'b0011)        //判断 时的个位等于3
                                            begin
                                                hour_ge<=0;
                                                hour_shi<=0;
                                            end
                                            else
                                                hour_ge<=hour_ge+1'b1;
                                end
                                else
                                    min_shi<=min_shi+1'b1;
                         end
                         else
                            min_ge<=min_ge+1'b1;
                 end
                 else
                     sec_shi<=sec_shi+1'b1;
        end
          
        else
         sec_ge<=sec_ge+1'b1;
    end

     

  4. 产生数码管扫描时钟信号
    //产生数码管扫描时钟
    always @(posedge clk)
    begin
       if(count2==10000)
       //if(count2==25000000) //测试视觉暂留
         begin
         count2<=0;
         clk_scan<=~clk_scan;
         end
       else
         count2<=count2+1;
    end

     

  5. 扫描时实现片选,以便利用视觉暂留
    //扫描时实现片选   视觉暂留
    always @(posedge clk_scan)
     begin 
         if(select==3'b110)
         select<=3'b000;
         else
         select<=select+1'b1;
         
     end

     

  6. 显示数字(注意分隔点DP的点亮与否)
    //显示数字
    always @(sec_ge or sec_shi or min_ge or min_shi or hour_ge or hour_shi or select)//敏感信号列表
     begin 
       if(select==3'b001)
       begin
       wei<=6'b111110;//秒个位数显示      不显示点
       case(sec_ge)
           4'b0000:begin duan<=8'b0_011_1111;end     // 显示0
           4'b0001:begin duan<=8'b0_000_0110;end     // 显示1
           4'b0010:begin duan<=8'b0_101_1011;end     // 显示2
           4'b0011:begin duan<=8'b0_100_1111;end     // 显示3
           4'b0100:begin duan<=8'b0_110_0110;end     // 显示4
           4'b0101:begin duan<=8'b0_110_1101;end     // 显示5
           4'b0110:begin duan<=8'b0_111_1101;end     // 显示6
           4'b0111:begin duan<=8'b0_000_0111;end     // 显示7
           4'b1000:begin duan<=8'b0_111_1111;end     // 显示8
           4'b1001:begin duan<=8'b0_110_1111;end     // 显示9
           default duan<=8'bx;
       endcase
       end
       
       else if(select==3'b010)
       begin
       wei<=6'b111101;//秒十位数显示      不显示点
       case(sec_shi)
           3'b000:duan<=8'b0_011_1111;     // 显示0
           3'b001:duan<=8'b0_000_0110;     // 显示1
           3'b010:duan<=8'b0_101_1011;     // 显示2
           3'b011:duan<=8'b0_100_1111;     // 显示3
           3'b100:duan<=8'b0_110_0110;     // 显示4
           3'b101:duan<=8'b0_110_1101;     // 显示5
           //3'b110:duan<=8'b1111_1101;     // 显示6
           default duan<=8'bx;
       endcase
       end
       
       else if(select==3'b011)
       begin
       wei<=6'b111011;//分钟个位数显示数字   显示点
       case(min_ge)
          4'b0000:begin duan<=8'b1_011_1111;end     // 显示0
          4'b0001:begin duan<=8'b1_000_0110;end     // 显示1
          4'b0010:begin duan<=8'b1_101_1011;end     // 显示2
          4'b0011:begin duan<=8'b1_100_1111;end     // 显示3
          4'b0100:begin duan<=8'b1_110_0110;end     // 显示4
          4'b0101:begin duan<=8'b1_110_1101;end     // 显示5
          4'b0110:begin duan<=8'b1_111_1101;end     // 显示6
          4'b0111:begin duan<=8'b1_000_0111;end     // 显示7
          4'b1000:begin duan<=8'b1_111_1111;end     // 显示8
          4'b1001:begin duan<=8'b1_110_1111;end     // 显示9
          default duan<=8'bx;
       endcase
       end
       
       else if(select==3'b100)
       begin
       wei<=6'b110111;//分钟十位数显示     不显示点
       case(min_shi)
              3'b000:duan<=8'b0_011_1111;     // 显示0
              3'b001:duan<=8'b0_000_0110;     // 显示1
              3'b010:duan<=8'b0_101_1011;     // 显示2
              3'b011:duan<=8'b0_100_1111;     // 显示3
              3'b100:duan<=8'b0_110_0110;     // 显示4
              3'b101:duan<=8'b0_110_1101;     // 显示5
              //3'b110:duan<=8'b1111_1101;     // 显示6
              default duan<=8'bx;
       endcase
       end
       
       else if(select==3'b101)
       begin
       wei<=6'b101111;//时钟个位数显示     显示点
       case(hour_ge)
          4'b0000:begin duan<=8'b1_011_1111;end     // 显示0
          4'b0001:begin duan<=8'b1_000_0110;end     // 显示1
          4'b0010:begin duan<=8'b1_101_1011;end     // 显示2
          4'b0011:begin duan<=8'b1_100_1111;end     // 显示3
          4'b0100:begin duan<=8'b1_110_0110;end     // 显示4
          4'b0101:begin duan<=8'b1_110_1101;end     // 显示5
          4'b0110:begin duan<=8'b1_111_1101;end     // 显示6
          4'b0111:begin duan<=8'b1_000_0111;end     // 显示7
          4'b1000:begin duan<=8'b1_111_1111;end     // 显示8
          4'b1001:begin duan<=8'b1_110_1111;end     // 显示9
          default duan<=8'bx;
       endcase
       end
       
       else 
       begin
       wei<=6'b011111;//时钟十位数显示     不显示点
       case(hour_shi)
           3'b000:duan<=8'b0_011_1111;     // 显示0
           3'b001:duan<=8'b0_000_0110;     // 显示1
           3'b010:duan<=8'b0_101_1011;     // 显示2
           default duan<=8'bx;
       endcase
       end
    end

     


五、板上实现

 

 


补充:初始化数据——测试功能是否完善

//初始化:从 23 :59 :54 开始计时,测试功能
initial
begin
    hour_shi<=2;
    hour_ge<=3;
    min_shi<=5;
    min_ge<=9;
    sec_shi<=5;
    sec_ge<=4;
end

 

 

 

总结

 

  • 4
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当您提到"FPGA数字时钟的全部代码"时,我假设您希望获取一个完整的FPGA数字时钟的设计,包括硬件描述语言(HDL)代码和约束文件。 下面是一个简单的FPGA数字时钟的VHDL代码示例: ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity DigitalClock is Port ( clk : in STD_LOGIC; reset : in STD_LOGIC; seconds : out STD_LOGIC_VECTOR (5 downto 0); minutes : out STD_LOGIC_VECTOR (5 downto 0); hours : out STD_LOGIC_VECTOR (4 downto 0)); end DigitalClock; architecture Behavioral of DigitalClock is signal sec_count : integer range 0 to 59 := 0; signal min_count : integer range 0 to 59 := 0; signal hour_count : integer range 0 to 23 := 0; begin process(clk, reset) begin if reset = '1' then sec_count <= 0; min_count <= 0; hour_count <= 0; elsif rising_edge(clk) then if sec_count = 59 then sec_count <= 0; if min_count = 59 then min_count <= 0; if hour_count = 23 then hour_count <= 0; else hour_count <= hour_count + 1; end if; else min_count <= min_count + 1; end if; else sec_count <= sec_count + 1; end if; end if; end process; seconds <= std_logic_vector(to_unsigned(sec_count, 6)); minutes <= std_logic_vector(to_unsigned(min_count, 6)); hours <= std_logic_vector(to_unsigned(hour_count, 5)); end Behavioral; ``` 请注意,这只是一个简单的示例,仅提供了最基本的时钟功能。根据您的需求,您可能需要添加其他功能或修改现有代码。 另外,您还需要在FPGA开发工具中提供约束文件,以将输入输出引脚映射到FPGA器件上的实际引脚。以下是一个简单的约束文件示例(假设使用Xilinx Vivado工具): ``` set_property PACKAGE_PIN pin_number [get_ports clk] set_property IOSTANDARD standard [get_ports clk] set_property PACKAGE_PIN pin_number [get_ports reset] set_property IOSTANDARD standard [get_ports reset] set_property PACKAGE_PIN pin_number [get_ports seconds] set_property IOSTANDARD standard [get_ports seconds] set_property PACKAGE_PIN pin_number [get_ports minutes] set_property IOSTANDARD standard [get_ports minutes] set_property PACKAGE_PIN pin_number [get_ports hours] set_property IOSTANDARD standard [get_ports hours] ``` 请将上述代码中的`pin_number`替换为实际的引脚号,并根据需要为时钟、复位和输出信号选择正确的`IOSTANDARD`。 请注意,这只是一个简单的示例,实际设计可能因所使用的FPGA器件和开发工具而有所不同。在进行更复杂的设计时,还可能需要考虑时钟域、时序约束、时钟分频等方面的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值