HDLBits 系列(19) 12小时时钟的Verilog设计

目录

背景

原题复现

审题

我的设计

设计解释

欢迎加入


背景

这篇博客设计一个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.

HDLBits 系列(19) 12小时时钟的Verilog设计_第1张图片

模块声明如下:

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); 

审题

这个题目的几个要求:

  • 能够进行12小时计数,那就要求有秒,分钟,小时;
  • 使用BCD计数器来实现;
  • 复位有效时,复位到12点;
  • 要能够区分上下午,上午pm为0,下午pm为1;
  • 复位比使能优先级更高;
  • 由于是时钟,所以是从1点到12点;

我的设计

好了,这里为了解决这个大问题,我先设计一个秒和分钟的计数器,也就是能从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+地区或学校+职位(意向职位)+昵称。 对于后来很晚的人,也许你看到这个博客我已经工作了,也许我已经变了,不再是一个热心的博主,因此,可能我没有时间做这些事情了,还请见谅。

 

 

你可能感兴趣的:(#,HDLBits)