chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于FPGA的高效除法器設(shè)計(jì)

FPGA研究院 ? 來源:數(shù)字站 ? 2025-10-28 14:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

來源:數(shù)字站

FPGA可以通過除號(hào)直接實(shí)現(xiàn)除法,但是當(dāng)除數(shù)或被除數(shù)位寬較大時(shí),計(jì)算會(huì)變得緩慢,導(dǎo)致時(shí)序約束不能通過。此時(shí)可以通過在除法IP中加入流水線來提高最大時(shí)鐘頻率,這種方式提高時(shí)鐘頻率也很有限。如果還不能達(dá)到要求,就只能把除法器拆分,來提高系統(tǒng)時(shí)鐘頻率。

其實(shí)最簡(jiǎn)單的方式是使用計(jì)數(shù)器對(duì)除數(shù)進(jìn)行累加,并且把累加的次數(shù)寄存,當(dāng)累加結(jié)果大于等于被除數(shù)時(shí),此時(shí)寄存的累加次數(shù)就是商,而被除數(shù)減去累加結(jié)果就得到余數(shù)。

但這種方式存在一種弊端,當(dāng)除數(shù)很小的時(shí)候,被除數(shù)特別大時(shí),需要經(jīng)過很多個(gè)時(shí)鐘周期才能計(jì)算除結(jié)果。比如被除數(shù)為100,除數(shù)為1,就需要100個(gè)時(shí)鐘左右才能計(jì)算出結(jié)果,效率無疑是低下的。因此一般不會(huì)使用這種方式實(shí)現(xiàn)除法器。

01除法器原理

首先觀察圖1中二進(jìn)制數(shù)10011001除以1010的計(jì)算過程,除數(shù)與被除數(shù)位寬相差4,4位除數(shù)(1010)大于被除數(shù)的高4位(1001),小于被除數(shù)的高5位(10011),所以首先是被除數(shù)的高5位減去除數(shù)(如圖紫色數(shù)字),得到01001。然后被除數(shù)的第2位到6位數(shù)據(jù)依舊大于除數(shù),則在次減去除數(shù),就這樣依次相減,最后得到商為1111,余數(shù)為3。

034429c4-b069-11f0-8c8f-92fbcf53809c.png

03981052-b069-11f0-8c8f-92fbcf53809c.png

圖1 二進(jìn)制除法

其實(shí)通過上面講述,就可以根據(jù)這個(gè)規(guī)律實(shí)現(xiàn)除法器了,每次從被除數(shù)高位取除數(shù)相同數(shù)據(jù)位寬的數(shù)據(jù)與除數(shù)進(jìn)行比較,大于等于時(shí)直接做減法,商加1。小于時(shí)被除數(shù)數(shù)據(jù)位寬向低位移動(dòng),被除數(shù)每右移動(dòng)1位,商左移1位,直到被除數(shù)移動(dòng)到最低位時(shí)結(jié)束運(yùn)算。

以上描述的方法在FPGA上不太好實(shí)現(xiàn),最好是改進(jìn)一下,將被除數(shù)和除數(shù)比較的位進(jìn)行固定,那樣就會(huì)好實(shí)現(xiàn)很多。

如圖2所示,還是前文的8位10011001除以4位1010,通過一個(gè)9位的寄存器存儲(chǔ)8位被除數(shù),始終比較被除數(shù)寄存器的第4到8位數(shù)據(jù)與除數(shù)的大小,如果大于除數(shù),則進(jìn)行減法運(yùn)算,否則將被除數(shù)左移1位,然后在次進(jìn)行判斷。

首先是5’b01001小于除數(shù)4’b1010,則將被除數(shù)左移1位。然后被除數(shù)高五位數(shù)據(jù)5’b10010大于除數(shù),則商1,兩者相減得到01001。得到數(shù)據(jù)作為被除數(shù)運(yùn)算位,此時(shí)被除數(shù)高5位還是比除數(shù)小,將被除數(shù)左移1位,相當(dāng)于運(yùn)算被除數(shù)的低位數(shù)據(jù),同時(shí)也要把商左移1位。

03ebace4-b069-11f0-8c8f-92fbcf53809c.png

圖2 除法運(yùn)算

就如同上圖循環(huán)判斷被除數(shù)高5位數(shù)據(jù)與除數(shù)的大小關(guān)系,然后對(duì)被除數(shù)進(jìn)行移位和減法運(yùn)算,就能夠計(jì)算出商和余數(shù)。當(dāng)被除數(shù)的最低位數(shù)據(jù)被移入高5位時(shí),在通過判斷被除數(shù)高5位數(shù)據(jù)與除數(shù)大小并進(jìn)行相應(yīng)減法后,運(yùn)算結(jié)束。也就是說,這種情況下,被除數(shù)位寬為8,除數(shù)位寬為4,則被除數(shù)左移4次后計(jì)算結(jié)束,余數(shù)等于最后被除數(shù)的數(shù)值右移4位(被除數(shù)總共左移的次數(shù))。

這種運(yùn)算FPGA實(shí)現(xiàn)就較為簡(jiǎn)單,例如被除數(shù)位寬為M,除數(shù)位寬為N,滿足M>=N,只需要比較被除數(shù)[M:M-N]與除數(shù)的大小,被除數(shù)左移M-N次后運(yùn)算結(jié)束,將最終的被除數(shù)右移M-N位得到余數(shù)。

