안녕하세요.
지난 시간에 LRG Arbiter에 대해 학습하였습니다.
오늘은 LRG Arbiter에 사용되는 Round-Robin 알고리즘을 사용해
Arbiter를 Verilog로 설계해보겠습니다.
Least Recent Granted 기반의 아비터를 만들기 전에,
먼저 Fixed History 기반의 RR 아비터를 설계해볼게요.
(Fixed History는 제가 그냥 지어낸 것입니다..
가장 기본적인, 돌아가면서 Grant하는 RR 알고리즘으로 생각해주세요)
History queue에 이전의 결과를 저장하지 않고,
M0 -> M1 -> M2 -> M3 -> M0 -> M1 ... 순서대로 돌아가면서 처리해보겠습니다.
Verilog Code
DUT
module round_robin_arbiter(
input clk,
input rst_n,
input [3:0] REQ,
output reg [3:0] GNT
);
reg [2:0] present_state;
reg [2:0] next_state;
parameter [2:0] s_ideal = 3'b000;
parameter [2:0] s_0 = 3'b001;
parameter [2:0] s_1 = 3'b010;
parameter [2:0] s_2 = 3'b011;
parameter [2:0] s_3 = 3'b100;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
present_state <= s_ideal;
end
else begin
present_state <= next_state;
end
end
always @ (*) begin
case (present_state)
s_ideal: begin
if (REQ[0]) next_state = s_0;
else if (REQ[1]) next_state = s_1;
else if (REQ[2]) next_state = s_2;
else if (REQ[3]) next_state = s_3;
else next_state = s_ideal;
end
s_0: begin
if (REQ[1]) next_state = s_1;
else if (REQ[2]) next_state = s_2;
else if (REQ[3]) next_state = s_3;
else if (REQ[0]) next_state = s_0;
else next_state = s_ideal;
end
s_1: begin
if (REQ[2]) next_state = s_2;
else if (REQ[3]) next_state = s_3;
else if (REQ[0]) next_state = s_0;
else if (REQ[1]) next_state = s_1;
else next_state = s_ideal;
end
s_2: begin
if (REQ[3]) next_state = s_3;
else if (REQ[0]) next_state = s_0;
else if (REQ[1]) next_state = s_1;
else if (REQ[2]) next_state = s_2;
else next_state = s_ideal;
end
s_3: begin
if (REQ[0]) next_state = s_0;
else if (REQ[1]) next_state = s_1;
else if (REQ[2]) next_state = s_2;
else if (REQ[3]) next_state = s_3;
else next_state = s_ideal;
end
default: begin
if (REQ[0]) next_state = s_0;
else if (REQ[1]) next_state = s_1;
else if (REQ[2]) next_state = s_2;
else if (REQ[3]) next_state = s_3;
else next_state = s_ideal;
end
endcase
end
always @ (*) begin
case (present_state)
s_0: GNT = 4'b0001;
s_1: GNT = 4'b0010;
s_2: GNT = 4'b0100;
s_3: GNT = 4'b1000;
default: GNT = 4'b0000;
endcase
end
endmodule
always 문을 현재 상태에 따라 값을 선택하는 MUX로 구성하였습니다.
그리고 그 내부는 if문을 사용하였기 때문에 우선순위가 생겨서,
MUX 여러개가 나열된 상태로 합성됩니다.
순서는 M0 -> M1 -> M2 -> M3 -> M0... 으로 설정하였습니다.
Testbench
`timescale 1ns / 1ps
module tb_round_robin_arbiter();
reg clk;
reg rst_n;
reg [3:0] REQ;
wire [3:0] GNT;
round_robin_arbiter rra (.clk (clk),
.rst_n (rst_n),
.REQ (REQ),
.GNT (GNT) );
always #5 clk = ~clk;
initial begin
clk = 1'b0; rst_n = 1'b1; REQ = 4'b0000; #1
rst_n = 1'b0; #1
rst_n = 1'd1; #8
REQ = 4'b1111; #40
REQ = 4'b1011; #20
REQ = 4'b0101; #20
REQ = 4'b0011; #30
$finish;
end
initial begin
$dumpfile ("dump.vcd");
$dumpvars();
end
endmodule
Simulation
10ns에 1111, 즉 모든 Master가 REQ를 보냈습니다.
따라서 앞서 정한 순서대로 0001(M0), 0010(M1), 0100(M2), 1000(M3) 번째 Master에게 승인을 내줬습니다.
50ns에 1011이 다시 들어왔습니다.
역시 0001(M0), 0010(M1)을 GRANT 하였습니다.
이때 70ns에서 0101로 REQ이 바뀌었습니다.
Fixed Priority라면 0001(M0)부터 처리했겠죠?
하지만 Round-Robin 이기 때문에 시간 순서대로 승인합니다.
이전에 M1까지 승인했기 때문에 M0가 아닌 M2를 먼저 GRANT해주는 것을 볼 수 있습니다.
이후 M0를 GRANT 해주었습니다.
지금까지 시간 순서대로 GRANT하는 Round-Robin Arbiter에 대해 알아보았습니다.
이 방식을 사용하면 Master들에게 공평하게 기회를 줄 수 있지만
빨리 처리해야 하는 Master에게는 좋지 않을 수 있습니다.
다음 게시글에서는 장점을 높이고 단점을 줄인
Fixed Priority + LRG Round-Robin Arbiter를 설계해서 돌아오겠습니다!
'Digital Design > SoC' 카테고리의 다른 글
[SoC] Arbiter_Fixed Priority (Design with Verilog) (0) | 2023.04.30 |
---|---|
[SoC] Round-Robin Arbiter_LRG (Design with Verilog) (0) | 2023.04.26 |
[SoC] DMAC LRG Arbitration (ARM DMAC Reference Manual) (0) | 2023.04.24 |
[SoC] Timing Violation (Setup/Hold/Skew/Jitter/해결법) (2) | 2023.04.14 |
[SoC] DMA Controller (2) | 2023.03.06 |
댓글