iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
Software Development

數位 IC 設計起手式系列 第 24

Day 24: Generate 家族成員

  • 分享至 

  • xImage
  •  

Generate 是個很強大的語法。

在寫 Verilog 時,我最討厭的狀況是:(以 Pseudocode 表示)

if (cond == True)
    ic1 a(...);
else 
    ic2 b(...);

簡單來說,我們會根據不同的狀況實體化不同的模組 (i.e. ic1, ic2) ,但是 if, else 必須被放置在 initial, always blocks 中。不只如此,initial, always blocks 內部是不能進行模組實體化的。因此上述的 Pseudocode 在 Verilog 中是不可行的。當然我們可以透過組合電路歸納出條件式的關係,但是那會相當麻煩。Generate 的其中一項功能就是解決上述 Pseudocode 所表達的事情!

為什麽 Generate 可以達成原本不可能的事情?
程式真正被處理的時間有兩個,一個就是大家理想狀況下的程式執行,另一種是執行前的預先處理。Generate 就是在執行前被預先處理的。而在執行開始時,所有電路元件都會被設計與置放完成,這樣就不會影響到原本的行為了!

Generate 共包含 3 種模式:

  1. Generate Conditional
  2. Generate Case
  3. Generate Loop

Generate Conditional

Conditional 就是「條件的」,用 C 語言的語法來說就是 if, else。

Verilog HDL: A Guide to Digital Design and Synthesis 這本書中提到了一個很實用的例子,想藉由這個機會和大家分享。這份程式碼的大意是說題目給了兩個數字,如果其中一個數子的位元數少於 8 位元,就使用 CLA 乘法器,否則就使用 Tree 乘法器。為什麼說實用?因為使用不同乘法器會有不同的效能,如果數字很大,但是使用了沒有被優化過的乘法器,後果可想而知。因此我們會先透過 Generate Conditional 來判定該時作何種硬體。

module multiplier (product, a0, a1);

    parameter a0_width = 8; // 8-bit bus by default
    parameter a1_width = 8; // 8-bit bus by default

    localparam product_width = a0_width + a1_width;

    output [product_width -1:0] product;
    input [a0_width-1:0] a0;
    input [a1_width-1:0] a1;

    generate
    if (a0_width <8) || (a1_width < 8)
        cla_multiplier #(a0_width, a1_width) m0 (product, a0, a1);
    else
        tree_multiplier #(a0_width, a1_width) m0 (product, a0, a1);
    endgenerate //end of the generate block
endmodule

程式碼中除了使用 generate ,還提到 parameter, localparam (這部分我們會在之後的章節提及) 等。透過這種組合,我們的電路更加的完善,因為電路變得可以透過賦予參數來產生不同的樣貌,而不是一開始就需要指定的。

補充: 不知道大家會不會好奇什麼是 Tree 乘法器?有興趣的同學可以參考 維基百科
Wallace Tree 是一種加速二進位乘法的硬體設計,他最主要的原理就是使用半加器和全加器來產生 Sum, Carry 。Wallace Tree 也可以視為 3 to 2 compressor ,因為在過程中,我們每此都取 3 行結果進行處理,處理後會得到 2 行,分別為 Sum Row, Carry Row 。如此不斷下去,我們可以得到最終的乘積。

Generate Case

既然 if, else 可以搭配 generate 來使用,case 也可以這麼做!

假設我們有多種計數器,但是根據不同情況,我們使用不同種計數器,範例如下:

generate
    case (N) 
        0: johnson j(...);
        1: mod5 m1(...);
        2: mod6 m2(...);
        ...
        default: ring r(...);
    endcase
endgenerate

Generate Loop

還有一種狀況是我們必須要重複實體化一樣的模組許多次,與 if, else 相同的是, for loop 內部無法實體化模組,因為他們存在於 initial, always loop 之中。因此我們會借用 generate 來完成這件事。

舉例來說,我們實作 Ripple Carry Adder 就可以透過這種方式來執行。大致上可以歸納兩個優點:

  1. 可以透過 N 來決定,這個加法器支援幾位元的加法
  2. 透過迴圈來幫助簡化實體化全加器所需的程式碼
genvar i;
generate for (i = 0; i < N; i++) begin
        Fadder f0(...);
    end
endgenerate

上一篇
Day 23: Sequential & Parallel
下一篇
Day 25: 參數式模組
系列文
數位 IC 設計起手式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言