题目要求:
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.
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.
大意:复位时设置时间为12:00:00 AM(即PM=0),hh、mm、ss为BCD (Binary-Coded Decimal)两位,分别代表小时(01-12)、分钟(00-59)、秒(00-59)。Reset的优先级高于enable。
要点:PM在11:59:59实现反转,ss为59时mm开始计时,mm、ss均为59,hh开始计时(第一遍设计出错,应把8位的hh、mm、ss各分为2个4位)
代码:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
reg [3:0] hh1,hh0,mm1,mm0,ss1,ss0;
always@(posedge clk)begin//ss
if(reset)begin
ss0<='b0;
end
else if(!reset&&ena==1'd1)begin//reset=0,ena=1
if(ss0==4'd9)begin
ss0<=4'd0;
end
else begin
ss0<=ss0+1'd1;
end
end
end
always@(posedge clk)begin
if(reset)begin
ss1<='b0;
end
else if(!reset&&ena==1'd1)begin
if(ss1==4'd5&&ss0==4'd9)begin
ss1<=4'd0;
end
else if(ss0==4'd9)begin
ss1<=ss1+1'd1;
end
end
end
//mm0--------------------------------------------
always@(posedge clk)begin
if(reset)begin
mm0<='d0;
end
else if(!reset&&ena==1'd1)begin
if(mm0==4'd9&&ss1==4'd5&&ss0==4'd9)begin//xx:x9:59,mm0归零
mm0<='d0;
end
else if(ss0==4'd9&&ss1==4'd5)begin//xx:xx:59,进位至mm0,开始计时
mm0<=mm0+1'd1;
end
end
end
//mm1-------------------------------------------
always@(posedge clk)begin
if(reset)begin
mm1<='d0;
end
else if(!reset&&ena==1'd1)begin
if(mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5)begin//xx:59:59,分钟位归零
mm1<=4'd0;
end
else if(ss0==4'd9&&ss1==4'd5&&mm0==4'd9)begin//xx:x9:59,mm1开始计时
mm1<=mm1+1'd1;
end
end
end
//hh0----------------------------
always@(posedge clk)begin
if(reset)begin
hh0<=4'd2;
end
else if(!reset&&ena==1'd1)begin
if(hh0==4'd9&&mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5)begin//09:59:59,跳转到10:00:00
hh0<=4'd0;
end
else if(hh1==4'd1&&hh0==4'd2&&mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5)begin//12:59:59跳转到01:00:00
hh0<=4'd1;
end
else if(mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5)begin//xx:59:59小时开始计时
hh0<=hh0+1'd1;
end
end
end
//hh1---------------------------------------------------
always@(posedge clk)begin
if(reset)begin
hh1<=4'd1;
end
else if(!reset&&ena==1'd1)begin
if(mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5&&hh0==4'd9)begin//09:59:59进位10:00:00
hh1<=4'd1;
end
else if(mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5&&hh1==4'd1&&hh0==4'd2)begin//12:59:59跳转至01:00:00
hh1<=4'd0;
end
end
end
always@(posedge clk)begin
if(reset)begin
pm<='b0;//复位要求12:00:00AM
end
if(mm0==4'd9&&mm1==4'd5&&ss0==4'd9&&ss1==4'd5&&hh0==4'd1&&hh1==4'd1)begin//每次到11:59:59时PM翻转
pm<=~pm;
end
end
//---------------------------------------------------------------------
assign hh={hh1,hh0};
assign mm={mm1,mm0};
assign ss={ss1,ss0};
endmodule
运行结果