2013年6月16日 星期日

硬體設計與軟體設計的不同思維

自己開始認真寫blog到現在約一年,總瀏覽人數大概6k,最多人看的,還是verilog的相關文章,顯然大家對這個莫名奇妙的語言都充滿了疑惑與不解。

最近正在寫一個verilog的作業,主要是要用verilog檢查8*8的candycrush有幾個步數是可以移動的,大概花了兩個小時,雖然寫出來的硬體很糟;但一方面發現自己verilog沒忘,另一方面也用這個例子,談談硬體設計與軟體設計差異之處。
這個問題,用軟體來寫實在滿簡單的,把陣列讀進來之後,只要用幾個for loop,把可能的狀況跑一次就是了,對一位有經驗的程式設計式來說,也許不用幾分鐘就能寫完。

但硬體設計來說,狀況就不一樣了。

--

我認為硬體設計的思維,必須從clock,前幾篇文所提到三大塊設計方式的角度下去想,這個模式和軟體有點差距,也造成很多從軟體轉到硬體設計人,有時就轉不過來,想不透為何硬體要這樣寫。
以這個candycrush為例,就我知道,有些人的判斷式是這樣寫的:
integer i;
...
case(state)
DOWN:begin
   for(i=0;i<40;i=i+1) begin
      count_num = ( (map[i]==map[i+1]&&map[i+3]==map[i] || map[i]==map[i+2]&&map[i+3]==map[i]) && i%8<6 )? count_num+1:count_num;
   end
end
簡單來說,在state為DOWN的時候,判斷 i這格糖果,和右邊一格、三格或是兩格、三格是否一樣(按:這個部分應該是原作者打錯,state應該是RIGHT),是的話就讓count_num加一。
看起來很合理,以軟體角度來說,不就是i=0,1...39,每次就檢查上面的判斷式?

這就是思維不同的地方,硬體設計你寫什麼,它都是同時進行的,combination circuit無時無刻把接到的資料進行邏輯運算並輸出;你如果希望某個行為和時間有關,希望它依序進行的東西,絕對都跟clock和sequencial circuit有關。
原作者可能是沒查過for loop在verilog內的意義為何,但for loop這個語法是combination circuit的一部分,實際上for loop在verilog內會被平行的展開,編譯器會自動把for loop內的code全部依for loop 變數展開,上面的寫法實際上大約等價於:

( (map[0]==map[1]&&map[3]==map[0] || map[0]==map[2]&&map[3]==map[0]) && 0%8<6 )? count_num+1:count_num; 
( (map[1]==map[2]&&map[4]==map[1] || map[1]==map[3]&&map[4]==map[1]) && 1%8<6 )? count_num+1:count_num;
下略38行。
於是當state進到DOWN時,count_num被平行輸入40個combination circuit中,每一個都有不同的判斷條件,有些加一,有些維持原值,然後要寫回到count_num裡,這下就天下大亂了(按,據說這個code最後無法合成到gate level)。
如果用我在三大塊中的例子:
Combinational circuit就像馬路,負責讓車(信號)流動,改變車道(運算)
Sequential circuit則像紅綠燈,負責管理信號什麼時候可以通行,到下一個combinational circuit。

這裡for loop的寫法,就像你要一位駕駛,每過一個紅綠燈就喝一種飲料,總共要喝40種;結果你把40支紅綠燈插在同一個路口,駕駛就得喝大雜燴了。

--

原作者的意思,應該是for loop展開的每一行,依序判斷,寫出結果到count_num中。
依序->和時間有關->請用sequential 電路和clock。
真正合理的寫法,是用另一個變數phase,在state DOWN從0加到39,這些動作才會依時間維度展開,而不是直接平行展開。
關鍵的幾行code大概是:
//count_num
if(state == DOWN) begin
( (map[phase]==map[phase+2]&&map[phase+3]==map[phase] || map[phase]==map[phase+1]&&map[phase+3]==map[phase]) && phase%8<6 )? count_num+1:count_num;
end
//phase
phase_next = (phase==39)? 0 : phase+1;
//state
state_next = (state==DOWN && phase==39): UP: DOWN;
隨隨便便打了這些,好像還是沒說到我想講的概念;簡單來說,硬體裡和時間有關的概念,一定都要歸到sequential的部分去;硬體設計是完全的一個口令一個動作,想像for loop裡的變數 i,在每一次clock來的時候加一,i不同時電路才有不同的行為,希望這樣的想法能對各位辛苦的電路人有幫助。