一些輪詢(xún)仲裁器方案的SystemVerilog 代碼
掃描二維碼
隨時(shí)隨地手機(jī)看文章
前文介紹了一個(gè)固定優(yōu)先級(jí)arbiter的可綜合SysyemVerilog代碼,你一定注意到了該設(shè)計(jì)的一個(gè)最大缺點(diǎn)。存在靜態(tài)優(yōu)先級(jí)意味著,在某些情況下,低優(yōu)先級(jí)的模塊可能永遠(yuǎn)無(wú)法得到服務(wù)。這被稱(chēng)為餓死,在某些設(shè)計(jì)中可能沒(méi)問(wèn)題,但在某些設(shè)計(jì)中,我們可能需要避免這種情況。
在下面的這篇文章中介紹了很多種輪詢(xún)仲裁方案。
「數(shù)字芯片設(shè)計(jì)【不定期更新文件】」
鏈接:https://pan.quark.cn/s/27331927a18e
避免它的一種方法是輪詢(xún)優(yōu)先級(jí)。一旦請(qǐng)求模塊得到服務(wù),下一個(gè)模塊將獲得最高優(yōu)先級(jí),以循環(huán)方式進(jìn)行優(yōu)先級(jí)的調(diào)整。這就是為什么這個(gè)仲裁器被稱(chēng)為Round Robin輪詢(xún)仲裁器,它用于避免設(shè)計(jì)中的餓死。
某個(gè)模塊的請(qǐng)求必須等待的最大時(shí)間取決于此設(shè)計(jì)中的請(qǐng)求者數(shù)量。
always_comb begin case (pointer_reg) 2'b00 : if (req[0]) grant = 4'b0001; else if (req[1]) grant = 4'b0010; else if (req[2]) grant = 4'b0100; else if (req[3]) grant = 4'b1000; else grant = 4'b0000; 2'b01 : if (req[1]) grant = 4'b0010; else if (req[2]) grant = 4'b0100; else if (req[3]) grant = 4'b1000; else if (req[0]) grant = 4'b0001; else grant = 4'b0000; 2'b10 : if (req[2]) grant = 4'b0100; else if (req[3]) grant = 4'b1000; else if (req[0]) grant = 4'b0001; else if (req[1]) grant = 4'b0010; else grant = 4'b0000; 2'b11 : if (req[3]) grant = 4'b1000; else if (req[0]) grant = 4'b0001; else if (req[1]) grant = 4'b0010; else if (req[2]) grant = 4'b0100; else grant = 4'b0000; endcase // case(req) end
此代碼適用于具有4位請(qǐng)求的RR仲裁。優(yōu)先級(jí)根據(jù)變量pointer_reg進(jìn)行輪換,每當(dāng)請(qǐng)求者獲得服務(wù)時(shí),pointer_reg都會(huì)發(fā)生變化。例如,如果模塊0被服務(wù),那么最高優(yōu)先級(jí)將是模塊1。當(dāng)模塊1被服務(wù)時(shí),模塊2將獲得最高優(yōu)先級(jí)。
我們可以寫(xiě)出計(jì)算pointer_reg值的邏輯,如下所示:
logic [1:0] pointer_req, next_pointer_req; always @(posedge clock) begin if (reset) pointer_req <= '0; else pointer_req <= next_pointer_req; end always_comb begin assign next_pointer_req = 2'b00; casez (gnt) 4'b0001: next_pointer_req = 2'b01; 4'b0010: next_pointer_req = 2'b10; 4'b0100: next_pointer_req = 2'b11; 4'b1000: next_pointer_req = 2'b00; endcase end
就像固定優(yōu)先級(jí)仲裁一樣,這種設(shè)計(jì)是不可擴(kuò)展的。輸入請(qǐng)求數(shù)量較多的代碼編寫(xiě)起來(lái)很繁瑣,而且容易出錯(cuò)。下面介紹其他可擴(kuò)展且易于參數(shù)化的設(shè)計(jì)。
The Rotate + Priority + Rotate Design
以“Rotate + Priority + Rotate”的設(shè)計(jì)為例。它使用固定優(yōu)先級(jí)仲裁器,并向右或向左移動(dòng)輸入,以模仿優(yōu)先級(jí)的旋轉(zhuǎn)。假設(shè)4'b1011是第一個(gè)輸入,這次沒(méi)有移位,因?yàn)檫@是第一個(gè)輸入。假設(shè)LSB具有最高優(yōu)先級(jí),當(dāng)我們將其發(fā)送給固定優(yōu)先級(jí)仲裁器時(shí),此輸入的輸出將為4'b0001。假設(shè)下一個(gè)輸入是4'b0011。通常,這種情況的輸出也是4'b0001,但在RR仲裁的情況下不是。由于這是第二個(gè)輸入,我們將其移動(dòng)1,因此對(duì)固定優(yōu)先級(jí)仲裁器的輸入現(xiàn)在變?yōu)?'b1001,輸出也變?yōu)?'b0001。但這不是我們的最終輸出,因?yàn)樵谟?jì)算輸出grant信號(hào)之前,我們將輸入“向左右”移動(dòng)了1,現(xiàn)在我們必須將其“向左”旋轉(zhuǎn)1才能獲得最終輸出,這樣輸出現(xiàn)在變成4'b0010。這是一個(gè)簡(jiǎn)單但有效的設(shè)計(jì)。決定左右旋轉(zhuǎn)的指針邏輯可以很容易地以我之前提到的方式編碼。這種設(shè)計(jì)速度不是很快,因?yàn)樾枰罅康牟僮鱽?lái)生成grant輸出,但綜合時(shí)需要非常小的面積。
The MUXed parallel priority arbiters
從圖表中可以看出,這個(gè)設(shè)計(jì)相當(dāng)大。該設(shè)計(jì)還是使用固定優(yōu)先級(jí)仲裁器,每個(gè)輸入請(qǐng)求都有一個(gè)固定優(yōu)先級(jí)仲裁器。隨著輸入請(qǐng)求者數(shù)量的增加,它只會(huì)越來(lái)越大。但好的方面是,它非???。由于所有優(yōu)先級(jí)仲裁器的輸出grant已經(jīng)計(jì)算好了,我們只是從中選擇一個(gè)輸出。讓我們嘗試為4位輸入請(qǐng)求總線(xiàn)編寫(xiě)此設(shè)計(jì)代碼。
module muxed_rr_arb( input logic clock, reset, input logic [3:0] req, output logic [3:0] gnt ); logic [3:0] mux_ip0, mux_ip1, mux_ip2, mux_ip3; //Instantiate fixed priority arbiter and calculate the grant output for shifted priorities fixed_pri_arbiter inst0 (.req(req), .gnt(mux_ip0)); fixed_pri_arbiter inst1 (.req(req>>1), .gnt(mux_ip1)); fixed_pri_arbiter inst2 (.req(req>>2), .gnt(mux_ip2)); fixed_pri_arbiter inst3 (.req(req>>3), .gnt(mux_ip3)); //Select line pointer calculation logic [1:0] pointer_req, next_pointer_req; always @(posedge clock) begin if (reset) pointer_req <= '0; else pointer_req <= next_pointer_req; end always_comb begin assign next_pointer_req = 2'b00; casez (gnt) 4'b0001: next_pointer_req = 2'b01; 4'b0010: next_pointer_req = 2'b10; 4'b0100: next_pointer_req = 2'b11; 4'b1000: next_pointer_req = 2'b00; endcase end //Final output always_comb begin case (pointer_req) 2'b00: gnt = mux_ip0; 2'b01: gnt = mux_ip1; 2'b10: gnt = mux_ip2; 2'b11: gnt = mux_ip3; endcase end endmodule
您可以使用generate for循環(huán)來(lái)實(shí)例化固定優(yōu)先級(jí)仲裁器,輕松地對(duì)此設(shè)計(jì)進(jìn)行參數(shù)化。
Two Simple Priority Arbiters with a Mask
此設(shè)計(jì)使用兩個(gè)固定的優(yōu)先級(jí)仲裁。一個(gè)用于計(jì)算請(qǐng)求輸入的grant輸出,另一個(gè)用于計(jì)算帶有屏蔽請(qǐng)求輸入的grant輸出。屏蔽請(qǐng)求是通過(guò)使用mask變量對(duì)輸入請(qǐng)求進(jìn)行AND來(lái)計(jì)算的,每次請(qǐng)求服務(wù)時(shí),其值都會(huì)發(fā)生變化。mask邏輯如下所示:
always@(/*AUTOSENSE*/pointer_reg) begin case (pointer_reg) // synopsys full_case parallel_case 2'b00: req_mask <= 4'b1111; 2'b01: req_mask <= 4'b1110; 2'b10: req_mask <= 4'b1100; 2'b11: req_mask <= 4'b1000; endcase end
這是一個(gè)非常有效的解決方案,在論文中提到的所有設(shè)計(jì)中,它提供了最佳性能。
Weighted RR Arbiter
這也是一個(gè)輪詢(xún)仲裁,但有一點(diǎn)變化。例如,讓我們假設(shè)請(qǐng)求者0的權(quán)重值為3,請(qǐng)求者1的權(quán)重值為2。如果在第一個(gè)周期中,輸入為4'b0011,請(qǐng)求者0將被服務(wù)?,F(xiàn)在請(qǐng)求者0已服務(wù),其權(quán)重減少到2。請(qǐng)求者1的權(quán)重值仍然為2。假設(shè)輸入在第二個(gè)周期中是相同的,即4'b0011。理想情況下,這次請(qǐng)求者1應(yīng)該根據(jù)循環(huán)計(jì)劃獲得服務(wù),但由于請(qǐng)求者0和1的權(quán)重相同,我們假設(shè)LSB具有最高的優(yōu)先級(jí),請(qǐng)求者0將再次獲得服務(wù),其權(quán)重將減少到1?,F(xiàn)在,如果我們?cè)诘谌齻€(gè)周期中看到相同的輸入,請(qǐng)求者1的權(quán)重值更大,因此請(qǐng)求者1這次將得到服務(wù)。