上述只適用于一般情況,還會(huì)出現(xiàn)圖3這種,被除數(shù)依舊是8位10000001,4位除數(shù)為0010,此時(shí)如果還拿被除數(shù)高5位減去除數(shù),得到的結(jié)果仍然大于除數(shù),會(huì)導(dǎo)致計(jì)算錯(cuò)誤。

0445bcf2-b069-11f0-8c8f-92fbcf53809c.png

034429c4-b069-11f0-8c8f-92fbcf53809c.png

圖3 除法運(yùn)算

此時(shí)可以把除數(shù)進(jìn)行左移,直到除數(shù)的最高位為1或者除數(shù)左移后大于被除數(shù)的高5位為止,需要考慮除數(shù)左移1位,相當(dāng)于增大2倍,要保持最終結(jié)果不變,被除數(shù)左移次數(shù)需要增加除數(shù)左移的次數(shù),并且最后余數(shù)右移的次數(shù)也會(huì)相應(yīng)增加。所以上述計(jì)算變?yōu)閳D4所示。

04ea1716-b069-11f0-8c8f-92fbcf53809c.png

034429c4-b069-11f0-8c8f-92fbcf53809c.png

圖4 除法運(yùn)算

首先除數(shù)根據(jù)條件需要左移2位都不會(huì)大于被除數(shù)的高5位,且不會(huì)溢出,所以除數(shù)就先左移2位,然后就是判斷被除數(shù)高5位是否大于除數(shù),大于除數(shù)就進(jìn)行減法運(yùn)算且商加1,減法運(yùn)算結(jié)果小于除數(shù)取代被除數(shù)參與運(yùn)算的數(shù)據(jù)位。如果被除數(shù)高5位小于除數(shù),則被除數(shù)和商一起左移,然后在次判斷。最終當(dāng)被除數(shù)左移次數(shù)達(dá)到除數(shù)左移次數(shù)加被除數(shù)與除數(shù)位寬之差時(shí)計(jì)算結(jié)束。02除法器實(shí)現(xiàn)

經(jīng)過上述分析,首先當(dāng)輸入數(shù)據(jù)有效時(shí),需要判斷除數(shù)和被除數(shù)是否為0,其中一個(gè)為0,則輸出均為0,且除數(shù)為0時(shí),應(yīng)該報(bào)錯(cuò)。該模塊采用一個(gè)狀態(tài)機(jī)作為架構(gòu),包括空閑狀態(tài),左移除數(shù),除法運(yùn)算三個(gè)狀態(tài)。假設(shè)除數(shù)位寬L_DIVR,被除數(shù)位寬L_DIVN,且L_DIVN>=L_DIVR。

模塊初始處于空閑狀態(tài),只有上游模塊把開始計(jì)算信號(hào)拉高且被除數(shù)與除數(shù)均不為0時(shí),狀態(tài)機(jī)跳轉(zhuǎn)到左移除數(shù)狀態(tài)。此時(shí)需要把除數(shù)和被除數(shù)存入對(duì)應(yīng)寄存器,把除數(shù)左移次數(shù)計(jì)數(shù)器、被除數(shù)左移次數(shù)計(jì)數(shù)器、商和余數(shù)暫存器清零。

開始信號(hào)只有在狀態(tài)機(jī)處于空閑狀態(tài)下才會(huì)有效,其余時(shí)間不會(huì)接收上游模塊的除數(shù)、被除數(shù)等數(shù)據(jù)。

在左移除數(shù)的狀態(tài)下,如果除數(shù)最高位為0,且除數(shù)左移1位比被除數(shù)寄存器的高L_DIVR+1位小,那么將除數(shù)左移1位,除數(shù)左移次數(shù)計(jì)數(shù)器加1。否則狀態(tài)機(jī)跳轉(zhuǎn)到除法運(yùn)算狀態(tài)。

狀態(tài)機(jī)處于除法運(yùn)算狀態(tài)時(shí),需要計(jì)算被除數(shù)高L_DIVR+1減去除數(shù)是否大于0。如果大于等于0,則將減法結(jié)果作為被除數(shù)的高L_DIVR+1位,商的最低位賦值為1,也就是加1。如果小于0且被除數(shù)左移次數(shù)小于除數(shù)左移次數(shù)加L_DIVN-L_DIVR時(shí),把被除數(shù)和商均左移1位,被除數(shù)左移次數(shù)計(jì)數(shù)器加1。

如果被除數(shù)左移次數(shù)等于除數(shù)左移次數(shù)加L_DIVN-L_DIVR,則狀態(tài)機(jī)跳轉(zhuǎn)到空閑狀態(tài),將被除數(shù)右移除數(shù)左移次數(shù)加L_DIVN-L_DIVR得到余數(shù)。

狀態(tài)機(jī)從除法狀態(tài)跳轉(zhuǎn)到空閑狀態(tài)時(shí),把商、余數(shù)進(jìn)行輸出。


以下代碼是模塊端口信號(hào):

