基于BASYS3开发板Verilog的计时器实验

基于BASYS3开发板Verilog的计时器实验

因为Basys3开发板只有4位数码管,而且中间的那个冒号无法显示。所以我们做4位的时间显示,min:sec或者hour:min
然后我们如何去实现这个呢?首先需要利用系统时钟来计时,每秒或者每分钟变换一次,需要进位时进位,以及将数字显示出来。

1. 分频模块

因为时钟是动态的所以需要动态刷新,而人眼在每秒26帧以上时,会因为视觉暂留效应认为是连续变换的。也就是一个数码管至少一秒应该刷新26次以上,4位数码管至少应该是102Hz以上的刷新频率。
而BASYS3开发板的系统时钟的频率为50MHz或者100MHz。所以应该高频率的系统时钟分为低频的刷新时钟。而分频方式有2分频还有整数分频等方式。
这里使用整数分频,即系统时钟变换N次时,让输出脉冲变化一次。
注意:因为Verilog语言中 if 必须和 else 配对,不能只有if,不然会报错。

module clkdiv(
    input clk,
    input pau,
    input res,
    output reg clk100
    );
    parameter update_interval = 50000000 / 100 - 1;     
    integer selcnt;
    reg state; 
   always @(posedge clk,posedge pau,posedge res)  //100Hz
       begin
       if(res)
       begin
         state<=0;
         selcnt<=0;
         clk100<=0;
       end
       else if(pau)
       state=~state;
       else begin
            if(state)
            begin    
                if (selcnt == update_interval)  
                begin  
                selcnt <= 0;  
                clk100 <=~clk100;  
                end
                else
                selcnt<=selcnt+1;
            end
            else
            selcnt<=selcnt+0;
            end         
   end
    
endmodule

输入为系统的时钟,res重置按钮/开关,pau暂停按钮/开关。这里update_interval代表的是分频值的大小,要分成100Hz。系统时钟每有update_interval个上升沿时输出脉冲发生一次变化,即完成分频。res表示reset,时间置0。而pau表示pause,暂停,按下第一次时,会认为是暂停,selcnt一直加0,从而使时间暂停。按下第二次之后,state取反,继续计数。

2.计数模块

输入为分频模块的输出的分频后的时钟脉冲,重置,输出为时间。代码为

module count(
    input clk100,
    input res,
    output [15:0]tim
    );
    integer q;
    reg[3:0]sec_0;
    reg[3:0]sec_1;
    reg[3:0]min_0;
    reg[3:0]min_1;
    always@(posedge clk100 or posedge res)
    begin
      if(res)begin
      q<=0;
      sec_1=4'b0000;
      sec_0=4'b0000;
      min_0=4'b0000;
      min_1=4'b0000;
      end
      else begin
            if(q==100)begin
                q<=0;
                if(sec_0==4'b1001) begin 
                    sec_0<=4'b0000;
                    if(sec_1==4'b0101)begin
                        sec_1<=4'b0000;
                        if(min_0==4'b1001)begin 
                            min_0<=4'b0000;
                            if(min_1==4'b0101)
                               min_1<=4'b0000;
                            else
                               min_1<=min_1+1;                    
                        end
                        else
                            min_0<=min_0+1;        
                    end
                    else
                        sec_1<=sec_1+1;                             
                end
                else
                sec_0<=sec_0+1;                    
            end
            else
            q<=q+1; 
      end             
   end
   assign tim={min_1,min_0,sec_1,sec_0};
endmodule

为什么这里没有把pau作为输入呢?因为时间的值是随着输入时钟变化的,而pause之后,分频模块里的时钟已经不再增加了,所以计数模块的值也不会发生变化了。

3.显示模块

普通的7段数码显示

module display(
    inout clk,
    input [15:0]tim,
    output reg[3:0] an,
    output reg[6:0] a_to_g
    );
    reg[1:0] sign;
    reg[3:0] digit;
    parameter update_interval = 50000000 / 160 - 1;     
    integer selcnt; 
   always @(posedge clk)  //分频160Hz
       begin  
        selcnt <= selcnt + 1;  
              
        if (selcnt == update_interval)  
        begin  
            selcnt <= 0;  
            sign <= sign+ 1;  
        end  
   end
    always @(*) //选择位
    case(sign)
       0:begin an=4'b1110;digit=tim[3:0];end
       1:begin an=4'b1101;digit=tim[7:4];end
       2:begin an=4'b1011;digit=tim[11:8];end
       3:begin an=4'b0111;digit=tim[15:12];end
    endcase
    always @(*)//显示段数
    case(digit)
       0:a_to_g=7'b0000001;
       1:a_to_g=7'b1001111;
       2:a_to_g=7'b0010010;
       3:a_to_g=7'b0000110;
       4:a_to_g=7'b1001100;
       5:a_to_g=7'b0100100;
       6:a_to_g=7'b0100000;
       7:a_to_g=7'b0001111;
       8:a_to_g=7'b0000000;
       9:a_to_g=7'b0000100;
      'hA:a_to_g=7'b0001000;
      'hB:a_to_g=7'b1100000;
      'hC:a_to_g=7'b0110001;
      'hD:a_to_g=7'b1000010;
      'hE:a_to_g=7'b0110000;
      'hF:a_to_g=7'b0111000;
   default:a_to_g=7'b0000001;
   endcase
    
endmodule

4.模块组合

module timer(
    input clk,
    input [1:0] btn,
    output [3:0] an,
    output [6:0] a_to_g,
    output dp
    );
    wire clk100;
    wire [15:0]tim; 
    assign dp=1'b1;
    clkdiv ck(.clk(clk),
              .pau(btn[0]),
              .res(btn[1]),
              .clk100(clk100));
    count ct(.clk100(clk100),
             .res(btn[1]),
             .tim(tim));
    display dis(.clk(clk),
                .tim(tim),
                .an(an),
                .a_to_g(a_to_g));
endmodule

如下,限制文件可能会报“ambiguous clock”这个问题,这个要注释一句就好了,百度上好像有。这里不粘出来了。

你可能感兴趣的:(Verilog,数字逻辑)