2. Visual verification of designs

2.1. Introduction

Note

In this chapter, a Mod-m counter is implemented and the counting is displayed on the LEDs and seven-segment-display device. Since, we want to visualize the output on these devices, therefore the reduced clock rate is required to visualize the counts.

In this chapter, we will re-implement the designs of the Chapter “Visual verification of designs” in the Verilog/VHDL tutorial. Please see the Verilog/SystemVerilog/VHDL tutorials for the explanation of the designs.

2.2. Flip flops

In this section, two types of flip flops are implemented.

2.2.1. Basic D flip flop

  • In the following code, the D-FF is implemented which transfer the input value to the output port after the delay of one clock cycle.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    # basic_dff.py
    # results is same as "basicDff.v" in the Verilog tutorial
    
    from myhdl import *
    
    @block
    def basic_dff(clk, reset_n, d, q):
        """ clk, reset, d : input
            q : output
        """
    
        @always(clk.posedge, reset_n.negedge)
        def dff_behave():
            if reset_n == 0 :
                q.next = 0
            else :
                q.next = d
        return dff_behave
    
    
    def main():
        clk = Signal(bool(0))
        reset_n = Signal(bool(0))
        d = Signal(bool(0))
        q = Signal(bool(0))
    
        top_dff = basic_dff(clk, reset_n, d, q)
        top_dff.convert(hdl="Verilog", initial_values=True)
    
    # function main() is the entry point
    if __name__ == '__main__':
        main()
    
  • The resultant Verilog code is shown below,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    // File: basic_dff.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 13:56:20 2017
    
    
    `timescale 1ns/10ps
    
    module basic_dff (
        clk,
        reset_n,
        d,
        q
    );
    // clk, reset, d : input
    // q : output
    
    input clk;
    input reset_n;
    input d;
    output q;
    reg q;
    
    always @(posedge clk, negedge reset_n) begin: BASIC_DFF_DFF_BEHAVE
        if ((reset_n == 0)) begin
            q <= 0;
        end
        else begin
            q <= d;
        end
    end
    
    endmodule
    

2.2.2. D-FF with enable port

  • In the below code, the ‘enable’ port is added to D-FF, so that input value is transferred to output port when the enable signal is high.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    # d_ff.py
    # results is same as "D_FF.v" in the Verilog tutorial
    
    from myhdl import *
    
    @block
    def dff_unit(clk, reset_n, en, d, q):
        """ clk, reset, en, d : input
            q : output
        """
    
        @always(clk.posedge, reset_n.negedge)
        def dff_behave():
            if reset_n == 0 :
                q.next = 0
            # else :
                # q.next = d
            elif  en == 1 :
                q.next = d
        return dff_behave
    
    # below module is created to change the name of the port
    # i.e. clk is changed to CLOCK_50
    @block
    def d_ff(CLOCK_50, reset_n, en, d, q):
        dff_top = dff_unit(CLOCK_50, reset_n, en, d, q)
        return dff_top
    
    def main():
        clk = Signal(bool(0))
        reset_n = Signal(bool(0))
        en = Signal(bool(0))
        d = Signal(bool(0))
        q = ResetSignal(0, active=0, async=True)
    
        top_dff2 = d_ff(clk, reset_n, en, d, q)
        top_dff2.convert(hdl="Verilog", initial_values=True)
    
    # function main() is the entry point
    if __name__ == '__main__':
        main()
    
  • The resultant Verilog code is shown below,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    // File: d_ff.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 14:05:54 2017
    
    
    `timescale 1ns/10ps
    
    module d_ff (
        CLOCK_50,
        reset_n,
        en,
        d,
        q
    );
    
    
    input CLOCK_50;
    input reset_n;
    input en;
    input d;
    output q;
    reg q;
    
    
    always @(posedge CLOCK_50, negedge reset_n) begin: D_FF_DFF_UNIT_1_DFF_BEHAVE
        if ((reset_n == 0)) begin
            q <= 0;
        end
        else if ((en == 1)) begin
            q <= d;
        end
    end
    
    endmodule
    

2.3. Mod-m Counter

