Arbiter Seçim Analizleri

Aşağıda farklı arbiter tasarımlarının sentez çıktıları karşılaştırılmaktadır. Sentez DCNXT üzerinden yapılmıştır.

Üzerine çok fazla düşülmediği için aşağıdaki sonuçlar çıkmış olabilir, backend’ konusunda daha tecrübeli biri daha farklı sonuçlar elde edebilir.

A- IO Register

1- Fonksiyon Arbiter Tasarımı

module arbiter_func
#(parameter WIDTH = 8)(
    input logic clk,
    input  logic [WIDTH-1:0] request,
    output logic [WIDTH-1:0] respond
    );

    function automatic logic [WIDTH-1:0] priority_encoder(input logic [WIDTH-1:0] req);
        integer i;
        begin
            priority_encoder = {WIDTH{1'b0}};
            for (i = WIDTH-1; i >= 0; i = i - 1) begin
                if (req[i]) begin
                    priority_encoder = (1 << i);
                    break;
                end
            end
        end
    endfunction

    always_comb begin
        respond_holder = priority_encoder(request_holder);
    end
    
    logic [WIDTH-1 : 0]request_holder, respond_holder;
    always@(posedge clk) begin
        request_holder <= request;
        respond <= respond_holder;
    end
endmodule

Timing Report:

data required time 1.83
data arrival time -0.54
slack (MET) 1.28

Area Report:

Combinational area: 30.751425
Buf/Inv area: 6.353600
Noncombinational area: 136.221182
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (Wire load has zero net area)
Total cell area: 166.972607

2- Case Arbiter Tasarımı

module case_arbiter
    #(parameter WIDTH = 8)(
    input clk,
    input  logic [WIDTH-1:0] request,
    output logic [WIDTH-1:0] respond
    );
logic [WIDTH-1 : 0]request_holder, respond_holder;
    always@(posedge clk) begin
        request_holder <= request;
        respond <= respond_holder;
    end

always_comb begin
                casez (request_holder[WIDTH-1:0])
                    8'b????_???1 : respond_holder = 8'b0000_0001;
                    8'b????_??10 : respond_holder = 8'b0000_0010;
                    8'b????_?100 : respond_holder = 8'b0000_0100;
                    8'b????_1000 : respond_holder = 8'b0000_1000;
                    8'b???1_0000 : respond_holder = 8'b0001_0000;
                    8'b??10_0000 : respond_holder = 8'b0010_0000;
                    8'b?100_0000 : respond_holder = 8'b0100_0000;
                    8'b1000_0000 : respond_holder = 8'b1000_0000;
                    8'b0000_0000 : respond_holder = 8'b0000_0000;
                    default      : respond_holder = 8'b0000_0000;
                endcase
            end

endmodule

Timing Report:

data required time 1.83
data arrival time -0.54
slack (MET) 1.29

Area Report:

Combinational area: 30.751425
Buf/Inv area: 6.353600
Noncombinational area: 136.221182
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (Wire load has zero net area)

Total cell area: 166.972607

3- Assign Arbiter Tasarımı

module assign_arbiter
    #(parameter WIDTH = 8)(
    input clk,
    input  logic [WIDTH-1:0] request,
    output logic [WIDTH-1:0] respond
    );
    
    logic [WIDTH-1:0]   higher_pri_reqs;
    logic [WIDTH-1 : 0]request_holder, respond_holder;
    always@(posedge clk) begin
        request_holder <= request;
        respond <= respond_holder;
    end

    assign higher_pri_reqs[WIDTH-1:1] = higher_pri_reqs[WIDTH-2:0] | request_holder[WIDTH-2:0];
    assign higher_pri_reqs[0] = 1'b0;
    assign respond_holder[WIDTH-1:0] = request_holder[WIDTH-1:0] & ~higher_pri_reqs[WIDTH-1:0];
    
    
endmodule

Timing Report:

data required time 1.83
data arrival time -0.54
slack (MET) 1.29

Area Report:

Combinational area: 30.751425
Buf/Inv area: 6.353600
Noncombinational area: 136.221182
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (Wire load has zero net area)
Total cell area: 166.972607

Sonuç olarak hepsinde aynı devre çıktı, assign ile yapılan tasarımda combinational olarak kendisine geri bağlama yapıldığını gördüğümde linter’dan geçmeyeceğini düşünmüştüm ancak tahminlerimde yanıldım ve görüldüğü üzere sentez sonucu diğer tasarımlarla birebir aynı çıktı.

