디지털 IC 프런트 엔드 연구 노트: 중재 폴링(4)

관련 기사

디지털 IC 프런트 엔드 연구 노트: LSFR(Linear Feedback Shift Register)

디지털 IC 프런트 엔드 연구 노트: 교차 클록 도메인 신호 동기화

디지털 IC 프런트 엔드 연구 노트: 신호 동기화 및 에지 감지

디지털 IC 프런트 엔드 연구 노트: 래치 래치 합성

디지털 IC 프런트 엔드 연구 노트: 그레이 코드(Verilog에서 구현한 이진 그레이 코드 변환기 포함)

디지털 IC 프런트 엔드 연구 노트: FIFO의 Verilog 구현(1)

디지털 IC 프런트 엔드 연구 노트: FIFO의 Verilog 구현(2)

디지털 IC 프런트 엔드 연구 노트: 중재 폴링(1)

디지털 IC 프런트 엔드 연구 노트: 중재 폴링(2)

디지털 IC 프런트 엔드 연구 노트: 중재 폴링(3)

디지털 IC 프런트 엔드 연구 노트: 중재 폴링(5)

디지털 IC 프런트 엔드 연구 노트: 중재 폴링(6)

디지털 IC 프런트엔드 연구 노트: LRU(최소 최근 사용) 알고리즘


6. 가중치가 있는 라운드 로빈(1부)

        가중 라운드 로빈(WRR) 방식은 기존의 라운드 로빈 방식과 유사하지만 차이점은 사용자마다 권한을 얻을 기회가 다르다는 것입니다. 즉, 사용자마다 가중치가 다르고 가중치가 높은 사용자가 라이선스 기회를 얻습니다 더. 가중치를 할당하는 방법에는 여러 가지가 있으며 그 중 두 가지를 여기에서 소개합니다. 첫 번째 방법은 폴링 주기 내에서 사용자가 부여(권한 부여)될 수 있는 횟수를 결정하는 변수를 각 사용자에게 할당하는 것입니다. 이 변수는 소프트웨어 프로그래밍을 통해 수정할 수 있으므로 이에 따라 폴링 가중치를 조정할 수 있습니다. 예를 들어 세 명의 사용자가 있고 agent0의 가중치는 3, agent1의 가중치는 2, agent2의 가중치는 1입니다. 하나의 폴링 주기에서 agent0은 최대 3번, agent1은 2번, agent2는 1번의 권한을 얻을 수 있습니다. 폴링 주기 시작 시 변수 N_agnt0, N_agnt1, N_agnt2는 각각 3, 2, 1로 미리 설정되어 있으며 각 폴링 후 해당 변수 값은 1씩 감소합니다. reset.은 기본 초기값입니다. 모든 사용자가 동시에 요청하는 경우 중재자는 다음 두 가지 방법 중 하나로 권한을 부여합니다.

        1. 사용자는 지속적으로 라이선스를 취득할 수 있으며, 취득한 라이선스의 개수는 기 설정된 가중치에 따라 결정됩니다. 모든 사용자가 동시에 요청하는 경우 권한 순서는 다음과 같습니다.

                (A,A,A),(B,B),C, (A,A,A),(B,B),C ......

        2. 권한 기회가 있는 모든 사용자 사이에서 공정한 폴링을 수행합니다.순환에서 서로 다른 사용자가 획득한 총 권한 기회는 미리 설정된 가중치 값에 의해 결정됩니다. 모든 요청이 동시에 발생하는 경우 승인 시퀀스는 다음과 같습니다.

                A,B,C,A,B,A B,C,A,B,A,A ......

        두 번째 방식에서는 소프트웨어 프로그래밍 가능 타이머를 사용하여 가중치를 할당합니다. 중재 주기가 시작될 때 타이머 값이 로드됩니다. 사용자가 권한을 얻으면 타이머는 만료될 때까지 카운트를 시작하며, 이때 권한이 있는 사용자가 작업을 완료하지 않은 경우 중재자는 현재 사용자의 권한을 중지하고 우선 순위에 따라 다음 사용자를 폴링합니다.

        다음은 WRR 폴링 방식을 이용한 Verilog 코드와 시뮬레이션 결과로 첫 번째 방법 중 첫 번째 권한 방법을 사용하며 순서는 A, A, A, B, B, C....

