# HDLBits Chapter 11 exercises and answers

Keywords: Verilog

# 1. Four bit binary counter

Build a 4-bit binary counter from 0 to 15 with a period of 16. Synchronous reset, reset should reset the counter to 0. Code implementation:

```module top_module (
input clk,
input reset,      // Synchronous active-high reset
output [3:0] q);

always@(posedge clk) begin
if(!reset)
q <= q + 1'b1;
else
q <= 4'b0;
end

endmodule
```

Verification results: # 2. Decimal counter 1

Build a decimal counter from 0 to 9 (including 9), with a period of 10. Synchronous reset, reset should reset the counter to 0. Code implementation:

```module top_module (
input clk,
input reset,        // Synchronous active-high reset
output [3:0] q);

always@(posedge clk) begin
if(reset)
q <= 4'b0;
else begin
if(q < 9)
q <= q + 1'b1;
else
q <= 4'b0;
end
end

endmodule
```

Verification results: # 3. Decimal counter 2

Make a decimal counter from 1 to 10. Synchronous reset, reset should reset the counter to 1. Code implementation:

```module top_module (
input clk,
input reset,
output [3:0] q);

always@(posedge clk) begin
if(reset)
q <= 4'd1;
else begin
if(q < 10)
q <= q + 1'b1;
else
q <= 4'd1;
end
end

endmodule
```

Verification results: # 4. Delayed decimal counter

Build a decimal counter from 0 to 9 (including 9), with a period of 10. Synchronous reset, reset should reset the counter to 0. We want to be able to pause the counter instead of always incrementing every clock cycle, so the slowena input indicates when the counter should be incremented. Code implementation:

```module top_module (
input clk,
input slowena,
input reset,
output [3:0] q);

always@(posedge clk) begin
if(reset)
q <= 4'b0;
else
if(slowena) begin
if(q == 4'd9)
q <= 4'b0;
else
q<= q + 1'b1;
end
end

endmodule
```

Verification results:  # 5. Counter for 1-12

Design a 1-12 counter with the following inputs and outputs:
Reset: the synchronous high level is effectively reset, and the forced counter is 1
Enable: counter operation is set to high level
Clk: rising edge trigger clock input
Q[3:0]: output of counter
c_enable, c_load, c_d[3:0]: control the signal to the provided 4-bit counter, so as to verify whether the operation is correct.

You can use the following components:

(1) The following 4-bit binary counter (count4) has enable and synchronous parallel load inputs (load priority is higher than enable). The count4 module is provided to you. Instantiate it in your circuit.
(2) Logic gate

```module count4(
input clk,
input enable,
input [3:0] d,
output reg [3:0] Q
);
```

c_enable,c_load and C_ The d output is the signals of enable, load and d input to the internal counter respectively. Their purpose is to check the correctness of these signals.

Code implementation:

```module top_module (
input clk,
input reset,
input enable,
output [3:0] Q,
output c_enable,
output [3:0] c_d
);

assign c_enable = enable;
assign c_load = reset | ((Q == 4'd12) && (enable == 1'b1));
assign c_d = c_load ? 4'b1 : 4'b0;

endmodule
```

Verification results: # 6. 1kHz → 1Hz counter

A 1 Hz signal, called OneHertz, is derived from the 1000 Hz clock and can be used to drive the enable signal of a set of hour / minute / second counters to create a digital wall clock. Because we want the clock to count once per second, the 1 Hz signal must accurately maintain one cycle per second. The frequency divider is built using modulus 10 (BCD) counters and as few other gates as possible. The enable signal is also output from each BCD counter you use (c_enable represents the fastest counter and c_enable represents the slowest counter).
The following BCD counters are provided for you. Enable must be high to run the counter. The reset is synchronized and set to high to force the counter to zero. All counters in the circuit must directly use the same 1000 Hz signal.

```module bcdcount (
input clk,
input reset,
input enable,
output reg [3:0] Q
);
```

Code implementation:

```module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
);

wire [3:0] one,ten,hundred;
assign c_enable = {one ==4'd9 && ten == 4'd9, one ==4'd9 ,1'd1};
assign OneHertz = {one ==4'd9 && ten == 4'd9 && hundred ==4'd9};

bcdcount counter0 (clk, reset, c_enable,one);
bcdcount counter1 (clk, reset, c_enable,ten);
bcdcount counter2 (clk, reset, c_enable,hundred);

endmodule
```

Verification results:   # 7. Four digit decimal counter

Build a 4-bit BCD (binary coded decimal) counter. Each decimal digit is encoded with 4 bits: q[3:0] is one bit, q[7:4] is ten bits, and so on. It is also necessary to output an enable signal to indicate when the three digit number should be increased. Code implementation:

