Verilog学习笔记——电子钟

///Verilog学习笔记——电子钟

Verilog学习笔记——电子钟

好久不见,我又回来开新坑了。

这学期开始接触数电了,感觉比模电好玩多了,而且因为数电极强的逻辑性以及又fpga这种可编程器件的存在,所以我觉得数电比模电更容易上手,而事实也是现在数电的发展远比模电强大。

闲话不多说,接下来我来介绍一下我设计的电子钟模块,它通过输入一个1Hz的时钟信号来达到计秒的功能,并且具有校准时、分、秒以及清零的功能。具体的实现方法是在内部设置了两套存储器,一套用于存储时钟信号计算的秒数,另一套用于存储用户自定义的校准时间,然后将两套存储相加即可输出最后的时分秒信号。

原理非常简单,算是我学习Verillog以来做的第一个模块了吧,接下来贴出代码:(添加了代码注释)

module clock(
    input clk,h_ad,m_ad,s_ad,res,    //输入clk为1Hz
    output reg[5:0]h,
    output reg[5:0]m,
    output reg[5:0]s
    );
    reg[5:0]h1;
    reg[5:0]m1;
    reg[5:0]s1;
    reg[5:0]h2;
    reg[5:0]m2;
    reg[5:0]s2;
    reg[6:0]m_tmp;  //寄存器定义
    initial begin //赋初值
        h=0;
        m=0;
        s=0;
        h1=0;
        h2=0;
        m1=0;
        m2=0;
        s1=0;
        s2=0;
    end
    always @(posedge clk,negedge res)begin //按秒增加时间
        s1=s1+1;
        if(s1==60)begin   //满60秒进一分
            s1=0;
            m1=m1+1;
        end
        if(m1==60)begin  //满60分进一小时
            m1=0;
            h1=h1+1;
        end
        if(h1==24)      //满24小时重置
            h1=0;
        if(!res)begin   //异步复位
            s1=0;
            m1=0;
            h1=0;
        end
    end
    always @(posedge h_ad,negedge res)begin //校时 时增加
        h2=h2+1;
        if(h2==24)  //满24小时重置
            h2=0;
        if(!res)    //异步复位
            h2=0;
    end
    always @(posedge m_ad,negedge res)begin //校时 分增加
        m2=m2+1;
        if(m2==60)  //满60分重置
            m2=0;
        if(!res)    //异步复位
            m2=0;
    end
    always @(posedge s_ad,negedge res)begin //校时 秒位置0
        s2=s1;
        if(!res)  //异步复位
            s2=0;
    end
    always @(h1,h2,m1,m2,s1,s2)begin
        h=h1+h2;                  //最终小时数为计时小时+矫时小时
        m_tmp=m1+m2;              //最终分钟数为计时分钟+矫时分钟
        if(s1>=s2)                //处理秒数置0矫时
            s=s1-s2;
        else begin
            s=s1+60-s2;
            if(m_tmp==0)begin     //矫时秒数超前分钟数减1
                h=h-1;
                m_tmp=59;
            end
            else
                m_tmp=m_tmp-1;
        end
        if(m_tmp>=60)begin        //分钟数满60进一小时
            m_tmp=m_tmp-60;
            h=h+1;
        end
        m=m_tmp[5:0];
        if(h>=24)                 //小时数限制在24小时内
            h=h-24;
    end
endmodule

同时与这个模块配套的还有一个动态显示模块,这个模块的作用是利用动态显示的方法在数码管上“同时”显示多位数字。这与你现在眼前的显示器类似:通过高速刷新,使各个数字轮流显示,每个仅显示几毫秒。由于人具有视觉暂留,所以在人眼中数码管上的数字就是同时点亮的。

以下是6位动态显示模块的代码:(由于使用的数码管接口自带译码电路,所以这里的模块直接输出了数字,对于其他某些情况还需要自己编写译码模块)

module show_dig_6(
    input [3:0]dig1,[3:0]dig2,[3:0]dig3,[3:0]dig4,[3:0]dig5,[3:0]dig6,   //待显示的6位数字
    input clk,              //时钟通常在1000Hz左右
    output reg[3:0]dig,    //输出数字
    output reg[6:1]ch      //输出数码管有效信号
    );
    reg [2:0]counter;
    initial begin
        dig=0;
        ch=6'b111111;
        counter=0;
    end
    always @(posedge clk) begin
        counter=counter+1;     //每周期计数器加1
        if(counter==6)         //计满6清零
            counter=0;
        case(counter)
            0:begin                  //对于每个状态
                dig=dig1;            //输出该位对应的数字
                ch=6'b011111;        //将对应位值为有效,其他无效
            end                      //下同
            1:begin
                dig=dig2;
                ch=6'b101111;
            end
            2:begin
                 dig=dig3;
                 ch=6'b110111;
            end
            3:begin
                  dig=dig4;
                  ch=6'b111011;
            end
            4:begin
                   dig=dig5;
                   ch=6'b111101;
            end
            5:begin
                    dig=dig6;
                    ch=6'b111110;
            end
            default:begin
                dig=0;
                ch=6'b111111;
            end
        endcase
    end
endmodule

然后将上面编写的两个模块整合进一个主模块中,将程序烧入FPGA里就完成了:

module Sinon(
    input clk,clock_clk,h_ad,m_ad,s_ad,res,
    output[3:0]dig,
    output[1:6]ch
    );
    wire [3:0]dig_out;
    wire [1:6]ch_out;
    wire [5:0]h_out;
    wire [5:0]m_out;
    wire [5:0]s_out;
    reg [5:0]h;
    reg [5:0]m;
    reg [5:0]s;
    reg [3:0]dig1;reg [3:0]dig2;reg [3:0]dig3;reg [3:0]dig4;reg [3:0]dig5;reg[3:0]dig6;
    always @(clock_clk,h_ad,m_ad,s_ad)begin
        h=h_out;
        m=m_out;
        s=s_out;
        dig1=h/10;   //获取小时数十位,下同
        dig2=h%10;   //获取小时数个位,下同
        dig3=m/10;
        dig4=m%10;
        dig5=s/10;
        dig6=s%10;
    end
    assign dig=dig_out;
    assign ch=ch_out;
    clock clock_0(clock_clk,h_ad,m_ad,s_ad,res,h_out,m_out,s_out);               //数字钟模块
    show_dig_6 show_dig(dig1,dig2,dig3,dig4,dig5,dig6,clk,dig_out,ch_out);       //动态显示模块
endmodule
发布者 | 2021-05-26T00:34:41+08:00 9月 24th, 2019|verilog, 学习笔记|3条评论

关于作者

blank
坚强大概——并不是指的的结果,而是迈向某个目标的过程吧。

3条评论

  1. blank
    江大佬的垃圾室友 2020年6月11日 在 下午2:19 -回复

    江大佬牛逼

  2. blank
    天生打雷 2019年12月4日 在 下午4:17 -回复

    波形发生器整活

发表评论

召唤伊斯特瓦尔