12-hour clock using six BCD digits
本文最后更新于:Tuesday, October 6th 2020, 11:32 am
problem link:https://hdlbits.01xz.net/wiki/Count_clock
Background
时钟是每个人每天都会用到的工具,那怎么用电子电路搭建一个12-hour(带有am/pm指示)的时钟呢?
Problem description
选择一系列合适的计数器。你的计数器统一被快时钟(fast-running clock)驱动, 还带有一个脉冲使能输入,该脉冲会在任何需要时钟加1的时候到来(i.e.,每秒来一次)
reset:重置时钟到12:00:00 AMpmis 0 for AM and 1 for PMhh:mm:ss:都各自代表两位BCD(用四位二进制表达一位十进制)数;hh(hours):01-12;mm(minutes):00-59;ss(seconds):00-59reset比enable有更高的权限,即使在使能信号无效的时候也可以值位。- 👇:从11:59:59 AM 到12:00:00 PM翻转和同步复位,使能的行为。
Hint:Note that 11:59:59 PM(晚上转钟) advances to 12:00:00 AM, and 12:59:59 PM(中午快1点了) advances to 01:00:00 PM. There is no 00:00:00.
Template
1 | |
Answer
① 1位BCD计数器
复位到0:为分钟,秒计数器服务
1
2
3
4
5
6
7
8
9
10
11
12
13/************** 1位BCD计数器,复位到0;实现0-9的循环 ***************/
module bcdreset0 (
input clk,
input reset, // Synchronous active-high reset
input enable,
output [3:0] q);
always @ (posedge clk) begin
if(reset) q <= 4'h0;
else if(!enable) q <= q;
else if(q == 4'h9) q <= 4'h0;
else q <= q + 4'h1;
end
endmodule复位到2:为小时低位服务(x->2)[⭐此处有特殊情况]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/************************* 1位BCD计数器,复位到2;实现0-9的循环 *************************/
/************** 个位为2时:当高位为1,下一次应该是1;但是当高位为0,下一次为3 **************/
module bcdreset2 (
input clk,
input reset, // Synchronous active-high reset
input flag, // 指示当前为特殊情况,即为12的时候
input enable,
output [3:0] q);
always @ (posedge clk) begin
if(reset) q <= 4'h2;
else if(!enable) q <= q;
else if(flag) q <= 4'h1; // 特殊情况
else if(q == 4'h9) q <= 4'h0;
else q <= q + 4'h1;
end
endmodule复位到1:为小时高位服务(x->1)[⭐此处有特殊情况]
1
2
3
4
5
6
7
8
9
10
11
12
13/*********** 1位BCD计数器,复位到2;实现0-1的循环 *************/
/*********** 每次使能到来,小时高位要么从0->1;要么从1->0;逻辑对应代码第11行***********/
module bcd_zero_one(
input clk,
input reset,
input enable,
output [3:0] q);
always @ (posedge clk) begin
if (reset) q <= 4'h1; // (复位为12; 高位为1)
else if (!enable) q <= q;
else q[0] <= ~q[0]; // 0变为1,1变为0(0000->0001)
end
endmodule② 两位BCD计数器
秒,分钟计数器:实现0-59循环;复位为0
1
2
3
4
5
6
7
8
9
10
11
12
13/**************** 两位BCD(8-bit)数表示0-59 ;循环到59时能不能下一个计数到0 **************/
module zero2fifty_nine(
input clk,
input reset,
input ena,
output [7:0] ss);
wire ena_ten, reset_ten;
assign reset_ten = (((ss == 8'h59) & ena) | reset)? 1'd1:1'd0;⭐// 当计数到59且下一个使能到来时,把高位置为到0;因为低位肯定回到0;如果不reset,那么肯定为60
assign ena_ten = ((ss[3:0] == 4'h9) & ena)?1'd1:1'd0; ⭐ // 个位到9(重点:必须使能到来)才能使能十位(假设现在为29分:00秒,分钟的十位使能必须在60s后才会到来;但是不并上使能,那么下一秒将是39分:01秒
decade_counter one (clk, reset, ena, ss[3:0]); // 4位二进制表示个位的0-9
decade_counter ten (clk, reset_ten, ena_ten, ss[7:4]); // 4位二进制表示十位的0-9
endmodule小时计数器:实现1-12循环,复位为12
1
2
3
4
5
6
7
8
9
10
11
12
13/************* 两位BCD(8-bit)数表示1-12;循环到12时能不能下一个计数到1 ***************/
/* ⭐(flag12) 小时个位为2时:当高位为1(12),下一次应该是1;但是当高位为0(02),下一次为3 */
module one2twelve(
input clk,
input reset,
input ena,
output [7:0] hh);
wire ena_ten, flag12;
assign ena_ten = (ena & ((hh == 8'h9)|(hh == 8'h12)))? 1'd1:1'd0; // 小时高位的改变信号(09->10;12->01)
assign flag12 = (hh == 8'h12); // 指示当前为12
BCDreset2 one (clk, reset, flag12, ena, hh[3:0]); // 4位二进制表示个位的0-9
BCDzero_one ten (clk, reset, ena_ten, hh[7:4]); // 4位二进制表示十位的0-1
endmodule③ 实例化三个②
1 | |
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!
