[文檔].艾米電子 – 多路選取器與多路分解器,Verilog

來源:互聯網
上載者:User
文章目錄
  • 1 多路選取器Multiplexer
  • 1.2 帶優先順序的多路選取器
  • 輔助閱讀
  • 參考
對讀者的假設

已經掌握:

  • 可程式化邏輯基礎
  • Verilog HDL基礎
  • 使用Verilog設計的Quartus II入門指南
  • 使用Verilog設計的ModelSIm入門指南

 

內容1 多路選取器Multiplexer

此處所說的多路選取器,為組合邏輯電路中的多路多路選取器:多路輸入,一路輸出。

 

1.1 不帶優先順序的多路選取器1.1.1 使用case語句描述

此處以4選1多路選取器為例:

 

代碼1.1 4選1多路選取器(可綜合)

`timescale 1ns/1nsmodule multiplexer(  input iA,  input iB,  input iC,  input iD,  input [1:0] iSel,  output reg oQ  );always @ (*)   case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;    2'b11 : oQ = iD;  endcaseendmodule

 

第10~16行,使用case語句來實現4選1多路選取器。因為是2^n個case選項,所以此處沒有使用default語句。下面我會使用一個3選1的多路選取器來說明default的作用。

always @ (*)   case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;    2'b11 : oQ = iD;  endcase

 

圖1.1 4選1多路選取器的RTL視圖

 

由圖1.1所示,在2^n個case選項時,沒有加上default語句,其綜合的結果為並行的MUX。

 

代碼1.2 4選1多路選取器testbench(不可綜合,僅用於模擬)

`timescale 1ns/1nsmodule multiplexer_tb;reg i_a, i_b, i_c, i_d;reg [1:0] i_sel;wire o_q; initial begin  i_a = 1; i_b = 0; i_c = 0; i_d = 0;  #20 i_a = 1; i_b = 0; i_c = 1; i_d = 1;  #20 i_a = 0; i_b = 0; i_c = 1; i_d = 0;  #20 i_a = 1; i_b = 1; i_c = 1; i_d = 0;end initial begin  i_sel = 2'b00;  #20 i_sel = 2'b01;  #20 i_sel = 2'b10;  #20 i_sel = 2'b11;  #20 $stop;end multiplexer multiplexer_inst(  .iA    (i_a),  .iB    (i_b),  .iC    (i_c),  .iD    (i_d),  .iSel  (i_sel),  .oQ    (o_q) ); endmodule

 

第3~5行聲明了一些變數,使用的標準為:映射為所需測試模組的輸入訊號,即需要使用initial或always來給出激勵,因此多聲明為reg類型;而映射為所需測試模組的輸出訊號,不需要激勵,聲明為wire類型即可。

reg i_a, i_b, i_c, i_d;reg [1:0] i_sel;wire o_q;

 

第21行,$stop表示模擬在此時刻終止。更多$打頭的函數,請參考Verilog文法書。

#20 $stop;

 

圖1.2  4選1多路選取器的功能模擬波形

 

圖1.3  4選1多路選取器的門級模擬波形

 

由圖1.2和圖1.3所示,在2^n個case選項時,沒有加上default語句,其功能模擬和門級模擬保持一致。

 

1.1.2 怎麼多出個鎖存器?

此處以3選1多路選取器為例。

 

代碼1.3 3選1多路選取器1(可綜合)

module multiplexer(  input iA,  input iB,  input iC,  input [1:0] iSel,  output reg oQ  );always @ (*)   case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;  endcaseendmodule

 

圖1.4 3選1多路選取器1的RTL視圖

 

1.4所示,綜合出來了鎖存器。下面我們討論如何消除這個鎖存器。

 

方法1 加(* full_case *)修飾

 

代碼1.4 3選1多路選取器2(可綜合)

module multiplexer(  input iA,  input iB,  input iC,  input [1:0] iSel,  output reg oQ  );always @ (*)   (* full_case *) case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;  endcaseendmodule

 

第10行,加(* full_case *)修飾,強制綜合成full case。

(* full_case *) case (iSel)

 

圖1.5 3選1多路選取器2的RTL視圖

 

方法2 使用default語句

 

代碼1.5 3選1多路選取器3(可綜合)

