前言
本文为学习记录,问题来自于HDLbits网站上的习题。笔者能力尚浅,如有纰漏错误欢迎指正,若有其他想法也欢迎交流。
问题描述:
Count clock-HDLbits
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.
问题解决:
源代码:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
reg [4:0] bcd_ena;
reg [3:0] s0,s1,m0,m1;
//设置计数条件
assign bcd_ena[0] = ena?1:0;
assign bcd_ena[1] = (s0 == 4'd9 && s1 <= 4'd5 && ena)?1:0;
assign bcd_ena[2] = (s0 == 4'd9 && s1 == 4'd5 && ena)?1:0;
assign bcd_ena[3] = (s0 == 4'd9 && s1 == 4'd5 && m0 == 4'd9 && m1 <= 4'd5 && ena)?1:0;
assign bcd_ena[4] = (s0 == 4'd9 && s1 == 4'd5 && m0 == 4'd9 && m1 == 4'd5 && ena)?1:0;
//实例化
bcd_count count0(clk,reset,bcd_ena[0],4'd9,s0);
bcd_count count1(clk,reset,bcd_ena[1],4'd5,s1);
bcd_count count2(clk,reset,bcd_ena[2],4'd9,m0);
bcd_count count3(clk,reset,bcd_ena[3],4'd5,m1);
bcd_count_h count4(clk,reset,bcd_ena[4],hh,pm);
assign mm = {m1,m0};
assign ss = {s1,s0};
endmodule
//由于分和秒都是60进制,故其计数规则相同
module bcd_count(input clk,input reset,input ena,input [3:0]limit,output [3:0]c);
//由于十位与各位递增的上限不同,故添加输入limit作为限制条件
always @(posedge clk)begin
if(reset || ena&&c == 4'd9 || ena&&c == limit)begin
c = 4'd0;
end
else begin
if(ena)
c = c + 1;
end
end
endmodule
//根据问题描述,小时对应的两位的计数范围为01-12,故与分和秒技术规则不同
module bcd_count_h(input clk,input reset,input ena,output [7:0]c,output pm);
//输出pm值为0时对应AM,值为1时对应PM
reg [3:0]c0,c1;
//初始化时间
initial begin
c0 = 4'd2;
c1 = 4'd1;
pm = 0;
end
always @(posedge clk)begin
if(reset)begin
c0 = 4'd2;
c1 = 4'd1;
pm = 0;
end
else if( ena&&c0 == 4'd9)begin
c0 = 4'd0;
c1 = c1 + 1;
end
//每当从11:59:59向12:00:00跳转时,pm信号取反
else if(ena && c1 ==4'd1 && c0 == 4'd1)begin
pm = ~pm;
c0 = c0 + 1;
end
//计数范围为01-12,不存在00:00:00
else if(ena && c1 == 4'd1 && c0 == 4'd2)begin
c1 = 4'd0;
c0 = 4'd1;
end
else begin
if(ena)begin
c0 = c0 + 1;
end
end
end
assign c = {c1,c0};
endmodule
仿真结果: