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.
解题思路:对于秒ss,当其计时到59时自动归零,并向分mm发出一个使能信号使其+1;
对于分mm,当mm计时到59并且ss计时到59时归零,并向时hh发出一个使能信号使其+1;
对于时hh,当hh计时到11,并且mm计时到59,并且ss计时到59时,让pm翻转;当计时到12:59:59时,令hh=1,mm=0,ss=0;
使能和清零信号单独处理。
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
wire [1:0] enable; //使能信号,enable[0]为mm使能,enable[1]为hh使能
ssBCD s1 (clk, reset, ena, ss); //ss计时模块
assign enable[0] = (ss == 8'h59) ? 1 : 0; //ss==59时使能mm计时
mmBCD m1 (clk, reset, enable[0], ss, mm); //mm计时模块
assign enable[1] = ((ss == 8'h59) && (mm == 8'h59)) ? 1 : 0; //ss==59并且mm==59时使能mm计时
hhBCD h1 (clk, reset, enable[1], ss, mm, hh, pm); //hh计时模块
endmodule
module ssBCD (input clk, reset, ena, output [7:0] ss); //ss计时模块
always @(posedge clk) begin
if (reset | (ss == 8'h59)) ss = 8'h00; //ss==59时自动归零
else if (ena == 0) ss = ss; //使能信号控制ss计时与否
else if (ss[3:0] == 9) begin ss[7:4]++; ss[3:0] = 0; end //2个BCD数字计时
else ss[3:0]++;
end
endmodule
module mmBCD (input clk, reset, ena, input [7:0] ss, output [7:0] mm);
always @(posedge clk) begin
if (reset | ((ss == 8'h59) && (mm == 8'h59))) mm = 8'h00;
else if (ena == 0) mm = mm;
else if (mm[3:0] == 9) begin mm[7:4]++; mm[3:0] = 0; end
else mm[3:0]++;
end
endmodule
module hhBCD (input clk, reset, ena, input [7:0] ss, input [7:0] mm, output [7:0] hh, output pm);
always @(posedge clk) begin
if (reset) begin hh = 8'h12; pm = 0; end
else if ((hh == 8'h11) && (ss == 8'h59) && (mm == 8'h59)) begin hh = 8'h12; pm = !(pm); end
else if ((hh == 8'h12) && (ss == 8'h59) && (mm == 8'h59)) begin hh = 8'h01; end
else if (ena == 0) hh = hh;
else if (hh[3:0] == 9) begin hh[7:4]++; hh[3:0] = 0; end
else hh[3:0]++;
end
endmodule