iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
Software Development

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

Day 23: Sequential & Parallel

  • 分享至 

  • xImage
  •  

不知道大家會不會好奇 begin, end 是做什麼的?只是單純要去區分各個區塊,就像是 C 語言的 { } 嗎?

其實沒有那麼簡單!過去我們都是使用 Sequential Block ,所以我們的程式碼才會由上而下執行。還有一種叫做 Parallel Block ,內部的程式碼都是同時進行。

Sequential Block

先從我們熟悉的 Sequential Block 說起。這種程式區塊有三個特性:

  1. 程式區塊由 begin, end 兩個關鍵字定義。
  2. 程式執行順序為由上而下執行。
  3. 時間延遲 (e.g. #3) 是相對於上一行執行的程式。

舉例來說:

initial begin
    #5 <statement 1>
    #1 <statement 2>
    #3 <statement 3>
    #2 <statement 4>
end

這段程式碼就是屬於 Sequential Block ,因為他們被 begin, end 包起來。再來看看執行順序,<statement 1> 先經過 5 個時間單位再執行,接著再換 <statement 2> 延遲後執行,以此類推。最終,<statement 4> 相對程式區塊開始時間後 11 個時間單位才被執行。

這類型程式相信大家在前面的案例中,已經見過許多!

Parallel Block

再來就是我們不熟悉的 Parallel Block 。這種程式區塊有四個特性:

  1. 程式區塊由 fork, join 兩個關鍵字定義。
  2. 程式執行順序為所有程式同時執行。
  3. 時間延遲 (e.g. #3) 是相對於程式區塊開始時間。
  4. 程式碼撰寫順序不影響執行順序。

一樣用上面的例子來說明:

initial fork
    #5 <statement 1>
    #1 <statement 2>
    #3 <statement 3>
    #2 <statement 4>
join

這段程式碼就是屬於 Parallel Block ,因為他們被 fork, join 包起來。再來看看執行順序,<statement 1> 先經過 5 個時間單位再執行,但是 <statement 2> 只需經過 1 個時間單位的延遲就可以執行,因此 <statement 2> 較 <statement 1> 更早被執行,以此類推。

Parallel Block 有一個需要克服的問題就是 Race Condition ,一旦有數條具相互關係的程式碼出現,我們無法預期結果為何,因為在現實中,中央處理器 (CPU) 一次只能處理一個指令,因此誰會先被執行,是無法預期的。舉一個例子:

reg x, y, z;
initial fork
    x = y;
    y = z;
    z = x;
join

Blocks 的補充

Nested Blocks

Nested Blocks 翻成中文是「巢狀區塊」,意思是我們可以在區塊中放置其他區塊。舉例來說:

initial begin
    <statement>
    <statement>
    fork
        <statement>
        <statement>
    join
end

這個功能強化了電路設計的彈行,也許我們的電路想要有一部分是平行處理的,那麼我們就可以將兩種 Blocks 混合做使用,而不是只使用單一種電路。

Named Blocks & Disabling

為什麼我們需要對程式區塊命名?有一個主要的原因是我們有可能需要終止一個區塊的運行。

在 C 語言中,我們想要結束一個程式區塊的運行,會透過關鍵字 break 來執行這個動作,但是 break 只能強制停止它所在的程式區塊。在 Verilog 中,可以透過關鍵字 disable 來停止程式區塊,而且我們可以強至其他程式區塊的運行,相比軟體設計的 break , Verilog 的 disable 更為強大。

先從區塊命名開始,簡單來說就是在 begin 或是 fork 後面加上區塊名字,舉個例子:

initial fork: block1
    <statement>
    <statement>
join
always begin: block2
    <statement>
    <statement>
end

有了名字,我們就可以來終止區塊運行。假設我們要比對兩個 reg 所儲存的數值是否一樣,我們可以這麼做:

reg [3:0] a, b;
    integer i;
    initial begin: block1
        a = 4'b1010; b = 4'b1110;
        i = 0;
        while (i < 4) begin
            if (a[i] == b[i]) 
                $display("a[%1d] = b[%1d] = %1d", i, i, a[i]);
            else begin
                $display("a[%1d] = %1d, b[%1d] = %1d", i, a[i], i, b[i]);
                disable block1;
            end
            i = i + 1;
        end
        $display("Same!!");
    end

在這個例子中,我們可以透過 disable 來決定是否要繼續執行迴圈。如果繼續執行迴圈雖然也沒有問題,但是我們會花費不必要的資源和時間,因此 disable 在這裡扮演很重要的角色。

結語

到目前為止,我們建構了較完整的程式區塊相關概念,相信大家能更加靈活的設計不同種電路。


上一篇
Day 22: 迴圈大禮包
下一篇
Day 24: Generate 家族成員
系列文
數位 IC 設計起手式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言