反壓機(jī)制指的是在輸出(或者輸入)端連接的模塊不能接收數(shù)據(jù)(或者沒有輸入數(shù)據(jù)),此時(shí)自己的模塊的運(yùn)行狀態(tài)需要暫停運(yùn)行。
反壓機(jī)制適用于所有擁有握手協(xié)議的模塊,且強(qiáng)烈建議使用反壓機(jī)制用于自己模塊設(shè)計(jì)。
反壓機(jī)制在公眾號(hào)最開始也有寫過,但是過去了很長時(shí)間,對(duì)設(shè)計(jì)有了新的理解,這篇文章會(huì)細(xì)述一對(duì)一、多對(duì)一、一對(duì)多、多對(duì)多之間反壓機(jī)制的細(xì)節(jié)和設(shè)計(jì)。
以下具體示例可以參見我的GitHub:back-pressure-mechanism
git@github.com:lookout1992/back-pressure-mechanism.git
一、一對(duì)一
一對(duì)一反壓是反壓機(jī)制中的基礎(chǔ),也是最常見的結(jié)構(gòu)。
如上圖,如果模塊內(nèi)部由一個(gè)寄存器組成,那模塊的輸出信號(hào)din.ready和dout.valid就可以如下設(shè)計(jì):
logic switch_en;
assign switch_en = !dout.valid | dout.ready;
logic r_valid;
always @ (posedge clk or negedge rst_n)begin
if(!rst_n)begin
r_valid <= 'd0;
end
else if(switch_en)begin
r_valid <= din.valid;
end
end
assign dout.valid = r_valid;
assign din.ready = switch_en
增加switch_en信號(hào),代表輸出端沒有準(zhǔn)備好輸出數(shù)據(jù) ,或者是連接輸出端的模塊已經(jīng) 準(zhǔn)備好接收數(shù)據(jù)。
總結(jié)一句話就是模塊(寄存器)的數(shù)據(jù)可以流動(dòng)起來。因此switch_en也是輸出口i_ready的賦值信號(hào)。
關(guān)于valid(或者沒有顯示的data計(jì)算部分),只有在switch_en有效時(shí),可以向下傳遞。
如果圖中模塊中由多級(jí)一對(duì)一的寄存器組成,那么最優(yōu)的設(shè)計(jì)思路是像上面設(shè)計(jì)一樣,一級(jí)級(jí)拼接起來,也是最復(fù)雜的。(而不是原始公眾號(hào)文章中,用一個(gè)switch_en控制所有的流水使能)
在實(shí)際設(shè)計(jì)中,有可能會(huì)在時(shí)序和資源之間平衡,需要把流水線拆開,分時(shí)復(fù)用運(yùn)算邏輯。因此會(huì)出現(xiàn)一筆輸入,但是有兩筆輸出,且運(yùn)算時(shí)需要使用兩次輸入數(shù)據(jù)(即不允許輸入寄存器更新太快)。這個(gè)時(shí)候需要添加新的使能(或者counter)等用于額外的判斷條件
以上具體示例可以參見我的GitHub:back-pressure-mechanism/one2one
二、多對(duì)一
多對(duì)一反壓是處理一對(duì)一之外最常見的結(jié)構(gòu),多用于多個(gè)輸入數(shù)據(jù)運(yùn)算輸出一個(gè)信號(hào)。
處理這種結(jié)構(gòu),主要思路是 所有輸入有效 ,對(duì)于switch2_en 和 switch3_en見上面一對(duì)一反壓設(shè)計(jì),主要描述switch1_en和輸入輸出之間的關(guān)系:
// din0 和din1 相遇前各自一組寄存器。
logic r_reg_din0_valid;
logic w_reg_din0_ready;
logic r_reg_din1_valid;
logic w_reg_din1_ready;
logic switch1_en;
logic w_reg_din_valid;
logic r_reg_dout_valid;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
r_reg_dout_valid <= 'd0;
end
else if(switch1_en)begin
r_reg_dout_valid<= w_reg_din_valid;
end
end
assign switch1_en = !dout.valid | dout.ready;
assign w_reg_din0_ready = r_reg_din1_valid & switch_en;
assign w_reg_din1_ready = r_reg_din0_valid & switch_en;
assign w_reg_din_valid = r_reg_din0_valid & r_reg_din1_valid;
以上具體示例可以參見GitHub:back-pressure-mechanism/more2one
三、一對(duì)多
以一輸入、二輸出為例:
輸入的ready和輸出的valid將會(huì)取決于所有輸出端口是否 準(zhǔn)備好 。
logic switch_en;
logic r_din_valid;
assign switch_en = (!dout0.valid | dout0.ready)&
(!dout1.valid | dout1.ready);
assign din.ready = switch_en;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
r_din_valid<= 'd0;
end
else if(switch_en)begin
r_din_valid<= din.valid;
end
end
assign dout0.valid = r_din_valid & dout1.ready;
assign dout1.valid = r_din_valid & dout0.ready;
四、多對(duì)多
多對(duì)多的反壓設(shè)計(jì)可以看做多對(duì)一和一對(duì)多反壓的集合。
五、總結(jié)
反壓設(shè)計(jì)的目的是模塊可以在輸入或者輸出沒有準(zhǔn)備好是可以自動(dòng)停止運(yùn)算,好的反壓機(jī)制的作用是可以在運(yùn)算因?yàn)檩斎牖蛘咻敵龅脑蛲V购蛦?dòng)時(shí)減少其中的空檔期。
六、快速迭代
如果在設(shè)計(jì)中時(shí)間緊張,要求快速迭代出一版可以使用的反壓機(jī)制代碼,那么就不能再按照上面的設(shè)計(jì)思路扣細(xì)活。
可以直接以模塊輸出端的valid&ready作為全部寄存器的switch_en,這就會(huì)造成一個(gè)問題在停止時(shí),所有運(yùn)算都將停止,這會(huì)在啟動(dòng)時(shí)有流水中會(huì)有一些空擋(氣泡)。
使用switch_en信號(hào)給所有輸入信號(hào)ready賦值,中間所有寄存器也都由switch_en控制或者由輸入信號(hào)的valid&ready控制。
logic switch_en = !dout.valid | dout.ready
assign din.ready = switch_en;
logic r_din_valid;
logic r_din_valid_d1;
logic r_din_valid_d2;
logic [DW-1:0] r_din_data;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
r_din_data <= 'd0;
end
else if(din.valid & din.ready) begin
r_din_data <= din.data;
end
end
...
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
r_din_valid <= 'd0;
r_din_valid_d1 <= 'd0;
r_din_valid_d2 <= 'd0;
end
else if(switch_en) begin
r_din_valid <= din.valid;
r_din_valid_d1 <= r_din_valid;
r_din_valid_d2 <= r_din_valid_d1;
end
end
assign dout.valid = r_din_valid_d2;
-
模塊
+關(guān)注
關(guān)注
7文章
2716瀏覽量
47529 -
IC
+關(guān)注
關(guān)注
36文章
5957瀏覽量
175729 -
寄存器
+關(guān)注
關(guān)注
31文章
5355瀏覽量
120531 -
GitHub
+關(guān)注
關(guān)注
3文章
471瀏覽量
16466
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論