105 countbcd
Build a 4-digit BCD (binary-coded decimal) counter. Each decimal digit is encoded using 4 bits: q[3:0] is the ones digit, q[7:4] is the tens digit, etc. For digits [3:1], also output an enable signal indicating when each of the upper three digits should be incremented.
You may want to instantiate or modify some one-digit decade counters.
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
BCD_counter u0
(
.clk (clk),
.reset (reset),
.enable (1),
.q (q[3:0])
);
BCD_counter u1
(
.clk (clk),
.reset (reset),
.enable (ena[1]),
.q (q[7:4])
);
BCD_counter u2
(
.clk (clk),
.reset (reset),
.enable (ena[2]),
.q (q[11:8])
);
BCD_counter u3
(
.clk (clk),
.reset (reset),
.enable (ena[3]),
.q (q[15:12])
);
assign ena[1] = (q[3:0] == 9);
assign ena[2] = ((q[7:4] == 9)&(q[3:0] == 9));
assign ena[3] = ((q[11:8] == 9)&(q[7:4] == 9)&(q[3:0] == 9));
endmodule
module BCD_counter(
input clk,
input reset, // Synchronous active-high reset
input enable,
output [3:0] q);
always@(posedge clk)
begin
if(reset)
q<= 0;
else
begin
if(enable)
begin
if(q<4'd9)
q<=q+4'd1;
else
q<=4'd0;
end
end
end
endmodule
106 count_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.
Hint...
Note that 11:59:59 PM advances to 12:00:00 AM, and 12:59:59 PM advances to 01:00:00 PM. There is no 00:00:00.
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
wire reset_ss,reset_mm,reset_hh;
wire enable_ss,enable_mm,enable_hh;
assign reset_ss = reset;
assign reset_mm = reset;
assign reset_hh = reset;
assign enable_ss = ena;
assign enable_mm = (ss == {4'd5,4'd9})&ena;
assign enable_hh = (ss == {4'd5,4'd9})&(mm == {4'd5,4'd9})&ena;
wire [7:0]d_hh;
assign d_hh = (reset)?{4'd1,4'd2}:{8'd1};
always@(posedge clk)
begin
if(reset)
pm <= 0;
else if((ss == {4'd5,4'd9})&(mm == {4'd5,4'd9})&(hh=={4'd1,4'd1}))
pm <= ~pm;
else
pm<=pm;
end
BCD_counter_8bits u0_ss
(
.clk(clk),
.reset(reset_ss),
.enable(enable_ss),
.d(0),
.max({4'd5,4'd9}),
.q(ss)
);
BCD_counter_8bits u1_mm
(
.clk(clk),
.reset(reset_mm),
.enable(enable_mm),
.d(0),
.max({4'd5,4'd9}),
.q(mm)
);
BCD_counter_8bits u2_hh
(
.clk(clk),
.reset(reset_hh),
.enable(enable_hh),
.d(d_hh),
.max({4'd1,4'd2}),
.q(hh)
);
endmodule
module BCD_counter_8bits(
input clk,
input reset,
input enable,
input [7:0]d,
input [7:0]max,
output [7:0]q
);
always@(posedge clk)
begin
if(reset)
q<=d;
else
begin
if(enable)
begin
if(q==max)
q=d;
else if(q[3:0]==4'd9)begin
q[7:4] <= q[7:4]+1'd1;
q[3:0] <= 4'd0;
end
else
begin
q[3:0]<=q[3:0]+1'd1;
end
end
end
end
endmodule