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 load,
	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 c_load,
    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;
    
    count4 counter(clk,c_enable,c_load,c_d,Q);
    
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[0] represents the fastest counter and c_enable[2] 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[0],one);
    bcdcount counter1 (clk, reset, c_enable[1],ten);
    bcdcount counter2 (clk, reset, c_enable[2],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[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[2] = ((ones == 4'd9) && (tens == 4'd9)) ? 1'b1 : 1'b0;
    assign ena[3] = ((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	add_ss_ones,end_ss_ones,add_ss_tens,end_ss_tens;
    wire	add_mm_ones,end_mm_ones,add_mm_tens,end_mm_tens;
    wire	add_hh_ones,end_hh_ones_0,end_hh_ones_1,add_hh_tens,end_hh_tens_0,end_hh_tens_1;
    wire	pm_ding;
    
    assign add_ss_ones = ena;
    assign end_ss_ones = add_ss_ones && (ss_ones == 4'd9);
    always @(posedge clk)begin
        if(reset)begin
            ss_ones <= 4'b0;
        end
        else if(add_ss_ones)begin
            if(end_ss_ones)
                ss_ones <= 4'b0;
            else 
                ss_ones <= ss_ones + 4'b1;
        end
    end
    
    assign add_ss_tens = end_ss_ones;
    assign end_ss_tens = add_ss_tens && (ss_tens == 4'd5);
    always @(posedge clk)begin
        if(reset)
            ss_tens <= 4'b0;
        else if(add_ss_tens)begin
            if(end_ss_tens)
                ss_tens <= 4'b0;
            else 
                ss_tens <= ss_tens + 4'b1;
        end
    end
    
    assign add_mm_ones = end_ss_tens;
    assign end_mm_ones = add_mm_ones && (mm_ones == 4'd9);
    always @(posedge clk)begin
        if(reset)
            mm_ones <= 4'b0;
        else if(add_mm_ones)begin
            if(end_mm_ones)
                mm_ones <= 4'b0;
            else
                mm_ones <= mm_ones + 4'b1;
        end
    end
    
    assign add_mm_tens = end_mm_ones;
    assign end_mm_tens = add_mm_tens && (mm_tens == 4'd5);
	always @(posedge clk)begin
        if(reset)
            mm_tens <= 4'b0;
        else if(add_mm_tens)begin
            if(end_mm_tens)
                mm_tens <= 4'b0;
            else 
                mm_tens <= mm_tens + 4'b1;
        end
    end
    
    assign add_hh_ones = end_mm_tens;
    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;
        else if(add_hh_ones)begin
            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 add_hh_tens = end_mm_tens;
    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;
        else if(add_hh_tens)begin
            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