Thứ Ba, 20 tháng 8, 2019

[Arbiter] Bài 2 - Phân xử theo mức ưu tiên động

Tiếp theo bài 1, bài viết này trình bày cách thiết kế một bộ phân xử theo mức ưu tiên động (dynamic priority). Chi tiết về cấu trúc mạch, RTL code và một kết quả mô phỏng minh họa sẽ được trình bày chi tiết.

1) Mô tả thiết kế
Bộ phân xử theo mức ưu tiên cố định gán một mức ưu tiên cố định cho mỗi nguồn request. Ví dụ như trong bài 1, nguồn request kết nối đến req[0] luôn có mức ưu tiên cao nhất và mức ưu tiên sẽ giảm dần theo thứ tự từ req[1], req[2], req[3], ...
Cách thiết kế này luôn làm cho nguồn request có mức ưu tiên càng thấp càng ít có khả năng được grant.
Một cách thiết kế giúp tăng khả năng được grant cho các nguồn request là cấp phát mức ưu tiên động. Nguyên tắc cơ bản là mỗi request được gửi đi, từ bất kỳ nguồn nào, sẽ được kèm theo một số chỉ định mức ưu tiên. Dựa trên số ưu tiên này các request sẽ được phân xử phù hợp.
Nếu hai request có số ưu tiền bằng nhau thì việc phân xử lại dựa trên mức ưu tiên cố định như bài 1.
Hình 1: Cấu trúc các chức năng logic của bộ phân xử theo mức ưu tiên động
Trong thiết kế này, mỗi nguồn request có thể thiết lập số ưu tiên bất kỳ cho mỗi request. Số ưu tiên này và thông tin request sẽ được so sánh thông qua các mạch logic được giới thiệu sau đây:
  • (1) Priority selection: Mạch logic tạo ra các tín hiệu request phụ dựa trên mức ưu tiên của request. Ví dụ, nếu có 4 nguồn request (req[3:0]) thì mỗi nguồn có thể thiết lập 4 giá trị ưu tiên từ 0 đến 3. Mạch này sẽ tạo ra 4 tín hiệu request phụ dựa trên việc so sánh mức ưu tiên lần lượt với 0, 1, 2 và 3. Khi tín hiệu request tích cực thì một trong 4 tín hiệu request phụ này sẽ tích cực tùy vào giá trị mức ưu tiên lúc đó. Ví dụ, req[0]=1 và mức ưu tiên priorityLevel của req[0] là 2 thì tín hiệu request phụ số 2 (compResult[2]) sẽ tích cực, 3 tín hiệu request phụ kia là 0. Với ví dụ là 4 nguồn request thì request phụ cho nguồn req[1]compResult[7:4], nguồn req[2] compResult[11:8] req[3] compResult[15:12].
Hình 2: Mạch nguyên lý tạo ra các request phụ (compResult) cho nguồn request 0 (req[0]) dựa trên mức ưu tiên
  • (2) Asserted request check: Mạch logic nhóm các tín hiệu request phụ từ các nguồn theo mức ưu tiên. Các tín hiệu có mức ưu tiên giống nhau sẽ được OR với nhau.

Hình 3: Mạch nguyên lý nhóm các tín hiệu request phụ có cùng mức ưu tiên từ các nguồn request. Hình này là mạch OR cho mức ưu tiên có giá trị 0 của 4 nguồn request.
  • (3) Request enable: Mạch logic này tạo ra tín hiệu enable cho từng nhóm ưu tiên. Ví dụ, nếu có 4 nguồn request (req[3:0]) thì mỗi nguồn có thể thiết lập 4 giá trị ưu tiên là 0, 1, 2 và 3. Bốn giá trị này ứng với 4 nhóm. Nếu nhóm 0 có request thì tín hiệu enable của nhóm này bằng 1. Tín hiệu enable của các nhóm có ưu tiên thấp hơn như 1, 2 và 3 chỉ tích cực khi enable của tất cả các nhóm có mức ưu tiên cao hơn nó là 0.
Hình 4: Mạch nguyên lý của tín hiệu enable nguồn request theo từng nhóm ưu tiên. Hình trên minh họa cho enable của nhóm 0, 1 và 2 (req[2:0])
  • (4) Request mask: Mạch logic sử dụng các tín hiệu enable để che các tín hiệu request phụ đã tạo ra ở bước (1). Sau khi che lại, chỉ các tín hiệu request phụ có cùng mức ưu tiên cao nhất mới tích cực.
Hình 5: Mạch nguyên lý của chức năng che (mask) các tín hiệu request phụ cho nguồn req[0] và req[1] trong ví dụ có 4 nguồn request. Ở đây newGrant[3:0] và newGrant[7:4] là các tín hiệu request phụ mới cho nguồn req[0] và req[1]
  • (5) Grant set: Mạch logic OR tất cả các tín hiệu request phụ ở bước (4) để tạo ra tín hiệu thiết lập grant cho từng nguồn request. Sau mạch này, nguồn request nào có chứa mức ưu tiên cao nhất thì tín hiệu yêu cầu tích cực grant của nguồn đó sẽ bằng 1.