module arbiter_wrr(clk,resetb,req_vec,
                   req_vec_wt_0,
                   req_vec_wt_1,
                   req_vec_wt_2,
                   req_n_valid,
                   end_access_vec,
                   gnt_vec);
    input clk;
    input resetb;
    input [2:0] req_vec;
    input [3:0] req_vec_wt_0;
    input [3:0] req_vec_wt_1;
    input [3:0] req_vec_wt_2;
    input req_n_valid;
    input [2:0] end_access_vec;
    output reg [2:0] gnt_vec;
    
    reg [2:0] arbiter_state,arbiter_state_nxt;
    reg [2:0] gnt_vec_nxt;
    reg [3:0] count_req_vec [2:0];
    reg [3:0] count_req_vec_nxt [2:0];
    wire [3:0] req_vec_wt [2:0];
    reg [3:0] req_vec_wt_stored [2:0];
    reg [3:0] req_vec_wt_stored_nxt [2:0];
    wire [2:0] cnt_reqdone_vec;
    
    parameter IDLE = 3'b001;
    parameter ARM_VALUE = 3'b010;
    parameter END_ACCESS = 3'b100;
    

    assign req_vec_wt[0] = req_vec_wt_0;
    assign req_vec_wt[1] = req_vec_wt_1;
    assign req_vec_wt[2] = req_vec_wt_2;    

    always@(*) begin
        arbiter_state_nxt = arbiter_state;
        gnt_vec_nxt = gnt_vec;
        count_req_vec_nxt[0] = count_req_vec[0];
        count_req_vec_nxt[1] = count_req_vec[1];
        count_req_vec_nxt[2] = count_req_vec[2];
        req_vec_wt_stored_nxt[0] = req_vec_wt_stored[0];
        req_vec_wt_stored_nxt[1] = req_vec_wt_stored[1];
        req_vec_wt_stored_nxt[2] = req_vec_wt_stored[2];
        case(arbiter_state)
            IDLE:begin
                if(req_n_valid)begin
                    arbiter_state_nxt = ARM_VALUE;
                    count_req_vec_nxt[0] = req_vec_wt[0];
                    count_req_vec_nxt[1] = req_vec_wt[1];
                    count_req_vec_nxt[2] = req_vec_wt[2];
                    req_vec_wt_stored_nxt[0] = req_vec_wt[0];
                    req_vec_wt_stored_nxt[1] = req_vec_wt[1];
                    req_vec_wt_stored_nxt[2] = req_vec_wt[2];
                end
            end
            ARM_VALUE:begin
                if((gnt_vec == 0) ||
                   (end_access_vec[0] & gnt_vec[0]) ||
                   (end_access_vec[1] & gnt_vec[1]) ||
                   (end_access_vec[2] & gnt_vec[2]))
                    begin
                        if(req_vec[0] & !cnt_reqdone_vec[0]) begin
                            arbiter_state_nxt = END_ACCESS;
                            gnt_vec_nxt = 3'b001;
                            count_req_vec_nxt[0] = count_req_vec[0] - 1;
                        end
                        else if(req_vec[1] & !cnt_reqdone_vec[0]) begin
                            arbiter_state_nxt = END_ACCESS;
                            gnt_vec_nxt = 3'b010;
                            count_req_vec_nxt[1] = count_req_vec[1] - 1;
                        end
                        else if(req_vec[2] & !cnt_reqdone_vec[1]) begin
                            arbiter_state_nxt = END_ACCESS;
                            gnt_vec_nxt = 3'b100;
                            count_req_vec_nxt[2] = count_req_vec[2] - 1;
                        end
                        else begin
                            count_req_vec_nxt[0] = req_vec_wt_stored[0];
                            count_req_vec_nxt[1] = req_vec_wt_stored[1];
                            count_req_vec_nxt[2] = req_vec_wt_stored[2];
                            gnt_vec_nxt = 3'b0;
                        end
                    end
            end
            END_ACCESS:if((end_access_vec[0] & gnt_vec[0]) ||
                          (end_access_vec[1] & gnt_vec[1]) ||
                          (end_access_vec[2] & gnt_vec[2]))
                        begin
                            arbiter_state_nxt = ARM_VALUE;
                            
                            if(req_vec[0] & !cnt_reqdone_vec[0]) begin
                                arbiter_state_nxt = END_ACCESS;
                                gnt_vec_nxt = 3'b001;
                            count_req_vec_nxt[0] = count_req_vec[0] - 1;
                            end
                            else if(req_vec[1] & !cnt_reqdone_vec[0]) begin
                                arbiter_state_nxt = END_ACCESS;
                                gnt_vec_nxt = 3'b010;
                                count_req_vec_nxt[1] = count_req_vec[1] - 1;
                            end
                            else if(req_vec[2] & !cnt_reqdone_vec[1]) begin
                                arbiter_state_nxt = END_ACCESS;
                                gnt_vec_nxt = 3'b100;
                                count_req_vec_nxt[2] = count_req_vec[2] - 1;
                            end
                            else begin
                                count_req_vec_nxt[0] = req_vec_wt_stored[0];
                                count_req_vec_nxt[1] = req_vec_wt_stored[1];
                                count_req_vec_nxt[2] = req_vec_wt_stored[2];
                                gnt_vec_nxt = 3'b0;
                            end
                        end
        endcase
    end

    assign cnt_reqdone_vec[0] = (count_req_vec[0] == 0);
    assign cnt_reqdone_vec[1] = (count_req_vec[1] == 0);
    assign cnt_reqdone_vec[2] = (count_req_vec[2] == 0);
    
    always@(posedge clk or negedge resetb) begin
        if(!resetb) begin
            arbiter_state <= IDLE;
            gnt_vec <= 0;
            count_req_vec[0] <= 0;    
            count_req_vec[1] <= 0; 
            count_req_vec[2] <= 0;
            req_vec_wt_stored[0] <= 0;
            req_vec_wt_stored[1] <= 0;
            req_vec_wt_stored[2] <= 0; 
        end 
        else begin
            arbiter_state <= arbiter_state_nxt;
            gnt_vec <= gnt_vec_nxt;
            count_req_vec[0] <= count_req_vec_nxt[0];    
            count_req_vec[1] <= count_req_vec_nxt[1]; 
            count_req_vec[2] <= count_req_vec_nxt[2];
            req_vec_wt_stored[0] <= req_vec_wt_stored_nxt[0];
            req_vec_wt_stored[1] <= req_vec_wt_stored_nxt[1];
            req_vec_wt_stored[2] <= req_vec_wt_stored_nxt[2]; 
        end
    end
endmodule

        코드에서 req_vec_wt_stored 신호는 각 사용자의 가중치 값을 저장하는 데 사용되고 count_req_vec는 사용자의 현재 남은 요청 수를 저장하는 데 사용됩니다. 참고: 공백 기간이 발생하면 모든 사용자의 남은 요청 수가 재설정됩니다.

위 내용은 "Verilog 고급 디지털 시스템 설계 기술 및 예제 분석"에서 가져온 것입니다.

추천

출처blog.csdn.net/weixin_45791458/article/details/131376265