In this section, a Mod M counter is implemented. Further, a testbench for the Mod M counter is shown in Section 3.1.

  • Following is the Python code for Mod M counter,

    Listing 2.1 mod_m_counter.py
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    # mod_m_counter.py
    # result is similar to 'modMCounter.v' in the verilog tutorial
    
    from myhdl import *
    
    @block
    def mod_m_counter(clk, reset_n, complete_tick, count, M, N):
        """ M = max count
            N = minimum bits required to represent M
        """
    
        count_reg = Signal(intbv(0)[N:0])
        count_next = Signal(intbv(0)[N:0])
    
        @always(clk.posedge, reset_n.negedge)
        def logic_reg():
            if reset_n == 0 :
                count_reg.next = 0
            else :
                count_reg.next = count_next
    
        @always_comb
        def logic_next():
            if count_reg == M-1 :
                count_next.next = 0
                complete_tick.next = 1
            else :
                count_next.next = count_reg + 1
                complete_tick.next = 0
    
        @always_comb
        def out_val():
            count.next = count_reg
    
        return out_val, logic_next, logic_reg
    
    
    def main():
        N = 3
        M = 5
    
        clk = Signal(bool(0))
        reset_n = Signal(bool(0))
        complete_tick = Signal(bool(0))
        count = Signal(intbv(0)[N:0])
        mod_m_counter_v = mod_m_counter(clk, reset_n, complete_tick, count, M, N)
        mod_m_counter_v.convert(hdl="Verilog", initial_values=True)
    
    if __name__ == '__main__':
        main()
    
  • The resultant Verilog code is shown below,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    // File: mod_m_counter.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 14:17:35 2017
    
    
    `timescale 1ns/10ps
    
    module mod_m_counter (
        clk,
        reset_n,
        complete_tick,
        count
    );
    // M = max count
    // N = minimum bits required to represent M
    
    input clk;
    input reset_n;
    output complete_tick;
    reg complete_tick;
    output [2:0] count;
    wire [2:0] count;
    
    reg [2:0] count_reg = 0;
    reg [2:0] count_next = 0;
    
    
    assign count = count_reg;
    
    
    always @(count_reg) begin: MOD_M_COUNTER_LOGIC_NEXT
        if (($signed({1'b0, count_reg}) == (5 - 1))) begin
            count_next = 0;
            complete_tick = 1;
        end
        else begin
            count_next = (count_reg + 1);
            complete_tick = 0;
        end
    end
    
    
    always @(posedge clk, negedge reset_n) begin: MOD_M_COUNTER_LOGIC_REG
        if ((reset_n == 0)) begin
            count_reg <= 0;
        end
        else begin
            count_reg <= count_next;
        end
    end
    
    endmodule
    

2.4. Clock ticks

To visualize the outputs, e.g. counting etc., we need to reduce the clock rate of the system; otherwise the changes will be too fast to observe.

Warning

  • The signal ‘count’ is not used anywhere in the ‘clock_tick.py’ but it is defined. Unlike VHDL, we can not keep the port Open in MyHDL. And a warning will be generated for the unused signal.
  • But ‘open port’ can be achieved by using ‘None’ keyword as shown in Section 2.7; also, it will remove the warning.
  • The Python code for generating the clock-ticks with reduced clock-rate are shown below,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # clock_tick.py
    # result is similar to 'clockTick.v' in the verilog tutorial
    
    from myhdl import *
    
    from mod_m_counter import mod_m_counter
    
    @block
    def clock_tick(clk, reset_n, clk_pulse, M, N):
        count = Signal(intbv(0)[N:0])
        mod_m_counter_inst = mod_m_counter(clk, reset_n, clk_pulse, count, M, N)
        return mod_m_counter_inst
    
    # instantiate clock_tick
    def main():
        clk = Signal(bool(0))
        reset_n = Signal(bool(0))
        clk_pulse = Signal(bool(0))
        M = 5000000 # 0.1 sec
        N = 29
    
        clock_tick_inst = clock_tick(clk, reset_n, clk_pulse, M, N)
        clock_tick_inst.convert(hdl="Verilog", initial_values=True)
    
    if __name__ == '__main__':
        main()
    
  • The corresponding Verilog code is shown below,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    // File: clock_tick.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 14:23:19 2017
    
    
    `timescale 1ns/10ps
    
    module clock_tick (
        clk,
        reset_n,
        clk_pulse
    );
    
    
    input clk;
    input reset_n;
    output clk_pulse;
    reg clk_pulse;
    
    wire [28:0] count;
    reg [28:0] mod_m_counter_1_count_reg = 0;
    reg [28:0] mod_m_counter_1_count_next = 0;
    
    
    assign count = mod_m_counter_1_count_reg;
    
    
    always @(mod_m_counter_1_count_reg) begin: CLOCK_TICK_MOD_M_COUNTER_1_LOGIC_NEXT
        if (($signed({1'b0, mod_m_counter_1_count_reg}) == (5000000 - 1))) begin
            mod_m_counter_1_count_next = 0;
            clk_pulse = 1;
        end
        else begin
            mod_m_counter_1_count_next = (mod_m_counter_1_count_reg + 1);
            clk_pulse = 0;
        end
    end
    
    
    always @(posedge clk, negedge reset_n) begin: CLOCK_TICK_MOD_M_COUNTER_1_LOGIC_REG
        if ((reset_n == 0)) begin
            mod_m_counter_1_count_reg <= 0;
        end
        else begin
            mod_m_counter_1_count_reg <= mod_m_counter_1_count_next;
        end
    end
    
    endmodule
    

2.5. Seven segment display

  • Below code convert the ‘hexadecimal number’ into seven-segment-display format,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    # hex_to_seven_seg.py
    # result is same as 'hexToSevenSegment.v' and
    # 'hexToSevenSegment_testCircuit.v' in the Verilog tutorial
    
    from myhdl import *
    
    @block
    def hex_to_seven_seg(hex_num, seven_seg):
    
        @always(hex_num)
        def logic():
            if hex_num == 0:
                seven_seg.next = 0b1000000
            elif hex_num == 1 :
                seven_seg.next = 0b1111001
            elif hex_num == 2 :
                seven_seg.next = 0b0100100
            elif hex_num == 3 :
                seven_seg.next = 0b0110000
            elif hex_num == 4 :
                seven_seg.next = 0b0011001
            elif hex_num == 5 :
                seven_seg.next = 0b0010010
            elif hex_num == 6 :
                seven_seg.next = 0b0000010
            elif hex_num == 7 :
                seven_seg.next = 0b1111000
            elif hex_num == 8 :
                seven_seg.next = 0b0000000
            elif hex_num == 9 :
                seven_seg.next = 0b0010000
            elif hex_num == 10 :
                seven_seg.next = 0b0001000
            elif hex_num == 11 :
                seven_seg.next = 0b0000011
            elif hex_num == 12 :
                seven_seg.next = 0b1000110
            elif hex_num == 13 :
                seven_seg.next = 0b0100001
            elif hex_num == 14 :
                seven_seg.next = 0b0000110
            else :
            # elif hex_num == 15 :
                seven_seg.next = 0b0001110
    
        return logic
    
    # instantiate hex_to_seven_seg with new port names
    @block
    def hex_to_seven_seg_test(SW, HEX0):
        hex_to_seven_seg_inst = hex_to_seven_seg(SW, HEX0)
        return hex_to_seven_seg_inst
    
    # instantiate hex_to_seven_seg_test
    def main():
        hex_num = Signal(intbv(0)[4:0])
        seven_seg = Signal(intbv(0)[7:0])
    
        hex_ss_v = hex_to_seven_seg_test(hex_num, seven_seg)
        hex_ss_v.convert(hdl="Verilog", initial_values=True)
    
    
    if __name__ == '__main__':
        main()
    
  • Below is the resultant Verilog code.

    Note

    • Note that, the if-else statement of Python code is automatically mapped into case-statement in the Verilog code.
    • Load this code to FPGA board and change the SW pattern and see the corresponding numbers on LEDG and seven-segment-display device.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    // File: hex_to_seven_seg_test.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 14:28:15 2017
    
    
    `timescale 1ns/10ps
    
    module hex_to_seven_seg_test (
        SW,
        HEX0
    );
    
    
    input [3:0] SW;
    output [6:0] HEX0;
    reg [6:0] HEX0;
    
    
    
    
    always @(SW) begin: HEX_TO_SEVEN_SEG_TEST_HEX_TO_SEVEN_SEG_1_LOGIC
        case (SW)
            'h0: begin
                HEX0 <= 64;
            end
            'h1: begin
                HEX0 <= 121;
            end
            'h2: begin
                HEX0 <= 36;
            end
            'h3: begin
                HEX0 <= 48;
            end
            'h4: begin
                HEX0 <= 25;
            end
            'h5: begin
                HEX0 <= 18;
            end
            'h6: begin
                HEX0 <= 2;
            end
            'h7: begin
                HEX0 <= 120;
            end
            'h8: begin
                HEX0 <= 0;
            end
            'h9: begin
                HEX0 <= 16;
            end
            'ha: begin
                HEX0 <= 8;
            end
            'hb: begin
                HEX0 <= 3;
            end
            'hc: begin
                HEX0 <= 70;
            end
            'hd: begin
                HEX0 <= 33;
            end
            'he: begin
                HEX0 <= 6;
            end
            default: begin
                HEX0 <= 14;
            end
        endcase
    end
    
    endmodule
    

2.6. Visual verification of Mod-m counter

In this section, we will connect all the previous designs i.e. mod_m_counter, hex_to_seven_seg and clock_tick to count the number upto ‘M’ and display the result on LEDs and seven-segment-display device.

  • Below is the top level entity which connects all the designs together and convert it into Verilog code,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    # mod_m_counter_visual_test.py
    # result is same as th modMCounter_VisualTest.v of the Verilog tutorial
    
    from myhdl import *
    
    from mod_m_counter import mod_m_counter
    from clock_tick import clock_tick
    from hex_to_seven_seg import hex_to_seven_seg_test
    
    @block
    def mod_m_counter_visual_test(CLOCK_50, reset_n, HEX0, LEDG, M, N):
        count = Signal(intbv(0)[N:0])
        clk_pulse = Signal(bool(0))
        complete_tick = Signal(bool(0))
    
        # reduced clock rate
        clock_tick_inst = clock_tick(CLOCK_50, reset_n, clk_pulse, 50000000, 29)
    
        # reduce clock rate is applied to mod_m_counter
        mod_m_counter_inst = mod_m_counter(clk_pulse, reset_n,
                complete_tick, count, M, N)
    
        # count is send for conversion
        hex_to_seven_seg_test_inst = hex_to_seven_seg_test(count, HEX0)
    
        # send count to LEDG
        @always_comb
        def led_logic():
            LEDG.next = count
    
        return instances()
    
    def main():
        CLOCK_50 = Signal(bool(0))
        reset_n = Signal(bool(0))
        HEX0 = Signal(intbv(0)[7:0])
        LEDG = Signal(intbv(0)[4:0])
        M = 12
        N = 4
    
        mod_m_counter_inst = mod_m_counter_visual_test(CLOCK_50, reset_n, HEX0, LEDG, M, N)
        mod_m_counter_inst.convert(hdl="Verilog", initial_values=True)
    
    if __name__ == '__main__':
        main()
    
  • Below is the resultant Verilog code. Load this code to FPGA board and see the counting on the seven-segment-display device and LEDs.

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    // File: mod_m_counter_visual_test.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 15:04:14 2017
    
    
    `timescale 1ns/10ps
    
    module mod_m_counter_visual_test (
        CLOCK_50,
        reset_n,
        HEX0,
        LEDG
    );
    
    
    input CLOCK_50;
    input reset_n;
    output [6:0] HEX0;
    reg [6:0] HEX0;
    output [3:0] LEDG;
    wire [3:0] LEDG;
    
    reg complete_tick = 0;
    reg clk_pulse = 0;
    wire [3:0] count;
    wire [28:0] clock_tick_1_count;
    reg [28:0] clock_tick_1_mod_m_counter_1_count_reg = 0;
    reg [28:0] clock_tick_1_mod_m_counter_1_count_next = 0;
    reg [3:0] mod_m_counter_2_count_reg = 0;
    reg [3:0] mod_m_counter_2_count_next = 0;
    
    
    
    
    assign clock_tick_1_count = clock_tick_1_mod_m_counter_1_count_reg;
    
    
    always @(clock_tick_1_mod_m_counter_1_count_reg) begin: MOD_M_COUNTER_VISUAL_TEST_CLOCK_TICK_1_MOD_M_COUNTER_1_LOGIC_NEXT
        if (($signed({1'b0, clock_tick_1_mod_m_counter_1_count_reg}) == (50000000 - 1))) begin
            clock_tick_1_mod_m_counter_1_count_next = 0;
            clk_pulse = 1;
        end
        else begin
            clock_tick_1_mod_m_counter_1_count_next = (clock_tick_1_mod_m_counter_1_count_reg + 1);
            clk_pulse = 0;
        end
    end
    
    
    always @(posedge CLOCK_50, negedge reset_n) begin: MOD_M_COUNTER_VISUAL_TEST_CLOCK_TICK_1_MOD_M_COUNTER_1_LOGIC_REG
        if ((reset_n == 0)) begin
            clock_tick_1_mod_m_counter_1_count_reg <= 0;
        end
        else begin
            clock_tick_1_mod_m_counter_1_count_reg <= clock_tick_1_mod_m_counter_1_count_next;
        end
    end
    
    
    
    assign count = mod_m_counter_2_count_reg;
    
    
    always @(mod_m_counter_2_count_reg) begin: MOD_M_COUNTER_VISUAL_TEST_MOD_M_COUNTER_2_LOGIC_NEXT
        if (($signed({1'b0, mod_m_counter_2_count_reg}) == (12 - 1))) begin
            mod_m_counter_2_count_next = 0;
            complete_tick = 1;
        end
        else begin
            mod_m_counter_2_count_next = (mod_m_counter_2_count_reg + 1);
            complete_tick = 0;
        end
    end
    
    
    always @(posedge clk_pulse, negedge reset_n) begin: MOD_M_COUNTER_VISUAL_TEST_MOD_M_COUNTER_2_LOGIC_REG
        if ((reset_n == 0)) begin
            mod_m_counter_2_count_reg <= 0;
        end
        else begin
            mod_m_counter_2_count_reg <= mod_m_counter_2_count_next;
        end
    end
    
    
    always @(count) begin: MOD_M_COUNTER_VISUAL_TEST_HEX_TO_SEVEN_SEG_TEST_1_HEX_TO_SEVEN_SEG_1_LOGIC
        case (count)
            'h0: begin
                HEX0 <= 64;
            end
            'h1: begin
                HEX0 <= 121;
            end
            'h2: begin
                HEX0 <= 36;
            end
            'h3: begin
                HEX0 <= 48;
            end
            'h4: begin
                HEX0 <= 25;
            end
            'h5: begin
                HEX0 <= 18;
            end
            'h6: begin
                HEX0 <= 2;
            end
            'h7: begin
                HEX0 <= 120;
            end
            'h8: begin
                HEX0 <= 0;
            end
            'h9: begin
                HEX0 <= 16;
            end
            'ha: begin
                HEX0 <= 8;
            end
            'hb: begin
                HEX0 <= 3;
            end
            'hc: begin
                HEX0 <= 70;
            end
            'hd: begin
                HEX0 <= 33;
            end
            'he: begin
                HEX0 <= 6;
            end
            default: begin
                HEX0 <= 14;
            end
        endcase
    end
    
    
    
    assign LEDG = count;
    
    endmodule
    

2.7. Open port in MyHDL

  • We can use the ‘None’ keyword to avoid connection for the unused port. For this, we need to modify the code for the output signal, which is going to be used as ‘optional connection’. In the below code, Section 2.6 is reimplemented.

  • First modify the ‘mod_m_counter.py’, in which the output signal ‘count’ and ‘complete_tick’ can be the optional connections; therefore these two signals are written inside the ‘if’ statement with ‘None’ keyword,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    # mod_m_counter.py
    
    from myhdl import *
    
    @block
    def mod_m_counter(clk, reset_n, complete_tick, count, M, N):
        """ M = max count
            N = minimum bits required to represent M
        """
    
        count_reg = Signal(intbv(0)[N:0])
        count_next = Signal(intbv(0)[N:0])
    
        @always(clk.posedge, reset_n.negedge)
        def logic_reg():
            if reset_n == 0 :
                count_reg.next = 0
            else :
                count_reg.next = count_next
    
        @always_comb
        def logic_next():
            if count_reg == M-1 :
                count_next.next = 0
            else :
                count_next.next = count_reg + 1
    
    
        # optional complete_tick
        if complete_tick is not None:
            @always_comb
            def complete_tick_logic():
                if count_reg == M-1 :
                    complete_tick.next = 1
                else :
                    complete_tick.next = 0
    
        # optional count
        if count is not None:
            @always_comb
            def out_val():
                count.next = count_reg
    
        return instances()  # return all instances
    
    
    def main():
        N = 3
        M = 5
    
        clk = Signal(bool(0))
        reset_n = Signal(bool(0))
        complete_tick = Signal(bool(0))
        count = Signal(intbv(0)[N:0])
    
        mod_m_counter_v = mod_m_counter(clk, reset_n, complete_tick, count, M, N)
        mod_m_counter_v.convert(hdl="Verilog", initial_values=True)
    
    if __name__ == '__main__':
        main()
    
  • Next, modify the ‘clock_tick.py’, which is instantiating the ‘mod_m_counter.py’, but not using the ‘count’ port. Hence keep if open (using None) as below,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # clock_tick.py
    
    from myhdl import *
    
    from mod_m_counter import mod_m_counter
    
    @block
    def clock_tick(clk, reset_n, clk_pulse, M, N):
        # count = Signal(intbv(0)[N:0])
        # mod_m_counter_inst = mod_m_counter(clk, reset_n, clk_pulse, count, M, N)
    
        # None for count-port
        mod_m_counter_inst = mod_m_counter(clk, reset_n, clk_pulse, None, M, N)
        return mod_m_counter_inst
    
    # instantiate clock_tick
    def main():
        clk = Signal(bool(0))
        reset_n = Signal(bool(0))
        clk_pulse = Signal(bool(0))
        M = 5000000 # 0.1 sec
        N = 29
    
        clock_tick_inst = clock_tick(clk, reset_n, clk_pulse, M, N)
        clock_tick_inst.convert(hdl="Verilog", initial_values=True)
    
    if __name__ == '__main__':
        main()
    
  • Lastly, update the ‘mod_m_counter_visual_test.py’, which is instantiating the ‘mod_m_counter.py’ but not using the port ‘complete_tick’,

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    # mod_m_counter_visual_test.py
    
    from myhdl import *
    
    from mod_m_counter import mod_m_counter
    from clock_tick import clock_tick
    from hex_to_seven_seg import hex_to_seven_seg_test
    
    @block
    def mod_m_counter_visual_test(CLOCK_50, reset_n, HEX0, LEDG, M, N):
        count = Signal(intbv(0)[N:0])
        clk_pulse = Signal(bool(0))
        # complete_tick = Signal(bool(0))
    
        # reduced clock rate
        clock_tick_inst = clock_tick(CLOCK_50, reset_n, clk_pulse, 50000000, 29)
    
        # reduce clock rate is applied to mod_m_counter
        # mod_m_counter_inst = mod_m_counter(clk_pulse, reset_n,
                        # complete_tick, count, M, N)
        mod_m_counter_inst = mod_m_counter(clk_pulse, reset_n, None, count, M, N)
    
        # count is send for conversion
        hex_to_seven_seg_test_inst = hex_to_seven_seg_test(count, HEX0)
    
        # send count to LEDG
        @always_comb
        def led_logic():
            LEDG.next = count
        return instances()
    
    def main():
        CLOCK_50 = Signal(bool(0))
        reset_n = Signal(bool(0))
        HEX0 = Signal(intbv(0)[7:0])
        LEDG = Signal(intbv(0)[4:0])
        M = 12
        N = 4
    
        mod_m_counter_inst = mod_m_counter_visual_test(CLOCK_50, reset_n, HEX0, LEDG, M, N)
        mod_m_counter_inst.convert(hdl="Verilog", initial_values=True)
    
    if __name__ == '__main__':
        main()
    
  • Now run the ‘mod_m_counter_visual_test.py’ and following code will be generated without warning. Load this design on the FPGA board to see the counting on the seven-segment-display device.

    // File: mod_m_counter_visual_test.v
    // Generated by MyHDL 1.0dev
    // Date: Fri Oct 13 15:16:53 2017
    
    
    `timescale 1ns/10ps
    
    module mod_m_counter_visual_test (
        CLOCK_50,
        reset_n,
        HEX0,
        LEDG
    );
    
    
    input CLOCK_50;
    input reset_n;
    output [6:0] HEX0;
    reg [6:0] HEX0;
    output [3:0] LEDG;
    wire [3:0] LEDG;
    
    reg clk_pulse = 0;
    wire [3:0] count;
    reg [28:0] clock_tick_1_mod_m_counter_1_count_reg = 0;
    reg [28:0] clock_tick_1_mod_m_counter_1_count_next = 0;
    reg [3:0] mod_m_counter_2_count_reg = 0;
    reg [3:0] mod_m_counter_2_count_next = 0;
    
    
    
    always @(posedge CLOCK_50, negedge reset_n) begin: MOD_M_COUNTER_VISUAL_TEST_CLOCK_TICK_1_MOD_M_COUNTER_1_LOGIC_REG
        if ((reset_n == 0)) begin
            clock_tick_1_mod_m_counter_1_count_reg <= 0;
        end
        else begin
            clock_tick_1_mod_m_counter_1_count_reg <= clock_tick_1_mod_m_counter_1_count_next;
        end
    end
    
    
    always @(clock_tick_1_mod_m_counter_1_count_reg) begin: MOD_M_COUNTER_VISUAL_TEST_CLOCK_TICK_1_MOD_M_COUNTER_1_LOGIC_NEXT
        if (($signed({1'b0, clock_tick_1_mod_m_counter_1_count_reg}) == (50000000 - 1))) begin
            clock_tick_1_mod_m_counter_1_count_next = 0;
        end
        else begin
            clock_tick_1_mod_m_counter_1_count_next = (clock_tick_1_mod_m_counter_1_count_reg + 1);
        end
    end
    
    
    always @(clock_tick_1_mod_m_counter_1_count_reg) begin: MOD_M_COUNTER_VISUAL_TEST_CLOCK_TICK_1_MOD_M_COUNTER_1_COMPLETE_TICK_LOGIC
        if (($signed({1'b0, clock_tick_1_mod_m_counter_1_count_reg}) == (50000000 - 1))) begin
            clk_pulse = 1;
        end
        else begin
            clk_pulse = 0;
        end
    end
    
    
    always @(posedge clk_pulse, negedge reset_n) begin: MOD_M_COUNTER_VISUAL_TEST_MOD_M_COUNTER_2_LOGIC_REG
        if ((reset_n == 0)) begin
            mod_m_counter_2_count_reg <= 0;
        end
        else begin
            mod_m_counter_2_count_reg <= mod_m_counter_2_count_next;
        end
    end
    
    
    always @(mod_m_counter_2_count_reg) begin: MOD_M_COUNTER_VISUAL_TEST_MOD_M_COUNTER_2_LOGIC_NEXT
        if (($signed({1'b0, mod_m_counter_2_count_reg}) == (12 - 1))) begin
            mod_m_counter_2_count_next = 0;
        end
        else begin
            mod_m_counter_2_count_next = (mod_m_counter_2_count_reg + 1);
        end
    end
    
    
    
    assign count = mod_m_counter_2_count_reg;
    
    
    always @(count) begin: MOD_M_COUNTER_VISUAL_TEST_HEX_TO_SEVEN_SEG_TEST_1_HEX_TO_SEVEN_SEG_1_LOGIC
        case (count)
            'h0: begin
                HEX0 <= 64;
            end
            'h1: begin
                HEX0 <= 121;
            end
            'h2: begin
                HEX0 <= 36;
            end
            'h3: begin
                HEX0 <= 48;
            end
            'h4: begin
                HEX0 <= 25;
            end
            'h5: begin
                HEX0 <= 18;
            end
            'h6: begin
                HEX0 <= 2;
            end
            'h7: begin
                HEX0 <= 120;
            end
            'h8: begin
                HEX0 <= 0;
            end
            'h9: begin
                HEX0 <= 16;
            end
            'ha: begin
                HEX0 <= 8;
            end
            'hb: begin
                HEX0 <= 3;
            end
            'hc: begin
                HEX0 <= 70;
            end
            'hd: begin
                HEX0 <= 33;
            end
            'he: begin
                HEX0 <= 6;
            end
            default: begin
                HEX0 <= 14;
            end
        endcase
    end
    
    assign LEDG = count;
    
    endmodule
    

2.8. Conclusion

In this chapter, we learn to reduce the clock rate to visualize the outputs on the display devices. The reduced clock rate is used to display the counting on the seven-segment-display device and LEDs. Further, the structure modeling is used here, which makes the code more manageable and reusable.