6.6.3 A hierarchical design

The Verilog converter can handle designs with an arbitrarily deep hierarchy.

For example, suppose we want to design an incrementer with Gray code output. Using the designs from previous sections, we can proceed as follows:

ACTIVE_LOW, INACTIVE_HIGH = 0, 1

def GrayInc(graycnt, enable, clock, reset, width):
    
    bincnt = Signal(intbv(0)[width:])
    
    inc_1 = inc(bincnt, enable, clock, reset, n=2**width)
    bin2gray_1 = bin2gray(B=bincnt, G=graycnt, width=width)
    
    return inc_1, bin2gray_1

According to Gray code properties, only a single bit will change in consecutive values. However, as the bin2gray module is combinatorial, the output bits may have transient glitches, which may not be desirable. To solve this, let's create an additional level of hierarchy and add an output register to the design. (This will create an additional latency of a clock cycle, which may not be acceptable, but we will ignore that here.)

def GrayIncReg(graycnt, enable, clock, reset, width):
    
    graycnt_comb = Signal(intbv(0)[width:])
    
    gray_inc_1 = GrayInc(graycnt_comb, enable, clock, reset, width)

    @always(clock.posedge)
    def reg_1():
        graycnt.next = graycnt_comb
    
    return gray_inc_1, reg_1

We can convert this hierarchical design as before:

width = 8
graycnt = Signal(intbv()[width:])
enable, clock, reset = [Signal(bool()) for i in range(3)]

gray_inc_reg_1 = toVerilog(GrayIncReg, graycnt, enable, clock, reset, width)

The Verilog output code looks as follows:

module GrayIncReg (
    graycnt,
    enable,
    clock,
    reset
);
 
output [7:0] graycnt;
reg [7:0] graycnt;
input enable;
input clock;
input reset;
 
reg [7:0] graycnt_comb;
reg [7:0] _gray_inc_1_bincnt;
 
 
always @(posedge clock or negedge reset) begin: _GrayIncReg_gray_inc_1_inc_1_incProcess
    if ((reset == 0)) begin
        _gray_inc_1_bincnt <= 0;
    end
    else begin
        if (enable) begin
            _gray_inc_1_bincnt <= ((_gray_inc_1_bincnt + 1) % 256);
        end
    end
end
 
always @(_gray_inc_1_bincnt) begin: _GrayIncReg_gray_inc_1_bin2gray_1_logic
    integer i;
    reg [9-1:0] Bext;
    Bext = 9'h0;
    Bext = _gray_inc_1_bincnt;
    for (i=0; i<8; i=i+1) begin
        graycnt_comb[i] <= (Bext[(i + 1)] ^ Bext[i]);
    end
end
 
always @(posedge clock) begin: _GrayIncReg_reg_1
    graycnt <= graycnt_comb;
end
 
endmodule

Note that the output is a flat ``net list of blocks'', and that hierarchical signal names are generated as necessary.

About this document