功能:
![2](https://gitee.com/lrk612/md_picture/raw/master/img/20210808172023.png)
设计思路:
首先对100M频率分频至1hz,然后对1hz信号的上升沿数量从0开始计数,保存在count中,那么count的值就是当前的总时间(单位为秒)。通过数学计算算出count对应的时分秒各自十位和个位的值,这是程序的第一部分。
然后是显示时间,以1khz频率对六个数码管轮流显示,显示值为该位上当前时刻对应的数值(时分秒的十位、个位),具体输出给显示管的是七段译码器的输出值。
其次是设计校时功能,h为小时校时输入,当h有效时,由1hz信号上升沿为触发,对count加3600(1h),同理,min为分钟校时输入,当min有效时,由1hz信号上升沿为触发,对count加60(1min)。
Verilog代码:
`timescale 1ns / 1ps
module Statu(y, en, m, clk_100M);
input m, en, clk_100M;
output[2:0] y;
reg[2:0] y;
reg[15:0] count1;
reg[8:0] count2;
reg clk_1khz, clk_1hz;
//变量说明:
//y为状态值,en为高有效使能,m为输入,clk_100M为100M的时钟信号
//count1和count2是分频器计的数变量,clk_1khz和clk_1hz是分频器的输出
//中间变量必须初始化
initial
begin
y = 3'b111;
clk_1khz = 0;
clk_1hz = 0;
count1 = 0;
count2 = 0;
end
//100M 100000分频得到1khz
always@(posedge clk_100M)
begin
if(count1 == 16'd49999)
begin
clk_1khz <= ~clk_1khz;
count1 <= 0;
end
else count1 <= count1 + 1;
end
//1khz 1000分频得到1hz
always@(posedge clk_1khz)
begin
if(count2 == 9'd499)
begin
clk_1hz <= ~clk_1hz;
count2 <= 0;
end
else count2 <= count2 + 1;
end
//状态机
always@(posedge clk_1hz)
begin
if(en == 1)
case(y)
3'b111: y <= 3'b000;
3'b000: y <= 3'b110;
3'b110: y <= m==1? 3'b100 : 3'b010;
3'b100: y <= m==1? 3'b101 : 3'b110;
3'b101: y <= m==1? 3'b001 : 3'b100;
3'b001: y <= m==1? 3'b011 : 3'b101;
3'b011: y <= m==1? 3'b010 : 3'b001;
3'b010: y <= m==1? 3'b110 : 3'b011;
endcase
else y <= 0;
end
endmodule
测试代码:
`timescale 1ns / 1ps
module test;
// Inputs
reg en;
reg m;
reg clk_100M;
reg count1, count2, clk_1khz, clk_1hz;
// Outputs
wire [2:0] y;
Statu uut (
.y(y),
.en(en),
.m(m),
.clk_100M(clk_100M)
);
//初始化
initial
begin
en = 1;
m = 0;
clk_100M = 0;
count1 = 0;
count2 = 0;
clk_1khz = 0;
clk_1hz = 0;
end
//100M时钟信号
always #50 clk_100M = ~clk_100M;
always #850 m = 1;
endmodule