12-hour clock
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.
1 module top_module(
2 input clk,
3 input reset,
4 input ena,
5 output pm,
6 output [7:0] hh,
7 output [7:0] mm,
8 output [7:0] ss);
9 reg pm_temp;
10 reg [3:0] ss_ones;
11 reg [3:0] ss_tens;
12 reg [3:0] mm_ones;
13 reg [3:0] mm_tens;
14 reg [3:0] hh_ones;
15 reg [3:0] hh_tens;
16
17 wire add_ss_ones;
18 wire end_ss_ones;
19 wire add_ss_tens;
20 wire end_ss_tens;
21 wire add_mm_ones;
22 wire end_mm_ones;
23 wire add_mm_tens;
24 wire end_mm_tens;
25 wire add_hh_ones;
26 wire end_hh_ones_0;
27 wire end_hh_ones_1;
28 wire add_hh_tens;
29 wire end_hh_tens_0;
30 wire end_hh_tens_1;
31 wire pm_ding;
32
33 assign add_ss_ones = ena;
34 assign end_ss_ones = add_ss_ones && (ss_ones == 4'd9);
35 always @(posedge clk)begin
36 if(reset)begin
37 ss_ones <= 4'b0;
38 end
39 else if(add_ss_ones)begin
40 if(end_ss_ones)begin
41 ss_ones <= 4'b0;
42 end
43 else begin
44 ss_ones <= ss_ones + 4'b1;
45 end
46 end
47 end
48
49 assign add_ss_tens = end_ss_ones;
50 assign end_ss_tens = add_ss_tens && (ss_tens == 4'd5);
51 always @(posedge clk)begin
52 if(reset)begin
53 ss_tens <= 4'b0;
54 end
55 else if(add_ss_tens)begin
56 if(end_ss_tens)begin
57 ss_tens <= 4'b0;
58 end
59 else begin
60 ss_tens <= ss_tens + 4'b1;
61 end
62 end
63 end
64
65 assign add_mm_ones = end_ss_tens;
66 assign end_mm_ones = add_mm_ones && (mm_ones == 4'd9);
67 always @(posedge clk)begin
68 if(reset)begin
69 mm_ones <= 4'b0;
70 end
71 else if(add_mm_ones)begin
72 if(end_mm_ones)begin
73 mm_ones <= 4'b0;
74 end
75 else begin
76 mm_ones <= mm_ones + 4'b1;
77 end
78 end
79 end
80
81 assign add_mm_tens = end_mm_ones;
82 assign end_mm_tens = add_mm_tens && (mm_tens == 4'd5);
83 always @(posedge clk)begin
84 if(reset)begin
85 mm_tens <= 4'b0;
86 end
87 else if(add_mm_tens)begin
88 if(end_mm_tens)begin
89 mm_tens <= 4'b0;
90 end
91 else begin
92 mm_tens <= mm_tens + 4'b1;
93 end
94 end
95 end
96
97 assign add_hh_ones = end_mm_tens;
98 assign end_hh_ones_0 = add_hh_ones && (hh_ones == 4'd9);
99 assign end_hh_ones_1 = add_hh_ones && ((hh_ones == 4'd2) && (hh_tens == 4'd1));
100 always @(posedge clk)begin
101 if(reset)begin
102 hh_ones <= 4'd2;
103 end
104 else if(add_hh_ones)begin
105 if(end_hh_ones_0)begin
106 hh_ones <= 4'b0;
107 end
108 else if(end_hh_ones_1)begin
109 hh_ones <= 4'b1;
110 end
111 else begin
112 hh_ones <= hh_ones+4'b1;
113 end
114 end
115 end
116
117 assign add_hh_tens = end_mm_tens;
118 assign end_hh_tens_0 = add_hh_tens && end_hh_ones_1;
119 assign end_hh_tens_1 = add_hh_tens && end_hh_ones_0;
120 always @(posedge clk)begin
121 if(reset)begin
122 hh_tens <= 4'b1;
123 end
124 else if(add_hh_tens)begin
125 if(end_hh_tens_0)begin
126 hh_tens <= 4'b0;
127 end
128 else if(end_hh_tens_1)begin
129 hh_tens <= hh_tens + 4'b1;
130 end
131 end
132 end
133
134 always@(posedge clk)begin
135 if(reset)begin
136 pm_temp <= 1'b0;
137 end
138 else if(pm_ding)begin
139 pm_temp <= ~pm_temp;
140 end
141 end
142
143 assign pm_ding = hh_tens == 4'd1 && hh_ones == 4'd1 && end_mm_tens;
144
145 assign ss = {ss_tens, ss_ones};
146 assign mm = {mm_tens, mm_ones};
147 assign hh = {hh_tens, hh_ones};
148 assign pm = pm_temp;
149
150 endmodule
按照之前的题目,由简单到复杂,这个题目就可以解决了,如果不清楚,建议把counter这个部分的题目,从第一题开始重新写一遍,慢慢理解就好。