Hình 6: Mạch nguyên lý tạo tín hiệu yêu cầu tích cực grant cho từng nguồn request. Hình minh họa này dành cho trường hợp có 4 nguồn request
  • (6) Same priority filter: Mạch logic lọc các grant có mức request giống nhau. Sau khi qua mạch logic (5), setGrant[*] của các nguồn request có mức ưu tiên cao nhất, các nguồn có cùng giá trị mức ưu tiên, sẽ đều tích cực. Mạch logic này sẽ lọc lại các setGrant[*] theo nguyên tắc req[0] có mức ưu tiên cao nhất và mức ưu tiên sẽ giảm dần từ req[1], req[2], ...
Hình 7: Mạch nguyên lý thiết lập mức ưu tiên cho các yêu cầu grant từ các nguồn có mức ưu tiên cao nhất giống nhau. Đây là ví dụ minh họa dành cho req[0], req[1] và req[2]
  • (7) Grant: Mạch logic cấp phát quyền truy cập cho request. Đây là một thanh ghi sẽ cập nhật giá trị mới từ ngõ ra mạch (6) nếu không có nguồn nào đang được grant (noGrant=0). Nếu có một nguồn đang được grant (noGrant=1) thì thanh ghi sẽ giữ nguyên giá trị cũ cho đến khi request đang được grant hiện tại kết thúc (req[*]=0).
Hình 8: Mạch nguyên lý của thanh ghi grant trong trường hợp có 4 nguồn request
2) RTL code
RTL code được viết dưới dạng "code linh động" (flexible code) có thể cấu hình được số nguồn request. Trong đó:
  • REQ_NUM là số nguồn request mong muốn
  • PRI_WIDTH là số bit thiết lập mức ưu tiên dành cho mỗi nguồn. Số bit này bằng log2 của số nguồn request. Ví dụ, 4 nguồn request thì mỗi nguồn có 2 bit thiết lập mức ưu tiên với các giá trị có thể thiết lập là 0, 1, 2 và 3. Trong đó, 0 là giá trị ứng với mức ưu tiên cao nhất.
  • PRI_TOTALW là tổng số bit dùng cho việc thiết lập mức ưu tiên. Giá trị thông số này bằng số nguồn nhân số bit ưu tiên, REQ_NUM*PRI_WIDTH
Trong RTL code này, tác giả tạo 2 function, một dùng để tổng hợp mạch logic OR với số đầu vào không cố định là orOut và một dùng để tính log2 là clog2. Chú ý, function tính log2 không tổng hợp thành mạch logic mà chỉ dùng để tính giá trị cho hằng số (parameter).
Hình 9: Giải thuật của function clog2 dùng để tính log2
Đối với function orOut, vì số lượng request là không cố định nên mạch logic OR của bước "(2) Asserted request check" có số đầu vào không cố định. Logic này thực hiện OR các bit ở các vị trí không tiên tục nhau trong cùng một tín hiệu, xem lại hình minh họa 3. Trường hợp này, chúng ta sẽ tạo một function có input là tín hiệu có chứa các bit cần OR (orIn) và một chỉ số dùng để chọn bit để OR (id).
Ví dụ 1: function OR các bit rời rạc

  function reg orOut;
    input [REQ_NUM*REQ_NUM-1:0] orIn;
   input integer id;
   integer i;
    begin
      orOut = 1'b0;
      for (i=0; i< REQ_NUM; i=i+1) begin
        orOut = orOut | orIn[id+i*REQ_NUM];
      end
    end
  endfunction

Function orOut được sử dụng cho mạch logic (2) như sau:
Ví dụ 2: Sử dụng function orOut để OR các bit rời rạc

for (i0=0; i0< REQ_NUM; i0=i0+1) begin: AChk
  assign orPriorityResult[i0] = 
  orOut(compResult[REQ_NUM*REQ_NUM-1:0],i0);
end

Khi giá trị i0=0, đoạn code trên sẽ tạo ra mạch nguyên lý hình 3.
Trên đây là một số điểm cần lưu ý về RTL code. Các bạn có thể tải RTL code đầy đủ ở cuois bài viết.
3) Kết quả mô phỏng
Hình dưới đây thể hiện 1 kết quả mô phỏng với các request có mức độ ưu tiên khác nhau. Trong mô phỏng này, mức ưu tiên của các request như sau:

  • req[0] có mức ưu tiên priorityLevel[1:0]=2'b11 (thấp nhất, ưu tiên mức 4)
  • req[1] có mức ưu tiên priorityLevel[3:2]=2'b10 (ưu tiên thứ 3)
  • req[2] có mức ưu tiên priorityLevel[5:4]=2'b00 (cao nhất, ưu tiên thứ 1)
  • req[3] có mức ưu tiên priorityLevel[7:6]=2'b01 (ưu tiên thứ 2)
Trong lần phân xử đầu tiên, chỉ có req[2] tích cực nên nó sẽ được grant, bất chấp mức ưu tiên. Trong các lần phân xử tiếp theo, khi có 2 hoặc nhiều request cùng tích cực, request có mức ưu tiên cao nhất sẽ được grant.


Hình 10: Minh họa một kết quả mô phỏng

Dữ liệu có thể tải:

Lịch sử cập nhật:
1) 2019.Aug.20 - Tạo lần đầu

0 bình luận:

Đăng nhận xét