Quartus编程实现时钟,具有基本的时间显示功能(00:00:00~23:59:59),以及其他附加功能:调整时间,设置闹铃,或者其它与时钟相关的功能。Modelsim实现仿真。
设计代码:
module clock(
clk, //时钟信号
rst_n, //复位信号
en, //控制时间的暂停
dout, //定时闹钟的输出
sel1, //更改定时闹钟的分的个位
sel2, //更改定时闹钟的分的十位
sel3, //更改定时闹钟的时的个位
sel4, //更改定时闹钟的时的十位
led_SG, //秒的个位
led_SS, //秒的十位
led_CG, //分的个位
led_CS, //分的十位
led_HG, //时的个位
led_HS //时的十位
);
input clk;
input rst_n;
input en;
input sel1;
input sel2;
input sel3;
input sel4;
output dout;
//秒
output led_SG;
output led_SS;
//分
output led_CG;
output led_CS;
//时
output led_HG;
output led_HS;
parameter CNT=50; //计数一秒需要的次数
parameter IDLE=3'b000;
parameter S1=3'b001;
parameter S2=3'b010;
parameter S3=3'b011;
parameter S4=3'b100; //S4为输出态
reg [8-1:0] led_SG ;
reg [8-1:0] led_SS ;
reg [8-1:0] led_CG ;
reg [8-1:0] led_CS ;
reg [8-1:0] led_HG ;
reg [8-1:0] led_HS ;
/*计数1秒的相关计数变量*/
reg [26-1:0] cnt0 ;
wire add_cnt0 ;
wire end_cnt0 ;
/*秒计数的相关变量,cnt1为秒的个位,cnt2为秒的十位*/
reg [4-1:0] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ;
reg [4-1:0] cnt2 ;
wire add_cnt2 ;
wire end_cnt2 ;
/*分计数的相关变量,cnt3为分的个位,cnt4为分的十位*/
reg [4-1:0] cnt3 ;
wire add_cnt3 ;
wire end_cnt3 ;
reg [4-1:0] cnt4 ;
wire add_cnt4 ;
wire end_cnt4 ;
/*时计数的相关变量,cnt5为时的个位,cnt6为时的十位*/
reg [4-1:0] cnt5 ;
wire add_cnt5 ;
wire end_cnt5 ;
reg [4-1:0] cnt6 ;
wire add_cnt6 ;
wire end_cnt6 ;
/*x用来确定时的个位cnt5计数的次数为10次还是4次,
当时的十位cnt6为0和1时,时的个位计数10次,
当时的十位cnt6为2时,时的个位计数4次*/
reg [3:0] x ;
wire [3:0] sel1;
wire [3:0] sel2;
wire [3:0] sel3;
wire [3:0] sel4;
wire [3:0] key;
reg [3:0] setup;
reg dout;
reg [2:0] state_c; //状态机的现态
reg [2:0] state_n; //状态机的次态
wire [2:0] idle2s1_start; //状态机初态转S1态的条件
wire [2:0] s12s2_start; //状态机S1态转S2态的条件
wire [2:0] s22s3_start; //状态机S2态转S3态的条件
wire [2:0] s32s4_start; //状态机S3态转S4态的条件
wire [2:0] s42idle; //状态机S4态转初态的条件
/**********************************************************************************************
**********************************************时钟*********************************************
**********************************************************************************************/
/*********************************
*************秒计数器**************
*********************************/
//计数1秒
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt0 <= 0;
end
else if(add_cnt0) begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 =1&&en==1; //加一条件,en控制其的运转与暂停,en为高电平时开始运转
assign end_cnt0 = add_cnt0 && cnt0== CNT-1; //结束条件
//秒的个位
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt1 <= 0;
end
else if(add_cnt1) begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 =end_cnt0; //加一条件
assign end_cnt1 = add_cnt1 && cnt1== 10-1; //结束条件
//七段数码管显示秒的个位
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
led_SG<=8'hff;
else begin
case(cnt1)
0: led_SG<=8'hc0;
1: led_SG<=8'hf9;
2: led_SG<=8'ha4;
3: led_SG<=8'hb0;
4: led_SG<=8'h99;
5: led_SG<=8'h92;
6: led_SG<=8'h82;
7: led_SG<=8'hf8;
8: led_SG<=8'h80;
9: led_SG<=8'h90;
default led_SG<=8'hff;
endcase
end
end
//秒的十位
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt2 <= 0;
end
else if(add_cnt2) begin
if(end_cnt2)
cnt2 <= 0;
else
cnt2 <= cnt2 + 1;
end
end
assign add_cnt2 =end_cnt1; //加一条件
assign end_cnt2 = add_cnt2 && cnt2== 6-1; //结束条件
//七段数码管显示秒的十位
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
led_SS<=8'hff;
else begin
case(cnt2)
0: led_SS<=8'hc0;
1: led_SS<=8'hf9;
2: led_SS<=8'ha4;
3: led_SS<=8'hb0;
4: led_SS<=8'h99;
5: led_SS<=8'h92;
default led_SS<=8'hff;
endcase
end
end
/*********************************
*************分计数器**************
*********************************/
//分的个位
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt3 <= 0;
end
else if(add_cnt3) begin
if(end_cnt3)
cnt3 <= 0;
else
cnt3 <= cnt3 + 1;
end
end
assign add_cnt3 = end_cnt2; //加一条件
assign end_cnt3 = add_cnt3 && cnt3== 10-1; //结束条件
//七段数码管显示分的个位
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
led_CG<=8'hff;
else begin
case(cnt3)
0: led_CG<=8'hc0;
1: led_CG<=8'hf9;
2: led_CG<=8'ha4;
3: led_CG<=8'hb0;
4: led_CG<=8'h99;
5: led_CG<=8'h92;
6: led_CG<=8'h82;
7: led_CG<=8'hf8;
8: led_CG<=8'h80;
9: led_CG<=8'h90;
default led_CG<=8'hff;
endcase
end
end
//分的十位
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt4 <= 0;
end
else if(add_cnt4) begin
if(end_cnt4)
cnt4 <= 0;
else
cnt4 <= cnt4 + 1;
end
end
assign add_cnt4 =end_cnt3; //加一条件
assign end_cnt4 = add_cnt4 && cnt4== 6-1; //结束条件
//七段数码管显示分的十位
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
led_CS<=8'hff;
else begin
case(cnt4)
0: led_CS<=8'hc0;
1: led_CS<=8'hf9;
2: led_CS<=8'ha4;
3: led_CS<=8'hb0;
4: led_CS<=8'h99;
5: led_CS<=8'h92;
default led_CS<=8'hff;
endcase
end
end
/*********************************
*************时计数器**************
*********************************/
//时的个位
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt5 <= 0;
end
else if(add_cnt5) begin
if(end_cnt5)
cnt5 <= 0;
else
cnt5 <= cnt5 + 1;
end
end
assign add_cnt5 =end_cnt4; //加一条件
assign end_cnt5 = add_cnt5 && cnt5== x-1 ; //结束条件,x约束其计数的次数
//七段数码管显示时的个位
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
led_HG<=8'hff;
else begin
case(cnt5)
0: led_HG<=8'hc0;
1: led_HG<=8'hf9;
2: led_HG<=8'ha4;
3: led_HG<=8'hb0;
4: led_HG<=8'h99;
5: led_HG<=8'h92;
6: led_HG<=8'h82;
7: led_HG<=8'hf8;
8: led_HG<=8'h80;
9: led_HG<=8'h90;
default led_HG<=8'hff;
endcase
end
end
//时的十位
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt6 <= 0;
end
else if(add_cnt6) begin
if(end_cnt6)
cnt6 <= 0;
else
cnt6 <= cnt6 + 1;
end
end
assign add_cnt6 =end_cnt5; //加一条件
assign end_cnt6 = add_cnt6 && cnt6== 3-1; //结束条件
always@(*) begin
if(cnt6==0) begin //当时的十位为0时,时的个位可以计数到9
x=10;
end
else if(cnt6==1) begin //当时的十位为1时,时的个位可以计数到9
x=10;
end
else if(cnt6==2) begin //当时的十位为2时,时的个位可以计数到3
x=4;
end
end
//七段数码管显示时的十位
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
led_HS<=8'hff;
else begin
case(cnt6)
0: led_HS<=8'hc0;
1: led_HS<=8'hf9;
2: led_HS<=8'ha4;
default led_HS<=8'hff;
endcase
end
end
/**********************************************************************************************
*************************************四段式状态机设置定时时钟************************************
**********************************************************************************************/
//第一段:同步时序always模块,格式化描述次态寄存器迁移到现态寄存器(不需要更改)
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
state_c<=IDLE;
end
else begin
state_c<=state_n;
end
end
//第二段:组合逻辑always模块,描述状态转移条件判断
always@(*) begin
case(state_c)
IDLE:begin
if(idle2s1_start) begin //当满足初态转S1态条件时,现态转为S1态
state_n=S1;
end
else begin
state_n=IDLE; //如若不满足,现态转回初态
end
end
S1:begin
if(s12s2_start) begin //当满足S1态转S2态条件时,现态转为S2态
state_n=S2;
end
else begin
state_n=IDLE; //如若不满足,现态转回初态
end
end
S2:begin
if(s22s3_start) begin //当满足S2转S3态条件时,现态转为S3态
state_n=S3;
end
else begin
state_n=IDLE; //如若不满足,现态转回初态
end
end
S3:begin
if(s32s4_start) begin //当满足S3态转S4态条件时,现态转为S4态(输出态)
state_n=S4;
end
else begin
state_n=IDLE; //如若不满足,现态转回初态
end
end
S4:begin
if(s42idle) begin //S4为输出态,进行输出后转回初态
state_n=IDLE;
end
end
default: begin
state_n=IDLE;
end
endcase
end
//第三段:进行次态state_n跳转条件的设计(设置闹钟)
assign idle2s1_start = state_c == IDLE && cnt3==sel1; //分的个位设置
assign s12s2_start = state_c == S1 && cnt4==sel2; //分的十位设置
assign s22s3_start = state_c == S2 && cnt5==sel3; //时的个位设置
assign s32s4_start = state_c == S3 && cnt6==sel4; //时的十位设置
assign s42idle = state_c == S4 && cnt2==1; //闹钟报时持续时间
//第四段:同步时序always模块,格式化描述寄存器输出
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout<=1'b0; //初始化
end
else if(state_c==S4) begin //当现态为S4时输出
dout<=1'b1;
end
else begin
dout<=1'b0;
end
end
endmodule
仿真代码:
`timescale 1 ns/ 1 ns
module clock_vlg_tst();
parameter CYCLE=20;
reg clk;
reg rst_n;
reg en;
wire dout;
wire [7:0] led_SG;
wire [7:0] led_SS;
wire [7:0] led_CG;
wire [7:0] led_CS;
wire [7:0] led_HG;
wire [7:0] led_HS;
reg [3:0] sel1;
reg [3:0] sel2;
reg [3:0] sel3;
reg [3:0] sel4;
clock i1 (
.clk(clk),
.led_SG(led_SG),
.led_SS(led_SS),
.led_CG(led_CG),
.led_CS(led_CS),
.led_HG(led_HG),
.led_HS(led_HS),
.sel1(sel1),
.sel2(sel2),
.sel3(sel3),
.sel4(sel4),
.dout(dout),
.en(en),
.rst_n(rst_n)
);
//生成本地时钟:50M
initial begin
clk = 0;
forever
#(CYCLE/2)
clk=~clk;
end
//生成复位信号
initial begin
rst_n = 0;
#2;
rst_n = 1;
end
//控制时钟暂停与开始的仿真相关代码部分
initial begin
en=1;
#3600000;
en=0;
#360000;
en=1;
end
//定时闹钟的仿真相关代码部分
initial begin
sel1 = 4'b0000;
sel2 = 4'b0000;
forever begin
//0
sel3 = 4'b0000;
sel4 = 4'b0000;
#3600000;
//1
sel3 = 4'b0001;
sel4 = 4'b0000;
#3600000;
//2
sel3 = 4'b0010;
sel4 = 4'b0000;
#3600000;
//3
sel3 = 4'b0011;
sel4 = 4'b0000;
#3600000;
//4
sel3 = 4'b0100;
sel4 = 4'b0000;
#3600000;
//5
sel3 = 4'b0101;
sel4 = 4'b0000;
#3600000;
//6
sel3 = 4'b0110;
sel4 = 4'b0000;
#3600000;
//7
sel3 = 4'b0111;
sel4 = 4'b0000;
#3600000;
//8
sel3 = 4'b1000;
sel4 = 4'b0000;
#3600000;
//9
sel3 = 4'b1001;
sel4 = 4'b0000;
#3600000;
//10
sel3 = 4'b0000;
sel4 = 4'b0001;
#3600000;
//11
sel3 = 4'b0001;
sel4 = 4'b0001;
#3600000;
//12
sel3 = 4'b0010;
sel4 = 4'b0001;
#3600000;
//13
sel3 = 4'b0011;
sel4 = 4'b0001;
#3600000;
//14
sel3 = 4'b0100;
sel4 = 4'b0001;
#3600000;
//15
sel3 = 4'b0101;
sel4 = 4'b0001;
#3600000;
//16
sel3 = 4'b0110;
sel4 = 4'b0001;
#3600000;
//17
sel3 = 4'b0111;
sel4 = 4'b0001;
#3600000;
//18
sel3 = 4'b1000;
sel4 = 4'b0001;
#3600000;
//19
sel3 = 4'b1001;
sel4 = 4'b0001;
#3600000;
//20
sel3 = 4'b0000;
sel4 = 4'b0010;
#3600000;
//21
sel3 = 4'b0001;
sel4 = 4'b0010;
#3600000;
//22
sel3 = 4'b0010;
sel4 = 4'b0010;
#3600000;
//23
sel3 = 4'b0011;
sel4 = 4'b0010;
#3600000;
end
end
endmodule
仿真结果:
//时钟模块
从仿真图中看出,当使能端口en为低电平时,时钟暂停工作,当en为高电平时时钟开始工作。
文章来源地址https://www.toymoban.com/news/detail-502006.html
从仿真图中可以看出,当秒的个位计数到9时,秒的十位加1。
从仿真图中可以看出,当秒的十位计数到5时,分的个位加1。
从仿真图中可以看出,当分的个位计数到9时,分的十位加1。
从仿真图中可以看出,当分的十位计数到5时,时的个位加1。
从仿真图中可以看出,当时的十位为0或1时,时的个位计数到9时,时的十位加1;当时的十位为2时,时的个位计数到3时,时的十位加1。
/定时闹钟模块
sel1、sel2、sel3、sel4分别给定时闹钟设置分的个位、分的十位、时的个位和时的十位,dout端口为定时报时的输出,当闹钟时间为整点时,开始报时。文章来源:https://www.toymoban.com/news/detail-502006.html
到了这里,关于电子时钟设计(verilog实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!