//當(dāng)輸入除數(shù)為0時(shí),error信號(hào)拉高,且商和余數(shù)為0;
//當(dāng)ready信號(hào)為低電平時(shí),不能將開始信號(hào)start拉高,此時(shí)拉高start信號(hào)會(huì)被忽略。
modulediv#(
 parameter    L_DIVN   = 8    ,//被除數(shù)的位寬;
 parameter    L_DIVR   = 4    //除數(shù)的位寬;
)(
input               clk    ,//時(shí)鐘信號(hào);
input               rst_n   ,//復(fù)位信號(hào),低電平有效;


inputstart    ,//開始計(jì)算信號(hào),高電平有效,必須在ready信號(hào)為高電平時(shí)輸入才有效。
input    [L_DIVN -1:0]   dividend  ,//被除數(shù)輸入;
input    [L_DIVR -1:0]   divisor   ,//除數(shù)輸入;


 output reg            ready   ,//高電平表示此模塊空閑。
 output reg            error   ,//高電平表示輸入除數(shù)為0,輸入數(shù)據(jù)錯(cuò)誤。
output reg            quotient_vld ,//商和余數(shù)輸出有效指示信號(hào),高電平有效;
 output reg   [L_DIVR -1:0] remainder  ,//余數(shù),余數(shù)的大小不會(huì)超過除數(shù)大小。
output reg   [L_DIVN -1:0] quotient   //商。
);

以下是狀態(tài)機(jī)狀態(tài)編碼和中間信號(hào)的定義,以及通過自動(dòng)計(jì)算位寬函數(shù)取計(jì)算計(jì)數(shù)器的位寬。

 localparam     L_CNT    =  clogb2(L_DIVN) ;//利用函數(shù)自動(dòng)計(jì)算移位次數(shù)計(jì)數(shù)器的位寬。
 localparam    IDLE    = 3'b001   ;//狀態(tài)機(jī)空閑狀態(tài)的編碼;
 localparam    ADIVR   = 3'b010   ;//狀態(tài)機(jī)移動(dòng)除數(shù)狀態(tài)的編碼;
 localparam    DIV    = 3'b100   ;//狀態(tài)機(jī)進(jìn)行減法計(jì)算和移動(dòng)被除數(shù)狀態(tài)的編碼;


 reg          vld    ;//
 reg     [2:0]    state_c   ;//狀態(tài)機(jī)的現(xiàn)態(tài);
 reg     [2:0]    state_n   ;//狀態(tài)機(jī)的次態(tài);
 reg     [L_DIVN :0]  dividend_r  ;//保存被除數(shù);
 reg     [L_DIVR -1:0] divisor_r   ;//保存除數(shù)。
 reg     [L_DIVN -1:0] quotient_r   ;//保存商。
 reg     [L_CNT -1:0]  shift_dividend ;//用于記錄被除數(shù)左移的次數(shù)。
 reg     [L_CNT -1:0]  shift_divisor ;//用于記錄除數(shù)左移的次數(shù)。


 wire     [L_DIVR :0]   comparison  ;//被除數(shù)的高位減去除數(shù)。
 wire           max    ;//高電平表示被除數(shù)左移次數(shù)已經(jīng)用完,除法運(yùn)算基本結(jié)束,可能還需要進(jìn)行一次減法運(yùn)算。


//自動(dòng)計(jì)算計(jì)數(shù)器位寬函數(shù)。
function integerclogb2(input integer depth);begin
if(depth ==0)
   clogb2 =1;
elseif(depth !=0)
for(clogb2=0; depth>0; clogb2=clogb2+1)
    depth=depth >>1;
  end
 endfunction


max用來判斷被除數(shù)左移次數(shù)是否等于除數(shù)于被除數(shù)位寬差加除數(shù)左移次數(shù)。而comparison在除數(shù)左移狀態(tài)時(shí),需要計(jì)算被除數(shù)高位與除數(shù)左移后相減的結(jié)果,在其余狀態(tài)下,計(jì)算被除數(shù)高位與除數(shù)相減的結(jié)果。

//max為高電平表示被除數(shù)左移的次數(shù)等于除數(shù)左移次數(shù)加上被除數(shù)與除數(shù)的位寬差;
 assign max = (shift_dividend == (L_DIVN - L_DIVR) + shift_divisor);