Önceki analizde Clock ile beraber hesaplanması için başına ve sonuna register eklemiştim. Şimdiki analizde sadece combinational sonuçları elde ettim. Denediğim dizayn türleri aralasında bariz bir fark bulunmuyor. Timing ve alan konusunda önde olan lzc tasarımını kullanmak mantıklı duruyor. Case ile yapılan da kullanılabilir aynı şekilde sentezlemiş zaten. Zaman kısıtını değiştirerek de denemelerde bulundum en mantıklısı lzc kullanmak gibi görünüyor. Timing denemelerinde ucu ucuna da olsa en düşük değeri lzc gördü.

B- Full Combinational

Fonksiyon ile yapılan arbiter sonuçları:

module arbiter_func
#(parameter WIDTH = 8)(
    input  logic [WIDTH-1:0] request,
    output logic [WIDTH-1:0] respond
    );
    function automatic logic [WIDTH-1:0] priority_encoder(input logic [WIDTH-1:0] req);
        integer i;
        begin
            priority_encoder = {WIDTH{1'b0}};
            for (i = WIDTH-1; i >= 0; i = i - 1) begin
                if (req[i]) begin
                    priority_encoder = (1 << i);
                    break;
                end
            end
        end
    endfunction

    always_comb begin
        respond = priority_encoder(request);
    end
endmodule  

Timing Report:

data arrival time 0.34

Area Report:

Combinational area: 30.751425
Buf/Inv area: 6.353600
Noncombinational area: 0.000000
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (Wire load has zero net area)

Total cell area: 30.751425

Case ile yapılan arbiter sonuçları:

module case_arbiter
    #(parameter WIDTH = 8)(
    input  logic [WIDTH-1:0] request,
    output logic [WIDTH-1:0] respond
    );

always_comb begin
                casez (request[WIDTH-1:0])
                    8'b????_???1 : respond = 8'b0000_0001;
                    8'b????_??10 : respond = 8'b0000_0010;
                    8'b????_?100 : respond = 8'b0000_0100;
                    8'b????_1000 : respond = 8'b0000_1000;
                    8'b???1_0000 : respond = 8'b0001_0000;
                    8'b??10_0000 : respond = 8'b0010_0000;
                    8'b?100_0000 : respond = 8'b0100_0000;
                    8'b1000_0000 : respond = 8'b1000_0000;
                    8'b0000_0000 : respond = 8'b0000_0000;
                    default      : respond = 8'b0000_0000;
                endcase
            end
endmodule  

Timing Report:

data arrival time 0.29

Area Report:

Combinational area: 29.734848
Buf/Inv area: 6.353600
Noncombinational area: 0.000000
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (Wire load has zero net area)

Total cell area: 29.734848

Assign ile yapılan arbiter sonuçları:

module assign_arbiter
    #(parameter WIDTH = 8)(
    input  logic [WIDTH-1:0] request,
    output logic [WIDTH-1:0] respond
    );
    
    logic [WIDTH-1:0]   higher_pri_reqs;
    
    assign higher_pri_reqs[WIDTH-1:1] = higher_pri_reqs[WIDTH-2:0] | request[WIDTH-2:0];
    assign higher_pri_reqs[0] = 1'b0;
    assign respond[WIDTH-1:0] = request[WIDTH-1:0] & ~higher_pri_reqs[WIDTH-1:0];  
endmodule  

Timing Report:

data arrival time 0.34

Area Report:

Combinational area: 30.751425
Buf/Inv area: 6.353600
Noncombinational area: 0.000000
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (Wire load has zero net area)

Total cell area: 30.751425


Design Comparison

Design Metrics

LZC de arbitration için kullanılan bir modüldür. Denediğim lzc tasarımı bana ait olmadığı için burada paylaşamıyorum.

Metric LZC CASE ASSIGN FUNC
Data Arrival Time 0.29 0.29 0.34 0.34
Number of Ports 16 16 16 16
Number of Nets 23 23 24 24
Number of Cells 15 15 16 16
Number of Combinational Cells 15 15 16 16
Number of Buf/inv 5 5 5 5
Number of References 6 6 7 7
Combinational Area 29.734848 29.734848 30.751425 30.751425
Buf/Inv Area 6.3536 6.3536 6.3536 6.3536
Total Cell Area 29.734848 29.734848 30.751425 30.751425