```module top_module (
input clk,
input reset,   // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);

reg [3:0] ones,tens,hundreds,thousands;

always @(posedge clk) begin
if(reset)
ones <= 4'b0;
else if(ones == 4'd9)
ones <=4'b0;
else
ones <= ones + 4'd1;
end

always @(posedge clk)begin
if(reset)
tens <= 4'b0;
else if(tens == 4'd9 && ones == 4'd9)
tens <= 4'b0;
else if(ones == 4'd9)
tens <= tens + 4'd1;
end

always @(posedge clk)begin
if(reset)
hundreds <= 4'b0;
else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
hundreds <= 4'b0;
else if(tens == 4'd9 && ones == 4'd9)
hundreds <= hundreds + 4'd1;
end

always @(posedge clk)begin
if(reset)
thousands <= 4'b0;
else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
thousands <= 4'b0;
else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
thousands <= thousands + 4'd1;
end

assign q = {thousands,hundreds,tens,ones};
assign ena = (ones == 4'd9) ? 1'b1 : 1'b0;
assign ena = ((ones == 4'd9) && (tens == 4'd9)) ? 1'b1 : 1'b0;
assign ena = ((ones == 4'd9) && (tens == 4'd9) && (hundreds == 4'd9)) ? 1'b1 : 1'b0;

endmodule
```

Verification results:  # 8. 12 hour clock

Create a set of counters (with am/pm indicators) suitable for use as a 12 hour clock. Your counter is driven by a fast running clk. ena must be 1 every time the clock increases. reset resets the clock to 12 noon. pm=0 in the morning and pm=0 in the afternoon. hh, mm, and ss are two BCD (binary coded decimal) numbers for hours (01-12), minutes (00-59), and seconds (00-59), respectively.

Reset has a higher priority than enable and occurs even when it is not enabled.

The following timing chart shows the flip behavior from 11:59:59 AM to 12:00:00 PM and the synchronous Reset and enable behavior. Code implementation:

```module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);

reg pm_temp;
reg [3:0] ss_ones,ss_tens,mm_ones,mm_tens,hh_ones,hh_tens;

wire	pm_ding;

assign end_ss_ones = add_ss_ones && (ss_ones == 4'd9);
always @(posedge clk)begin
if(reset)begin
ss_ones <= 4'b0;
end
if(end_ss_ones)
ss_ones <= 4'b0;
else
ss_ones <= ss_ones + 4'b1;
end
end

assign end_ss_tens = add_ss_tens && (ss_tens == 4'd5);
always @(posedge clk)begin
if(reset)
ss_tens <= 4'b0;
if(end_ss_tens)
ss_tens <= 4'b0;
else
ss_tens <= ss_tens + 4'b1;
end
end

assign end_mm_ones = add_mm_ones && (mm_ones == 4'd9);
always @(posedge clk)begin
if(reset)
mm_ones <= 4'b0;
if(end_mm_ones)
mm_ones <= 4'b0;
else
mm_ones <= mm_ones + 4'b1;
end
end

assign end_mm_tens = add_mm_tens && (mm_tens == 4'd5);
always @(posedge clk)begin
if(reset)
mm_tens <= 4'b0;
if(end_mm_tens)
mm_tens <= 4'b0;
else
mm_tens <= mm_tens + 4'b1;
end
end

assign end_hh_ones_0 = add_hh_ones && (hh_ones == 4'd9);
assign end_hh_ones_1 = add_hh_ones && ((hh_ones == 4'd2) && (hh_tens == 4'd1));
always @(posedge clk)begin
if(reset)
hh_ones <= 4'd2;
if(end_hh_ones_0)
hh_ones <= 4'b0;
else if(end_hh_ones_1)
hh_ones <= 4'b1;
else
hh_ones <= hh_ones + 4'b1;
end
end

assign end_hh_tens_0 = add_hh_tens && end_hh_ones_1;
assign end_hh_tens_1 = add_hh_tens && end_hh_ones_0;
always @(posedge clk)begin
if(reset)
hh_tens <= 4'b1;
if(end_hh_tens_0)
hh_tens <= 4'b0;
else if(end_hh_tens_1)
hh_tens <= hh_tens + 4'b1;
end
end

always@(posedge clk)begin
if(reset)
pm_temp <= 1'b0;
else if(pm_ding)
pm_temp <= ~pm_temp;
end

assign pm_ding = hh_tens == 4'd1 && hh_ones == 4'd1 && end_mm_tens;

assign ss = {ss_tens, ss_ones};
assign mm = {mm_tens, mm_ones};
assign hh = {hh_tens, hh_ones};
assign pm = pm_temp;

endmodule
```

Verification results:    reference material: Verilog counter.

Posted by eojlin on Thu, 23 Sep 2021 01:15:00 -0700