//用來判斷除數(shù)和被除數(shù)第一次做減法的高位兩者的大小,當(dāng)被除數(shù)高位大于等于除數(shù)時(shí),comparison最高位為0,反之為1。
//comparison的計(jì)算結(jié)果還能表示被除數(shù)高位與除數(shù)減法運(yùn)算的結(jié)果。
//在移動(dòng)除數(shù)時(shí),判斷的是除數(shù)左移一位后與被除數(shù)高位的大小關(guān)系,進(jìn)而判斷能不能把除數(shù)進(jìn)行左移。
 assign comparison = ((divisor[L_DIVR-1] ==0) && ((state_c == ADIVR))) ?
    dividend_r[L_DIVN : L_DIVN - L_DIVR] - {divisor_r[L_DIVR-2:0],1'b0} :
    dividend_r[L_DIVN : L_DIVN - L_DIVR] - divisor_r;//計(jì)算被除數(shù)高位減去除數(shù),如果計(jì)算結(jié)果最高位為0,表示被除數(shù)高位大于等于除數(shù),如果等于1表示被除數(shù)高位小于除數(shù)。

下面是狀態(tài)機(jī)跳轉(zhuǎn)代碼。

//狀態(tài)機(jī)次態(tài)到現(xiàn)態(tài)的轉(zhuǎn)換;
 always@(posedge clkornegedge rst_n)begin
if(rst_n==1'b0)begin//初始值為空閑狀態(tài);
   state_c <= IDLE;
? ? end
else?begin//狀態(tài)機(jī)次態(tài)到現(xiàn)態(tài)的轉(zhuǎn)換;
? ? ? state_c <= state_n;
? ? end
? end


//狀態(tài)機(jī)的次態(tài)變化。
? always@(*)begin
case(state_c)
IDLE : begin//如果開始計(jì)算信號(hào)為高電平且除數(shù)和被除數(shù)均不等于0。
if(start & (dividend !=?0) & (divisor !=?0))begin
? ? ? ? ? state_n = ADIVR;
? ? ? ? end
else?begin//如果開始條件無效或者除數(shù)、被除數(shù)為0,則繼續(xù)處于空閑狀態(tài)。
? ? ? ? ? state_n = state_c;
? ? ? ? end
? ? ? end
ADIVR : begin//如果除數(shù)的最高位為高電平或者除數(shù)左移一位大于被除數(shù)的高位,則跳轉(zhuǎn)到除法運(yùn)算狀態(tài);
if(divisor_r[L_DIVR-1] | comparison[L_DIVR])begin
? ? ? ? ? state_n = DIV;
? ? ? ? end
else?begin
? ? ? ? ? state_n = state_c;
? ? ? ? end
? ? ? end
DIV :?begin
if(max)begin//如果被除數(shù)移動(dòng)次數(shù)達(dá)到最大值,則狀態(tài)機(jī)回到空閑狀態(tài),計(jì)算完成。
? ? ? ? ? state_n = IDLE;
? ? ? ? end
else?begin
? ? ? ? ? state_n = state_c;
? ? ? ? end
? ? ? end
default?: begin//狀態(tài)機(jī)跳轉(zhuǎn)到空閑狀態(tài);
? ? ? ? state_n = IDLE;
? ? ? end
? ? endcase
? end


下面是除數(shù)和被除數(shù)、商的計(jì)算過程,與前文描述一致,不再贅述。

//對(duì)被除數(shù)進(jìn)行移位或進(jìn)行減法運(yùn)算。
//初始時(shí)需要加載除數(shù)和被除數(shù),然后需要判斷除數(shù)和被除數(shù)的高位,確定除數(shù)是否需要移位。
//然后根據(jù)除數(shù)和被除數(shù)高位的大小,確認(rèn)被除數(shù)是移位還是與除數(shù)進(jìn)行減法運(yùn)算,注意被除數(shù)移動(dòng)時(shí),為了保證結(jié)果不變,商也會(huì)左移一位。
//如果被除數(shù)高位與除數(shù)進(jìn)行減法運(yùn)算,則商的最低位變?yōu)?,好比此時(shí)商1進(jìn)行的減法運(yùn)算。經(jīng)減法結(jié)果賦值到被除數(shù)對(duì)應(yīng)位。
 always@(posedge clkornegedge rst_n)begin
if(rst_n==1'b0)begin//初始值為0;
   divisor_r <=?0;
? ? ? dividend_r <=?0;
? ? ? quotient_r <=?0;
? ? ? shift_divisor <=?0;
? ? ? shift_dividend <=?0;
? ? end//狀態(tài)機(jī)處于加載狀態(tài)時(shí),將除數(shù)和被除數(shù)加載到對(duì)應(yīng)寄存器,開始計(jì)算;
elseif(state_c == IDLE && start && (dividend !=?0) & (divisor !=?0))begin
? ? ? dividend_r <= dividend;//加載被除數(shù)到寄存器;
? ? ? divisor_r <= divisor;//加載除數(shù)到寄存器;
? ? ? quotient_r <=?0;//將商清零;
? ? ? shift_dividend <=?0;//將移位的被除數(shù)寄存器清零;
? ? ? shift_divisor <=?0;?//將移位的除數(shù)寄存器清零;
? ? end//狀態(tài)機(jī)處于除數(shù)左移狀態(tài),且除數(shù)左移后小于等于被除數(shù)高位且除數(shù)最高位為0。
elseif(state_c == ADIVR && (~comparison[L_DIVR]) && (~divisor_r[L_DIVR-1]))begin
? ? ? divisor_r <= divisor_r <



參考代碼如下所示:

//注意此模塊默認(rèn)被除數(shù)的位寬大于等于除數(shù)的位寬。
//當(dāng)quotient_vld信號(hào)為高電平且error為低電平時(shí),輸出的數(shù)據(jù)是除法計(jì)算的正確結(jié)果。
//當(dāng)輸入除數(shù)為0時(shí),error信號(hào)拉高,且商和余數(shù)為0;
//當(dāng)ready信號(hào)為低電平時(shí),不能將開始信號(hào)start拉高,此時(shí)拉高start信號(hào)會(huì)被忽略。
module div#(
 parameter    L_DIVN   = 8    ,//被除數(shù)的位寬;
 parameter    L_DIVR   = 4//除數(shù)的位寬;
)(
 input         clk    ,//時(shí)鐘信號(hào);
 input          rst_n   ,//復(fù)位信號(hào),低電平有效;


 input          start    ,//開始計(jì)算信號(hào),高電平有效,必須在ready信號(hào)為高電平時(shí)輸入才有效。
 input    [L_DIVN -1:0] dividend  ,//被除數(shù)輸入;
 input    [L_DIVR -1:0] divisor   ,//除數(shù)輸入;


 output  reg        ready   ,//高電平表示此模塊空閑。
 output  reg        error   ,//高電平表示輸入除數(shù)為0,輸入數(shù)據(jù)錯(cuò)誤。
 output reg        quotient_vld ,//商和余數(shù)輸出有效指示信號(hào),高電平有效;
 output reg   [L_DIVR -1:0] remainder  ,//余數(shù),余數(shù)的大小不會(huì)超過除數(shù)大小。
 output reg   [L_DIVN -1:0] quotient   //商。
); 
 localparam     L_CNT    =  clogb2(L_DIVN) ;//利用函數(shù)自動(dòng)計(jì)算移位次數(shù)計(jì)數(shù)器的位寬。
 localparam    IDLE    = 3'b001   ;//狀態(tài)機(jī)空閑狀態(tài)的編碼;
 localparam    ADIVR   = 3'b010   ;//狀態(tài)機(jī)移動(dòng)除數(shù)狀態(tài)的編碼;
 localparam    DIV    = 3'b100   ;//狀態(tài)機(jī)進(jìn)行減法計(jì)算和移動(dòng)被除數(shù)狀態(tài)的編碼;


 reg          vld    ;//
 reg     [2:0]    state_c   ;//狀態(tài)機(jī)的現(xiàn)態(tài);
 reg     [2:0]    state_n   ;//狀態(tài)機(jī)的次態(tài);
 reg     [L_DIVN :0]  dividend_r  ;//保存被除數(shù);
 reg     [L_DIVR -1:0] divisor_r   ;//保存除數(shù)。
 reg     [L_DIVN -1:0] quotient_r   ;//保存商。
 reg     [L_CNT -1:0]  shift_dividend ;//用于記錄被除數(shù)左移的次數(shù)。
 reg     [L_CNT -1:0]  shift_divisor ;//用于記錄除數(shù)左移的次數(shù)。


 wire     [L_DIVR :0]   comparison  ;//被除數(shù)的高位減去除數(shù)。
 wire           max    ;//高電平表示被除數(shù)左移次數(shù)已經(jīng)用完,除法運(yùn)算基本結(jié)束,可能還需要進(jìn)行一次減法運(yùn)算。


//自動(dòng)計(jì)算計(jì)數(shù)器位寬函數(shù)。
function integerclogb2(input integer depth);begin
if(depth ==0)
   clogb2 =1;
elseif(depth !=0)
for(clogb2=0; depth>0; clogb2=clogb2+1)
    depth=depth >>1;
  end
 endfunction


//max為高電平表示被除數(shù)左移的次數(shù)等于除數(shù)左移次數(shù)加上被除數(shù)與除數(shù)的位寬差;
 assign max = (shift_dividend == (L_DIVN - L_DIVR) + shift_divisor);


//用來判斷除數(shù)和被除數(shù)第一次做減法的高位兩者的大小,當(dāng)被除數(shù)高位大于等于除數(shù)時(shí),comparison最高位為0,反之為1。
//comparison的計(jì)算結(jié)果還能表示被除數(shù)高位與除數(shù)減法運(yùn)算的結(jié)果。
//在移動(dòng)除數(shù)時(shí),判斷的是除數(shù)左移一位后與被除數(shù)高位的大小關(guān)系,進(jìn)而判斷能不能把除數(shù)進(jìn)行左移。
 assign comparison = ((divisor[L_DIVR-1] ==0) && ((state_c == ADIVR))) ?
    dividend_r[L_DIVN : L_DIVN - L_DIVR] - {divisor_r[L_DIVR-2:0],1'b0} :
    dividend_r[L_DIVN : L_DIVN - L_DIVR] - divisor_r;//計(jì)算被除數(shù)高位減去除數(shù),如果計(jì)算結(jié)果最高位為0,表示被除數(shù)高位大于等于除數(shù),如果等于1表示被除數(shù)高位小于除數(shù)。


//狀態(tài)機(jī)次態(tài)到現(xiàn)態(tài)的轉(zhuǎn)換;
 always@(posedge clkornegedge rst_n)begin
if(rst_n==1'b0)begin//初始值為空閑狀態(tài);
   state_c <= IDLE;
? ? end
else?begin//狀態(tài)機(jī)次態(tài)到現(xiàn)態(tài)的轉(zhuǎn)換;
? ? ? state_c <= state_n;
? ? end
? end


//狀態(tài)機(jī)的次態(tài)變化。
? always@(*)begin
case(state_c)
IDLE : begin//如果開始計(jì)算信號(hào)為高電平且除數(shù)和被除數(shù)均不等于0。
if(start & (dividend !=?0) & (divisor !=?0))begin
? ? ? ? ? state_n = ADIVR;
? ? ? ? end
else?begin//如果開始條件無效或者除數(shù)、被除數(shù)為0,則繼續(xù)處于空閑狀態(tài)。
? ? ? ? ? state_n = state_c;
? ? ? ? end
? ? ? end
ADIVR : begin//如果除數(shù)的最高位為高電平或者除數(shù)左移一位大于被除數(shù)的高位,則跳轉(zhuǎn)到除法運(yùn)算狀態(tài);
if(divisor_r[L_DIVR-1] | comparison[L_DIVR])begin
? ? ? ? ? state_n = DIV;
? ? ? ? end
else?begin
? ? ? ? ? state_n = state_c;
? ? ? ? end
? ? ? end
DIV :?begin
if(max)begin//如果被除數(shù)移動(dòng)次數(shù)達(dá)到最大值,則狀態(tài)機(jī)回到空閑狀態(tài),計(jì)算完成。
? ? ? ? ? state_n = IDLE;
? ? ? ? end
else?begin
? ? ? ? ? state_n = state_c;
? ? ? ? end
? ? ? end
default?: begin//狀態(tài)機(jī)跳轉(zhuǎn)到空閑狀態(tài);
? ? ? ? state_n = IDLE;
? ? ? end
? ? endcase
? end


//對(duì)被除數(shù)進(jìn)行移位或進(jìn)行減法運(yùn)算。
//初始時(shí)需要加載除數(shù)和被除數(shù),然后需要判斷除數(shù)和被除數(shù)的高位,確定除數(shù)是否需要移位。
//然后根據(jù)除數(shù)和被除數(shù)高位的大小,確認(rèn)被除數(shù)是移位還是與除數(shù)進(jìn)行減法運(yùn)算,注意被除數(shù)移動(dòng)時(shí),為了保證結(jié)果不變,商也會(huì)左移一位。
//如果被除數(shù)高位與除數(shù)進(jìn)行減法運(yùn)算,則商的最低位變?yōu)?,好比此時(shí)商1進(jìn)行的減法運(yùn)算。經(jīng)減法結(jié)果賦值到被除數(shù)對(duì)應(yīng)位。
? always@(posedge clk?or?negedge rst_n)begin
if(rst_n==1'b0)begin//初始值為0;
? ? ? divisor_r <=?0;
? ? ? dividend_r <=?0;
? ? ? quotient_r <=?0;
? ? ? shift_divisor <=?0;
? ? ? shift_dividend <=?0;
? ? end//狀態(tài)機(jī)處于加載狀態(tài)時(shí),將除數(shù)和被除數(shù)加載到對(duì)應(yīng)寄存器,開始計(jì)算;
elseif(state_c == IDLE && start && (dividend !=?0) & (divisor !=?0))begin
? ? ? dividend_r <= dividend;//加載被除數(shù)到寄存器;
? ? ? divisor_r <= divisor;//加載除數(shù)到寄存器;
? ? ? quotient_r <=?0;//將商清零;
? ? ? shift_dividend <=?0;//將移位的被除數(shù)寄存器清零;
? ? ? shift_divisor <=?0;?//將移位的除數(shù)寄存器清零;
? ? end//狀態(tài)機(jī)處于除數(shù)左移狀態(tài),且除數(shù)左移后小于等于被除數(shù)高位且除數(shù)最高位為0。
elseif(state_c == ADIVR && (~comparison[L_DIVR]) && (~divisor_r[L_DIVR-1]))begin
? ? ? divisor_r <= divisor_r <> shift_dividend;
  end
elsebegin
   quotient_vld <=?1'b0;
? ? end
? end


//當(dāng)輸入除數(shù)為0時(shí),將錯(cuò)誤指示信號(hào)拉高,其余時(shí)間均為低電平。
? always@(posedge clk?or?negedge rst_n)begin
if(rst_n==1'b0)begin//初始值為0;
? ? ? error <=?1'b0;
? ??end
elseif(state_c == IDLE && start)begin
if(divisor==0)//開始計(jì)算時(shí),如果除數(shù)為0,把錯(cuò)誤指示信號(hào)拉高。
? ? ? ? error <=?1'b1;
else//開始計(jì)算時(shí),如果除數(shù)不為0,把錯(cuò)誤指示信號(hào)拉低。
? ? ? ? error <=?1'b0;
? ? end
? end


//狀態(tài)機(jī)處于空閑且不處于復(fù)位狀態(tài);
? always@(*)begin
if(start || state_c != IDLE || vld)
? ? ? ready =?1'b0;
else
? ? ? ready =?1'b1;
? end


endmodule

03
除法器仿真


對(duì)應(yīng)的TestBench文件如下所示:

`timescale1ns/1ns
moduletest();
  localparam L_DIVN     = 8       ;//被除數(shù)的位寬;
  localparam L_DIVR     = 4       ;//除數(shù)的位寬;
  localparam CYCLE      = 20       ;//時(shí)鐘周期;


  reg               clk       ;//時(shí)鐘信號(hào);
  reg               rst_n      ;//復(fù)位信號(hào),低電平有效;
  reg               start      ;//開始計(jì)算信號(hào),高電平有效,
  reg     [L_DIVN -1:0]  dividend    ;//被除數(shù)輸入;
  reg     [L_DIVR -1:0]  divisor     ;//除數(shù)輸入;


  wire    [L_DIVN -1:0]  quotient    ;//商。
  wire    [L_DIVR -1:0]  remainder    ;//余數(shù),余數(shù)的大小不會(huì)超過除數(shù)大小。
  wire              quotient_vld  ;//商和余數(shù)輸出有效指示信號(hào),高電平有效;
  wire              ready      ;//高電平表示此模塊空閑。
  wire              error      ;//高電平表示輸入除數(shù)為0,輸入數(shù)據(jù)錯(cuò)誤。


  reg               quotient_error ;
  reg               rem_error    ;


//例化待測(cè)試的除法器模塊;
  div#(
    .L_DIVN     ( L_DIVN    ),//被除數(shù)的位寬;
    .L_DIVR     ( L_DIVR    )//除數(shù)的位寬;
  )
  u_div(
    .clk      ( clk      ),//時(shí)鐘信號(hào);
    .rst_n     ( rst_n     ),//復(fù)位信號(hào),低電平有效;
    .start     ( start     ),//開始計(jì)算信號(hào),高電平有效,
    .dividend    ( dividend   ),//被除數(shù)輸入;
    .divisor    ( divisor    ),//除數(shù)輸入;
    .quotient    ( quotient   ),//商。
    .remainder   ( remainder   ),//余數(shù),余數(shù)的大小不會(huì)超過除數(shù)大小。
    .ready     ( ready     ),//高電平表示此模塊空閑。
    .error     ( error     ),//高電平表示輸入除數(shù)為0,輸入數(shù)據(jù)錯(cuò)誤。
    .quotient_vld  ( quotient_vld )//商和余數(shù)輸出有效指示信號(hào),高電平有效;
  );


//生成時(shí)鐘信號(hào);
  initial begin
    clk =0;
    forever#(CYCLE/2) clk = ~clk;
  end


//生成復(fù)位信號(hào);
  initial begin
    rst_n =1;
#2;
    rst_n =0;//開始時(shí)復(fù)位5個(gè)時(shí)鐘;
#(5*CYCLE);
    rst_n =1;
  end


  initial begin
#1;
    dividend =121; divisor =13;start=0;
#(8*CYCLE);
    repeat(20)begin//循環(huán)進(jìn)行20次運(yùn)算;
#(5*CYCLE);
      dividend = {$random};//產(chǎn)生隨機(jī)數(shù)作為被除數(shù);
      divisor = {$random} ;//產(chǎn)生隨機(jī)數(shù)作為除數(shù);
      start =1;
#(CYCLE);
      start =0;
      @(negedge quotient_vld);
#1;
#(3*CYCLE);
    end
#(5*CYCLE);
    $stop;//停止仿真;
  end


//對(duì)模塊輸出的數(shù)據(jù)進(jìn)行判斷。
  always@(posedge clkornegedge rst_n)begin
if(rst_n==1'b0)begin//初始值為0;
      quotient_error <=?1'b0;
? ? ? ? ? ? rem_error <=?1'b0;
? ? ? ??end
? ? ? ??else?if(quotient_vld && (divisor!=0))begin
? ? ? ? ? ? quotient_error <= ((dividend / divisor) != quotient);
? ? ? ? ? ? rem_error <= ((dividend % divisor) != remainder);
? ? ? ? end
? ? end


endmodule



仿真結(jié)果如下所示,商和余數(shù)的錯(cuò)誤指示信號(hào)均為低電平,表示除法運(yùn)算的結(jié)果沒有什么問題。

058e6802-b069-11f0-8c8f-92fbcf53809c.png

圖5 仿真結(jié)果

模塊內(nèi)部信號(hào)的詳細(xì)仿真如圖6、7所示,具體含義與前文介紹一致,就不再贅述了。

05eac66a-b069-11f0-8c8f-92fbcf53809c.png

圖6 除法模塊詳細(xì)仿真

063f32d6-b069-11f0-8c8f-92fbcf53809c.png

圖7 除法模塊詳細(xì)仿真

04總結(jié)

使用該模塊需要注意幾點(diǎn):

1、被除數(shù)位寬必須大于等于除數(shù)位寬。

2、當(dāng)error為高電平時(shí),表示輸入除數(shù)為0,此時(shí)輸出的商和余數(shù)均為0且無效。 3、只有當(dāng)quotient_vld為高電平時(shí),模塊輸出的商和余數(shù)才是有效的。

4、只有當(dāng)模塊處于空閑(ready為高電平)時(shí),外部輸入的start和除數(shù)、被除數(shù)才能有效。 如果需要源文件,在公眾號(hào)后臺(tái)回復(fù)“基于FPGA的除法器”(不包括引號(hào))即可。由于我只使用vscode和modelsim對(duì)工程進(jìn)行仿真,所以沒有vivado和quartus工程。下面視頻就是通過vscode調(diào)用modelsim進(jìn)行仿真的視頻。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1650

    文章

    22222

    瀏覽量

    628150
  • 計(jì)數(shù)器
    +關(guān)注

    關(guān)注

    32

    文章

    2304

    瀏覽量

    97344
  • 除法器
    +關(guān)注

    關(guān)注

    2

    文章

    15

    瀏覽量

    14101
  • 狀態(tài)機(jī)
    +關(guān)注

    關(guān)注

    2

    文章

    497

    瀏覽量

    28725

原文標(biāo)題:基于FPGA的高效除法器

文章出處:【微信號(hào):FPGA研究院,微信公眾號(hào):FPGA研究院】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于FPGA除法器純邏輯設(shè)計(jì)案例

    除法運(yùn)算。很多人覺得不就是除法嘛,直接打上/即可,但是,FPGA是不能正確綜合這個(gè)除法器的,綜合的結(jié)果只是一個(gè)固定數(shù)值,而不像其他微處理器??梢赃@么說,用
    的頭像 發(fā)表于 06-17 10:17 ?8138次閱讀
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>除法器</b>純邏輯設(shè)計(jì)案例

    除法器工作原理介紹

    二進(jìn)制除法器的本質(zhì)是多次減法,直到余數(shù)小于除數(shù)為止。對(duì)應(yīng)的兩個(gè)N bit二進(jìn)制數(shù)的除法算法如下。 1、設(shè)置2N bit寄存器A的低N位存放被除數(shù),設(shè)置2N bit寄存器B的高N位存放除數(shù),設(shè)置N
    發(fā)表于 10-21 08:32

    如何對(duì)蜂鳥e203內(nèi)核乘除法器進(jìn)行優(yōu)化

    控制邏輯:除法器控制邏輯設(shè)計(jì)合理與否直接影響到除法器的性能表現(xiàn),因此可以優(yōu)化除法器控制邏輯,如增加硬件控制邏輯、優(yōu)化狀態(tài)轉(zhuǎn)移邏輯等,可以有效提高除法器的效率。 采用更
    發(fā)表于 10-24 06:47

    ise的除法器modelsim仿不了?

    `大蝦們,小女子最近調(diào)程序的時(shí)候用到了ise ip core的除法器,但是調(diào)用modelsim仿真的時(shí)候發(fā)現(xiàn)木有進(jìn)行除法啊,單獨(dú)寫了個(gè)除法器也還是用不了,這是什么情況呢?(vhdl寫的程序哈)`
    發(fā)表于 06-15 11:52

    基于FPGA除法器

    定點(diǎn)除法器的輸出是商和余數(shù)的形式,但是我想讓他表示成小數(shù)的形式(因?yàn)樽詈笠偷綌?shù)碼管顯示),該怎么裝換?求大神,給點(diǎn)思路也可以!總共是8位顯示,而整數(shù)部分和小數(shù)部分的位數(shù)不定?怎么設(shè)計(jì)
    發(fā)表于 05-15 20:01

    高速硬件除法器

    這是一個(gè)高速硬件除法器,要求畫出此硬件的除法器的工作流程圖。說明其工作原理特別是高速原理。要求有仿真時(shí)序波形圖并說出說明在fpga上驗(yàn)證器硬件功能。
    發(fā)表于 12-17 09:10

    除法器的設(shè)計(jì)資料分享

    4.3 實(shí)例九 除法器設(shè)計(jì)4.3.1. 本章導(dǎo)讀要求掌握除法器原理,并根據(jù)原理設(shè)計(jì)除法器模塊以及設(shè)計(jì)對(duì)應(yīng)的測(cè)試模塊,最后在 Robei可視化仿真軟件經(jīng)行功能實(shí)現(xiàn)和仿真驗(yàn)證。設(shè)計(jì)原理這個(gè)除法器
    發(fā)表于 11-12 07:03

    并行除法器 ,并行除法器結(jié)構(gòu)原理是什么?

    并行除法器 ,并行除法器結(jié)構(gòu)原理是什么?   1.可控加法/減法(CAS)單元    和陣列乘法器非常相似,陣列式除法器也是一種并行運(yùn)算部件,采用大規(guī)模集成
    發(fā)表于 04-13 10:46 ?1.6w次閱讀

    除法器對(duì)數(shù)運(yùn)算電路的應(yīng)用

    除法器對(duì)數(shù)運(yùn)算電路的應(yīng)用 由對(duì)數(shù)電路實(shí)現(xiàn)除法運(yùn)算的數(shù)學(xué)原理是:
    發(fā)表于 04-24 16:07 ?3061次閱讀
    <b class='flag-5'>除法器</b>對(duì)數(shù)運(yùn)算電路的應(yīng)用

    AD734:10 MHz四象限乘法器/除法器數(shù)據(jù)表

    AD734:10 MHz四象限乘法器/除法器數(shù)據(jù)表
    發(fā)表于 05-15 10:18 ?12次下載
    AD734:10 MHz四象限乘<b class='flag-5'>法器</b>/<b class='flag-5'>除法器</b>數(shù)據(jù)表

    簡(jiǎn)化合成器的有源乘法器除法器

    簡(jiǎn)化合成器的有源乘法器除法器
    發(fā)表于 05-16 17:15 ?9次下載
    簡(jiǎn)化合成器的有源乘<b class='flag-5'>法器</b>和<b class='flag-5'>除法器</b>

    實(shí)例九— 除法器設(shè)計(jì)

    4.3 實(shí)例九 除法器設(shè)計(jì)4.3.1. 本章導(dǎo)讀要求掌握除法器原理,并根據(jù)原理設(shè)計(jì)除法器模塊以及設(shè)計(jì)對(duì)應(yīng)的測(cè)試模塊,最后在 Robei可視化仿真軟件經(jīng)行功能實(shí)現(xiàn)和仿真驗(yàn)證。設(shè)計(jì)原理這個(gè)除法器
    發(fā)表于 11-07 10:51 ?18次下載
    實(shí)例九— <b class='flag-5'>除法器</b>設(shè)計(jì)

    FPGA常用運(yùn)算模塊-除法器

    本文是本系列的第四篇,本文主要介紹FPGA常用運(yùn)算模塊-除法器,xilinx提供了相關(guān)的IP以便于用戶進(jìn)行開發(fā)使用。
    的頭像 發(fā)表于 05-22 16:20 ?5212次閱讀
    <b class='flag-5'>FPGA</b>常用運(yùn)算模塊-<b class='flag-5'>除法器</b>

    FPGA基于線性迭代法的除法器設(shè)計(jì)

    FPGA實(shí)現(xiàn)除法的方法有幾種,比如直接用/來進(jìn)行除法運(yùn)算,調(diào)用IP核進(jìn)行除法運(yùn)算,但這兩種方式都有個(gè)共同的問題——都是黑盒子,在進(jìn)行時(shí)序違例處理時(shí),往往不好操作,比如想打打拍改善下時(shí)序
    的頭像 發(fā)表于 07-04 10:03 ?1991次閱讀
    <b class='flag-5'>FPGA</b>基于線性迭代法的<b class='flag-5'>除法器</b>設(shè)計(jì)

    使用IAR IDE仿真RL78內(nèi)置硬件乘法器除法器注意事項(xiàng)

    使用IAR IDE仿真RL78內(nèi)置硬件乘法器除法器注意事項(xiàng)
    的頭像 發(fā)表于 10-30 17:04 ?1993次閱讀
    使用IAR IDE仿真RL78內(nèi)置硬件乘<b class='flag-5'>法器</b>和<b class='flag-5'>除法器</b>注意事項(xiàng)