module multiplexer(  input iA,  input iB,  input iC,  input [1:0] iSel,  output reg oQ  );always @ (*)   case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;    default: oQ = 1'b0;  endcaseendmodule

 

第14行,加上default語句,來描述預設動作。

    default: oQ = 1'b0;

 

圖1.6 3選1多路選取器3的RTL視圖

 

方法3 在敏感列表後,賦初值

代碼1.6 3選1多路選取器4(可綜合)

module multiplexer(  input iA,  input iB,  input iC,  input [1:0] iSel,  output reg oQ  );always @ (*)begin  oQ = 1'b0;  case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;  endcaseendendmodule

 

注意第9~17,在代碼1.3的基礎上,于敏感列表之後,加入oQ的初值。

always @ (*)begin  oQ = 1'b0;  case (iSel)    2'b00 : oQ = iA;    2'b01 : oQ = iB;    2'b10 : oQ = iC;  endcaseend

 

圖1.7 3選1多路選取器4的RTL視圖

 

方法123的比較

代碼1.7 3選1多路選取器的testbench(不可綜合,僅用於模擬)

`timescale 1ns/1nsmodule multiplexer_tb;reg i_a, i_b, i_c;reg [1:0] i_sel;wire o_q;initial begin  i_a = 0; i_b = 0; i_c = 0;  #20 i_a = 1; i_b = 0; i_c = 0;  #20 i_a = 1; i_b = 0; i_c = 1;  #20 i_a = 0; i_b = 0; i_c = 1;  #20 i_a = 1'bx; i_b = 1'bx; i_c = 1'bx;endinitial begin  i_sel = 2'bxx;  #20 i_sel = 2'b00;  #20 i_sel = 2'b01;  #20 i_sel = 2'b10;  #20 i_sel = 2'b11;  #20 $stop;endmultiplexer multiplexer_inst(  .iA    (i_a),  .iB    (i_b),  .iC    (i_c),  .iSel  (i_sel),  .oQ    (o_q) );endmodule

 

圖1.8 方法1的功能模擬波形

 

圖1.9 方法1的門級模擬波形

 

由圖1.8和圖1.9所示,雖然方法1加了(* full_case *)修飾後,3選1多路選取器的綜合結果沒有產生鎖存器,但是其功能模擬波形卻當作鎖存器來處理,而其門級模擬波形則是當作無關項來處理。即方法1,其前後模擬結果是不一致的。至於其他的特點,本文暫不討論。想要瞭解更多full case的資訊,請閱讀參考2。

 

圖1.10 方法2的功能模擬波形

 

圖1.11 方法2的門級模擬波形

 

1.10和1.11所示,方法2使用了default語句,其前後模擬和綜合的RTL視圖一致。蕭鴻森大哥提醒我們:正確的做法是,default指定輸出0或者某個選項。

 

 

圖1.12 方法3的功能模擬波形

 

圖1.13 方法3的門級模擬波形

 

1.12和1.13所示,方法3在敏感列表後,賦初值也可以很好解決鎖存器的問題。

 

1.1.3 結論

雖然方法123都可以解決鎖存器的問題,但是:方法1的前後模擬結果不同;方法3的其他特點暫時沒有研究。因此此處只推薦大家使用方法2,即要實現並行的mux,當case選項不是2^n個的時候,加上default指定輸出0或某個選項是最安全的(雖然Verilog文法沒有強制加入default)。

 

1.2 帶優先順序的多路選取器1.2.1 使用if-else-if描述

此處以3選1多路選取器為例。

代碼1.8 使用if-else-if描述的3選1多路選取器(可綜合)

module multiplexer(  input iA,  input iB,  input iC,  input [1:0] iSel,  output reg oQ  );always @ (*)   if (iSel == 2'b0)     oQ = iA;  else if (iSel == 2'b01)     oQ = iB;  else    oQ = iC;endmodule

 

第9~15行,使用if-else-if描述帶優先順序的多路選取器。有人看到My Code會有一點小疑問?為什麼always塊沒有加begin-end的。其實呢這個begin-end就相當於C語言裡面的{},與C語言類似,當後面的語句條數為1時,可以省略begin-end。而if-else-if恰好為一個完整的語句。

always @ (*)   if (iSel == 2'b0)     oQ = iA;  else if (iSel == 2'b01)     oQ = iB;  else    oQ = iC;

 

圖1.14 使用if-else-if描述的3選1多路選取器的RTL視圖

 

1.2.2 使用“: ?”描述

既然使用if-else-if可以描述帶優先順序的多路選取器,那麼使用“: ?”當然也是可行的。

 

代碼1.9 使用“: ?”描述的3選1多路選取器(可綜合)

module multiplexer(  input iA,  input iB,  input iC,  input [1:0] iSel,  output oQ  );assign oQ = (iSel == 2'b00) ? iA :            (iSel == 2'b01) ? iB : iC;            endmodule

 

第9~10行,使用“: ?”描述帶優先順序的多路選取器。

assign oQ = (iSel == 2'b00) ? iA :            (iSel == 2'b01) ? iB : iC;

 

實際上等同於,為什麼使用上面這種寫法呢?因為“: ?”的運算優先順序比較低,所以不必加括弧。

assign oQ = (iSel == 2'b00) ? iA :            ((iSel == 2'b01) ? iB : iC);

 

 

 

 

注意:第6行的聲明,由於是使用assign語句賦值,因此無需聲明成reg類型。

  output oQ  

 

圖1.15 使用“: ?”描述的3選1多路選取器的RTL視圖

 

1.15所示,使用“: ?”描述多路選取器與if-else-if描述完全一致,因此兩種描述方式可以互換。

 

2 多路分解器De-Multiplexer

多路分解器,也叫資料選取器,顧名思義即多路輸入,一路輸出。有了前面的基礎,那麼描述一個多路分解器,便是輕而易舉事情了。

 

代碼2.1 使用case描述多路分解器

module de_multiplexer(  input iA,  input [1:0] iSel,  output reg oQ_0,  output reg oQ_1,  output reg oQ_2);always @ (*)begin  oQ_0 = 1'b0;  oQ_1 = 1'b0;  oQ_2 = 1'b0;  case (iSel)    2'b00 : oQ_0 = iA;    2'b01 : oQ_1 = iA;    2'b10 : oQ_2 = iA;    default : ;  endcaseendendmodule

 

第9~20行,在敏感列表後,追加初始值,可以有效地避免產生鎖存器。

always @ (*)begin  oQ_0 = 1'b0;  oQ_1 = 1'b0;  oQ_2 = 1'b0;  case (iSel)    2'b00 : oQ_0 = iA;    2'b01 : oQ_1 = iA;    2'b10 : oQ_2 = iA;    default : ;  endcaseend
 

圖2.1 代碼2.1綜合後的RTL視圖

 

代碼2.2 代碼2.1的testbench

`timescale 1ns/1nsmodule de_multiplexer_tb;reg i_a;reg [1:0] i_sel;wire o_q_0, o_q_1, o_q_2;initial begin  i_a = 0;  forever #10 i_a = ~i_a;end initial begin  i_sel = 2'b00;  #20 i_sel = 2'b01;  #20 i_sel = 2'b10;  #20 i_sel = 2'b11;  #20 $stop;end de_multiplexer de_multiplexer_inst(  .iA(i_a),  .iSel(i_sel),  .oQ_0(o_q_0),  .oQ_1(o_q_1),  .oQ_2(o_q_2));endmodule

 

圖2.1 代碼2.1的功能模擬波形

 

圖2.2 代碼2.1的門級模擬波形

 

圖2.1和圖2.2的所示波形與代碼2.1一致。

 

輔助閱讀

1. Wikipedia.Multiplexer

 

參考

1. 劉福奇, 劉波.Verilog HDL應用程式設計執行個體精講.電子工業出版社

2. Cliff Cummings' Award-Winning Verilog & SystemVerilog Papers. "full_case parallel_case", the Evil Twins of Verilog Synthesis

3. 蕭鴻森.(原創) 多工器MUX coding style整理 (SOC) (Verilog) (Quartus II)

4. Altera.Recommended HDL Coding Styles.General Coding Guidelines

 

另見

[與艾米一起學FPGA/SOPC].[邏輯實驗文檔連載計劃]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.