用Verilog实现时钟芯片


时钟芯片基础——60进制计数器

设计目的

nexys 4板上的7段码LED显示时钟信息,其中包括时钟的小时,分钟,秒钟部分,且能够实现时钟的停止计时信号,手动调整小时,分钟模块功能。

设计思路

值得一提的是这里的信号我都用上升沿检测来实现,这样每个模块都可以直接接受时钟信号,而进位信号或者其他的控制信号都可以通过上升沿检测模块来提供一个上升沿信号来实现

  1. 首先利用分频器产生固定频率的信号来实现每秒钟计数频率和7段码数码管的工作的要求频率。计数功能由单独的秒级,分钟级和小时级三个分别的计数模块负责,秒级和分钟级的计数模块输出进位信号让下一部分自增。
  2. 计数模块存在输入的RST信号,当接受到RST信号时,计数模块内部寄存器全部清0,所以全部重新计数。
  3. 秒级计数模块存在输入的停止信号,当接受到停止信号时秒级计数模块停止计数,内部寄存器不再发生改变,所以不再产生进位信号让分钟级计数单位发生改变。
  4. 分钟级和小时级计数模块存在状态改变信号,当状态信号为1时,分钟级和小时级计数模块不再接受来自上一级的时钟进位信号,转而接受手动调整开关产生的自增信号,实现手动调整小时和分钟的数值;当状态信号为0时,分钟级和小时级计数模块正常接受来自上一级的时钟进位信号,同时忽略手动调整开关产生的自增信号。
  5. 时钟模块之间的进位信号和手动调整状态下的自增信号都通过上升沿检测实现只输入给相应的模块一个时钟周期的高电平,所以所有模块的时钟信号都可以接受系统时钟。

设计原理图

用Verilog实现时钟芯片

代码实现

在之前的博客中已经写了60进制计数器的实现,这个时钟芯片不外乎就类似于两个60进制的计数器和一个24进制的计数器,同时两两之间有进位信号。
同时还增加了停止,手动调整这两个功能。其中停止功能只需要停止秒级信号的计数,而手动调整这个功能只需要为分钟模块和小时模块输入增加或减少信号,而控制模块只需要增加它的状态量,让它能实现6个位依次点亮,所以需要6个状态,其他的模块都不需要改变

秒级计数模块

module Counter60(
input clk,
input rst,
//input up,//技术模式转换
input palse,//停止计数信号
output reg [5:0]cnt,
output reg cout//传入下一个时钟模块信号
 );
 
 //variation declaration
// reg state,state_next;//1 represents up
// reg c,c_next;//show wherther up?
 
 //state logic
 [email protected](posedge clk,posedge rst)
 if(rst)begin
 cnt<=0;
 cout<=0;
 end
 else
 if(palse)//高电平停止计数
 cnt<=cnt;//暂停
 else//开始计数
// if(up)//高电平上升计数
 if(cnt==59)begin
 cnt<=0;
 cout<=1;//在59的时候进位输出一个计数信号
 end
 else begin
 cnt<=cnt+1;
 cout<=0;
 end

分钟级计数模块

module Counter60_minute(
    input clk,
    input rst,
    input change,//改变模式信号,SW3
    input add,
//    input subject,//上升和下降信号
    output reg cout,
    output reg [5:0]cnt
    );
    
    //variation declaration
    reg state,state_next;
    reg cout_next;
    reg [5:0]cnt_next;
    
    //output logic
    [email protected](posedge clk,posedge rst)
   if(rst==1)begin
    cnt<=5'b00000;
    cout<=0;
    state<=0;//0模式为正常计数模式
    end
    else begin
    cnt<=cnt_next;
    cout<=cout_next;
    state<=state_next;
    end
    
    //next state logic 
    [email protected]*
    begin
    state_next<=state;
    cout_next<=cout;
    cnt_next<=cnt;
    case(state)
    0:begin//正常计数信号
    if(change==1)
    state_next<=1;//进入信号改变阶段
    else 
    state_next<=0;
    if(cnt==59) begin
    cnt_next<=0;
    cout_next<=1;//产生上升沿
    state_next<=0;
    end
    else begin//正常计数
    cnt_next<=cnt+1;
    state_next<=0;
    cout_next<=0;//回归下降沿
    end
    end
    1:begin //修改计数器示数状态
    if(change==0)
    state_next<=0;//进入进入正常计数阶段
    else
    state_next<=1;
    if(add)//出现自增信号,示数加1
    if(cnt==60)
    cnt_next<=0;
    else
    cnt_next<=cnt+1;//自增1
    else 
    cnt_next<=cnt;//没有自增信号
    end
    default: begin
    state_next<=0;//进入到正常计数状态
    cout_next<=0;
    cnt_next<=0;
    end//在default里面赋初值?
    endcase
    end
    
endmodule

小时级计数模块

module Counter24(
    input clk,
    input rst,
//    output reg cout,
    output reg [5:0]cnt
    );
    
    [email protected](posedge clk,posedge rst)
    if(rst)
    cnt<=0;
    else
    if(cnt==24)//等待第24个信号
    cnt<=0;
    else
    cnt<=cnt+1;
    
endmodule

控制模块

module Controller(
    input clk,
    input rst,
    input [3:0]H1,
    input [3:0]L1,
    input [3:0]H2,
    input [3:0]L2,
    input [3:0]L3,
    input [3:0]H3,//增加输入信号
    output reg [3:0]Q,
    output reg [7:0]AN
    );
    //variation declaration
    reg [2:0]state;
    reg [2:0]state_next;//一共6个状态位
    reg [3:0]Q_next;
    reg [7:0]AN_next;
    
    //FSMD state
    [email protected](posedge clk,posedge rst)
    if(rst==1) begin
    state<=0;
    Q<=4'H0;
    AN<=8'H00;//全灭清零测试
    end
    else begin
    state<=state_next;
    AN<=AN_next;
    Q<=Q_next;
    end
    
    //next state logic & output logic
    [email protected]*
    begin
    state_next<=state;
    AN_next<=AN;
    Q_next<=Q;
    case(state)
    0: begin
    Q_next<=L1;//output equals low 
    AN_next<=8'b11111110;//turn on the 8th led//高电平选中数码管位数
    state_next<=1;//next stage is high
    end
    1: begin
    Q_next<=H1;//output equals HIGH 
    AN_next<=8'b11111101;//turn on the 7th led
    state_next<=2;//next stage is LOW
    end
    2:begin
     Q_next<=L2;//output equals low 
     AN_next<=8'b11110111;//turn on the 8th led
     state_next<=3;//next stage is high
     end
      3:begin
         Q_next<=H2;//output equals low 
         AN_next<=8'b11101111;//turn on the 8th led
         state_next<=4;//next stage is high
         end
          4:begin
             Q_next<=L3;//output equals low 
             AN_next<=8'b10111111;//turn on the 8th led
             state_next<=5;//next stage is high
             end
       5:begin
                 Q_next<=H3;//output equals low 
                 AN_next<=8'b01111111;//turn on the 8th led
                 state_next<=0;//next stage is high
                 end
       default:begin
                                  Q_next<=H3;//output equals low 
                                  AN_next<=8'b01111111;//turn on the 8th led
                                  state_next<=0;//next stage is high
                                  end
       
     endcase
     end
     
endmodule

实验结果

用Verilog实现时钟芯片