目录
背景
原题复现
审题
我的设计
设计解释
欢迎加入
这篇博客设计一个12小时的时钟,通过例化4bit BCD码计数器来设计,如果你给予的时钟周期是1s,则能够当做时钟来用哦。
原题如下:
Create a set of counters suitable for use as a 12-hour clock (with am/pm indicator). Your counters are clocked by a fast-running clk, with a pulse on ena whenever your clock should increment (i.e., once per second).
reset resets the clock to 12:00 AM. pm is 0 for AM and 1 for PM. hh, mm, and ss are two BCD (Binary-Coded Decimal) digits each for hours (01-12), minutes (00-59), and seconds (00-59). Reset has higher priority than enable, and can occur even when not enabled.
用计数器设计一个带am/pm的12小时时钟。该计数器通过一个CLK进行计时,用ena使能信号来驱动时钟的递增。
reset信号将时钟复位为12:00 AM。 信号pm为0代表AM,为1代表PM。hh、mm和ss由两个BCD计数器构成hours(01~12), minutes(00~59) , second(00~59)。Reset信号比enable信号有更高的优先级,即使没有enable信号也可以进行复位操作。
The following timing diagram shows the rollover behaviour from 11:59:59 AM to 12:00:00 PM and the synchronous reset and enable behaviour.
模块声明如下:
Module Declaration
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
这个题目的几个要求:
好了,这里为了解决这个大问题,我先设计一个秒和分钟的计数器,也就是能从0到59的模60BCD计数器:
module count60(
input clk,
input reset,
input en,
output reg [7:0] cnt_out
);
always@(posedge clk) begin
if(reset) cnt_out <= 0;
else if(en) begin
if(cnt_out == 8'h59) begin
cnt_out <= 0;
end
else if(cnt_out[3:0] == 9) begin
cnt_out[3:0] <= 0;
cnt_out[7:4] <= cnt_out[7:4] + 1;
end
else begin
cnt_out[3:0] <= cnt_out[3:0] + 1;
end
end
end
endmodule
在设计一个从1计数到12的模12 BCD计数器:
module count12 (
input clk, // Clock
input reset, // Asynchronous reset active high
input en,
output reg [7:0] cnt_out
);
always@(posedge clk) begin
if(reset) cnt_out <= 8'h12;
else if(en) begin
if(cnt_out == 8'h12) begin
cnt_out <= 1;
end
else if(cnt_out[3:0] == 9) begin
cnt_out[3:0] <= 0;
cnt_out[7:4] <= cnt_out[7:4] + 1;
end
else begin
cnt_out[3:0] <= cnt_out[3:0] + 1;
end
end
end
endmodule
最后,通过例化得到最终的12小时时钟:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
count60 inst_second(
.clk(clk),
.reset(reset),
.en(ena),
.cnt_out(ss)
);
count60 inst_min(
.clk(clk),
.reset(reset),
.en(ena&(ss == 8'h59)),
.cnt_out(mm)
);
count12 inst_hour(
.clk(clk),
.reset(reset),
.en(ena&(ss == 8'h59)&(mm == 8'h59)),
.cnt_out(hh)
);
reg p;
always@(posedge clk) begin
if(reset) p <= 0;
else if(hh == 8'h11 && ss == 8'h59&& mm == 8'h59) p <= ~p;
else ;
end
assign pm = p;
endmodule
上面代码的最后一部分用于产生pm指示上下午的信号:
reg p;
always@(posedge clk) begin
if(reset) p <= 0;
else if(hh == 8'h11 && ss == 8'h59&& mm == 8'h59) p <= ~p;
else ;
end
assign pm = p;
这样,设计就结束了。
通过例化模块的方式比在一个模块中写完整个设计要简洁,清晰,思路也更明朗了。
在今年的秋招一开始,我就建立了一个微信群,在CSDN发布了一条博文,召集全国各地的同行朋友们共同加入,共同讨论秋招求职笔试,面试经验,目前已经有300多人加入,各位才华横溢,让我大开眼界。 到今天11月份,从西北地区最早结束到其他各地陆续结束,但是我们曾开玩笑说,本群继续召集下一届同行,作为先行者的我们也会对你们给予应有的帮助,欢迎加入,到你们晒工资的时候,会不会再次把我们倒挂呢?拭目以待。 由于人数较多,所以加我的时候务必备注:CSDN+地区或学校+职位(意向职位)+昵称。 对于后来很晚的人,也许你看到这个博客我已经工作了,也许我已经变了,不再是一个热心的博主,因此,可能我没有时间做这些事情了,还请见谅。