2014年9月18日 星期四

timing loop和combinational loop的不同

真是抱歉! 最近公司的事情比較多,所以就比較沒有時間寫新文章分享!

今天是要分享一下,在合成時,我們會遇到的兩個廻圈電路問題。

在合成時,合成器會告訴你,你的程式在合成電路時,是否會有迴圈電路產生。一個是循序廻圈電路(timing loop circuit),另一個是邏輯廻圈電路(combinational loop circuit)。比較常聽到的是邏輯廻圈電路,比較少聽到循序廻圈電路。而一般來說,也很難在合成階段才看到邏輯廻圈電路的錯誤訊息。因為在合成電路以前,你會跑很多軟體來驗證RTL code,它們都會將邏輯廻圈電路錯誤告訴你,修正這個錯誤。所以合成階段就會很少看到,但是合成器是有能力驗證出邏輯廻圈電路的錯誤的。大家要知道這件事實。

循序廻圈電路問題:是雞生蛋、蛋生雞的問題。為什麼會這麼說?之後的圖示,你應該就會看出來原因。合成器會告訴你這個是警告(warning) 訊息,然把這個路徑條列出來。合成器列出來的路徑通常都是在clock path

邏輯廻圈電路:是無窮廻圈問題。合成器會告訴你這個是錯誤(Error) 訊息。

循序廻圈電路和邏輯廻圈電路是不一樣的事件。邏輯廻圈電路是同一時間無窮廻圈,這是一個嚴重的錯誤程式設計行為,所以一定要修正。而循序廻圈電路是不同一時間無窮廻圈,所以不一定要修正,但是要知道。

什麼是循序廻圈電路?什麼是邏輯廻圈電路?下面的圖示可以明顯告訴你。

Fig1: 循序廻圈電路


Fig2: 邏輯廻圈電路



循序廻圈電路用白話一點的解釋,我需要有一個clock domain,來讓循序邏輯選擇使用哪一個clock?但因為還沒有決定clock ,所以還不能選擇使用哪一個clock?因為沒有選擇使用哪一個clock,所以就沒有clock domain可以來決定?因為沒有clock domain,所以就沒有辦法選擇使用哪一個clock?就這樣子,一直得廻圈。
邏輯廻圈電路相信大家就更了解了,就不多做說明。

下面貼一張合成器的警告訊息

解決的方法有:
1. 設定clock的起始點在pA點上,不要在clk0clk1
2. set_case_analysis,強制設定clk_sel的值。

其實,這是一個警告訊息,或許有人會告訴你這不影響合成電路的結果,不用理它。Timing_loop確實是一個不會影響合成電路正確性的警告訊息;但是如果它完全不會有任何影響,為什麼合成器要顯示這個訊息出來?它想「善意」地提醒工程師什麼事情呢?
換另一個的角度來思考;用程式寫出來的電路,我們是否已有預期知道會有一個廻圈電路產生?如果有,是不是就可以利用這個警告訊息來驗證我們的想法和路徑。如果沒有,我們也可以用這個警告訊息來了解到底是哪一個環節出忽意料之外,產生我們所無法預期的行為。
另外,利用set_case_analysis來讓警告訊消息的方式,也是可以讓我們知道廻圈的癥結點是否已經被完全掌握?如果沒有,我們就可以利用這個警告訊息,知道原來還有些電路是我們所不知道的。我們就可以再深入了解,以期望能百分百掌握電路。

很多工程師都忽視Design Compiler的警告訊息,我覺得這不是一個好現象。數位工程師本來就需要很多軟體的輔佐,來讓自己寫出沒有錯誤且穩定的電路。這些警告訊息其實也是一種輔佐方法,讓工程師更了解自己的電路,而不是只用simulator來了解電路。接受各種軟體的不同訊息,可以讓你對RTL coding的掌握度更高。說不定,有時候還可以得到不一樣的程式經驗。






2014年7月28日 星期一

堆疊IC的IC design flow分享

在半導體領域中,目前還滿熱門的話題就是堆疊IC(3D IC),堆疊IC的主要技術有封裝以及TSV兩種方面。技術瓶頸突破主要是在封裝廠以及晶圓廠。做為一個數位工程師,他能做得是什麼?
不管是堆疊封裝還是TSV,在技術上,數位工程師都是無法著墨。雖然無法做為一個主要角色,但做為一個輔助角色而言,數位工程師是絕對能幫得上忙的。
堆疊IC是一個新的方法、新的觀念。目前已知可以堆疊的介面選擇有很多,例如:DDR3, LPDDR2,PHY的介面等等,堆疊的方法也有很多,例如:利用 TSV技術找到新的堆疊面,或是兩個IC面對面的堆疊等等。依目前現況,堆疊的測試沒有統一的方法或是標準。目前已經有人在努力制定標準或是概念,相信在不久的將來,或許會有一個新的協定發展出來,而人們可以經過這個協定測試各種不同堆疊方式做出來的IC

在做堆疊IC之前,首先我們要先有一些通俗的概念,然後我們再去探討問題是什麼?再過來才去找可能的答案有哪些?
堆疊IC的通俗概念。

1. 堆疊IC前,要先找到一顆好的IC來堆疊。
2. 堆疊IC的堆疊介面一定要符合要求,才能拿來堆疊。
3. 堆疊IC封裝後,要能確認裏面的IC都是好的,尤其是堆疊的介面。

以上兩點,相信大家應該都能清楚明白。

針對以上想法,整理應該做的測試項有哪些?

4. 在堆疊前,測試IC的電路是否完整的?
        基本的function都要能運行,速率也要能達到要求。就目前單顆IC測試方法而言,相信已經有很多成熟的方法可以確保這件事情。
5. 在堆疊前,IC的堆疊介面速率是否符合要求?

        如果堆疊介面速率需要在1GHz下運行,在堆疊前,首先要確認IC的堆疊介面是否可以1GHz下運行,如果不行,就不能拿來堆疊。不然,花了一大筆錢,做出一堆不符合要求的堆疊晶片,不就白費功夫。

有些人堆疊IC不做TSV,有些人要做。如果你有做TSV的話,在做完TSV後,還是要再次確認IC的狀態。

6. TSV後,測試IC的電路是否完整的?
7. TSV後,IC的堆疊介面速率是否符合要求?
8. 新做的TSV介面是否有導通?

之後我們開始做堆疊,然後封裝。封裝後,我們要確認以下的項目,才能確保晶片的品質。

9. 堆疊後,確認每個IC的內部電路是否完整的?
10. 堆疊後,確認堆疊介面的資料傳輸是否正確?確保堆疊的正確性!

不曉得大家是否有注意到,1~34~56~89~10的測試觀念都很雷同?測試觀念其實只分成兩個觀念: 

1. 不管是堆疊前還是堆疊後,單顆IC都要能運行無誤。
2. 不管是堆疊前還是堆疊後,堆疊介面的運作,都要能在目標速率下,運行無誤。

第一個觀念,相信大家都已經是耳熟能詳。單顆IC的測試有很多,挑幾個來做即可。第二個觀念,相信大家總有一天可以找解決的方式。此時,我想強調的重點是:你是一個數位工程師。在設計電路時,IC design流程是你一定要遵循,且你的設計電路也一定要在這裏被qualify。在IC design 流程中,你要用什麼方法驗證兩顆IC的堆疊介面?在傳統的認知裏,IC design流程是單顆IC的設計流程,怎麼做才能做到兩個IC同時被qualify

在分享經驗以前,我先把當時的已知條件先列出來。
1. 需要一個可以在IO上做loopbackIO cell.

2. IO cellLIB必須是完整的,包含loopback pathtiming分析。
3. 需要堆疊介面的RC timing值,因為做simulationsynthesis會用到。

4. 兩個堆疊IC都是新設計的IC

在堆疊介面上,使用可以loopbackIO cell,設計一個測試電路,在IO input上和output上各放置一個DFF. IO cell視為一個combination的電路。所以不管是堆疊前,還是堆疊後,其實都是DFF.DFF.timing分析。因此,在堆疊前,可以利用測試電路知道,資料經由IO cell後,是否還是正確?timing是否符合要求?如果都是正確的,我們即可以拿來做為一個堆疊的IC準備。





在這裏要注意的是,測試電路的DFF是在IO cellinput方向和output方向,所以在正常的電路設計裏,也要用到這兩個DFF,如果才能確保測試電路出來所做出來的測試結果,在正常路徑下,也能運行無誤。
所以在simulation階段,我們可以模擬堆疊前和堆疊後的結果。Test wrap也可以在FPGA階段時驗證。
synthesis階段,我們可以先單獨synthesize IC_AIC_B,然後再建立一個大的block,把IC_AIC_B放入,檢查剛剛synthesisIC_AnetlistIC_Bnetlist是否有符合timing?

如果有堆疊介面的RC timingLIB,我們也可以把它加上去,再次檢查timing

prime time時,除了要驗證單獨的IC_AIC_Btiming外,還要做block_Ctiming analysis

simulation驗證->timing分析-> post-simulation,每個步驟都有完整的驗證。所以,我們可以知道,在堆疊前,通過測試電路的IC,就一定可以拿做堆疊。堆疊後,通過測試電路的IC,就一定可以確保堆疊介面的資料傳輸可以運行。

是否還需要多做其他的debug pin,來監測或是了解堆疊運行的情況,這就要視情況而定,沒有固定的答案。

2014年6月29日 星期日

用數學式子講解兩種跨clock domain處理的timing是不同的

真是抱歉! 這陣子比較忙,所以就沒有更新文章。

今天我想從數學多項式子來說明跨 clock訊號上的觀念。以下有兩個圖。


Fig1:pq先做and邏輯運算後,再sync.clockB.


Fig2:p q先做sync.處理後,才做and邏輯運算。

有兩個訊號pq。第一種情況是先做and邏輯運算後,再同步處理到clockB,所需要的時間是Y(t1). 第二種情況是先同步處理到clockB後,才做and邏輯運算,所需要的時間是Y(t2)。請問Y(t1)Y(t2)的時間是否相同?

Sync_1, Sync_2, Sync_3 是用相同的module呼叫,同步處理的步驟一致。

你認為,從開始到結束,Y(t1) 所需要花費的時間和Y(t2)會是相同的嗎?

大部份的人都會認為Y(t1)=Y(t2),但是,事實是這樣子的嗎?我們可以試著用數學不等式來證明它們所需要花費的時間。以下,我們列出Y(t1)Y(t2)的不等式。看看是否一致?

假設,DFF.clockA所需要的時間是Xa, DFF.clockB所需要的時間是Xb.
and邏輯運算時間不計。Sync_1所需要的時間為X1, Sync_2所需要的時間為X2, Sync_3所需要的時間為X3.

Y(t1)的不等式是
Y(p)=Xa+X1+Xb;
Y(q)= Xa+X1+Xb;
所以Y(t1)= Xa+X1+Xb;

Y(t2)的不等式是
Y(p)=Xa+X2+Xb;
Y(q)= Xa+X3+Xb;

Y(t2)= max( Y(p), Y(q));

在這裏有一個觀念,雖然Sync_1, Sync_2, Sync_3,是呼叫同一個同步處理的module,但是因為在合成netlist時,clockAclockB是設成不用檢查 timing的 false path,所以Sync_1Sync_2,和Sync_3所需要的時間就會不同,因為我們不曉得DC會怎麼 place and route Sync_1的電路,它可能在Sync_1路徑上放100buffer, Sync_2路徑上放500buffer, Sync_3路徑上放1000buffer,因為我們已經設定成clockAclockB之間是false path。只要是設成false path的路徑,我們就要將它視為 timing上無法精準的算計,這是因為我們設定的限制條件不足。

所以我們得到Y(t1)Y(t2)的不等式,

Y(t1)= Xa+X1+Xb;
Y(t2)= max( Y(p), Y(q));

請問,這兩個不等式是相同的嗎?答案很明顯地是不同的。或許有些人會說,我以前的經驗兩個都設計過,並沒有不同。為什麼?

從理論上來說,這本來就是兩種不同的不等式,我們並不能否定這個事實。可是為什麼實務經驗裏,卻有機會可以相容?因為在DC合成器裏,它會儘量將跨clockpath 做最佳化處理,讓分別在兩個不同clock下的DFF 路徑上,是最短時間的路徑。再加上,我們所需要的只是要符合一個 clock period的 timing。所以就會有機會可以讓Y(t1)和Y(t2)可以相容。

但理論上不相同的東西。數位工程師在設計晶片時,從一開始就要想清楚,從理論上就要證明自己的方法是對的,然後才會在實務的過程中實現自己方法。這樣子的系統才是從根本上的穩定系統。如果不用穩定數學式子證明,只想要在DC合成過程中尋求穩定,那無異是緣木求魚;結果總會有例外發生,無法穩定系統。

理論上,不同的數學式子,就是不同的,數位工程師在設計跨 clock的程式時,必須要有以上的觀念,如此才能真正了解系統不穩定的問題。所以如果你著重的是 P和 Q到達Y的時間,那麼你必須選擇 Y(t1)的設計方法。如果你不注重 P和 Q的到達時間,那麼你就可以選 Y(t2)的設計方法。 Y(t1)和 Y(t2)就本質上就是不同的數學式子,視你的需要,選擇你的式子,沒有對錯可言。

2014年6月8日 星期日

Ncverilog 產生clock的小技巧

如果你想要簡單的在nccverilog做一個clock的產生器,你可以參考看看下面的技巧。

1. 沒有延遲,產生 50/50 duty的clock。
EXAMPLE:
initial clk = 0;
always #10 clk = ~clk;
2. 沒有延遲,產生 不是50/50 duty的clock。
EXAMPLE:
always
begin
clk = 0;
#10;
clk = 1;
#20;
end
3. 有延遲,產生 50/50 duty的clock。
EXAMPLE:
always
begin
clk = 0;
#300;
forever #10 clk = ~clk;
end

你可以選擇你想要的來使用。

2014年5月29日 星期四

RTL coding習慣和backend之間的關聯

下個星期是端午連假,所以就提早把下個星期要發佈,提早發佈!

今天我跟大家說明一下,寫RTL程式時,我們應該要去怎麼思索verilog code的寫法。我並不是想說明verilog 的語法,而是你的verilog程式,在合成時,Design Compiler(DC)怎麼去看待你的程式,它是怎麼解讀你的程式。畢竟我們寫出來的程式,是要給Design Compiler(DC)合出正確的的電路。

以下來原來原始程式的一部份,因為保密原則,我只能給一點點範例來說。下以的電路設計是一個SmartBus slaververilog codeSMBCi_DP51iclock訊號,是input訊號。SMBDi_DP51idata訊號,也是input訊號。
原始的設計是把SMBCi_DP51i當成是clock source,但是因為SmartBus的結束訊號的行為,有些數位工程師會SMBDi當成是clock source,來設計出結束訊號的偵測。以下就是一些程式的範例,紅色部份就是當成clock source的訊號。

wire SMBCi_DP51 = SMBCi;
wire SMBDi_DP51 = SMBDi;

// detect start condition -------------------------------
always @(negedge SMBDi_DP51 or negedge rstb)
begin
        if ( ~ rstb )
                sta <= 1'b0;
        else
                sta <= SMBCi_DP51;
end

always @(negedge SMBDi_DP51 or negedge rstb)
begin
        if ( ~ rstb )
                re_sta <= 1'b0;
        else
                re_sta <= SMBCi_DP51 & ( AdrCmdCnt == 6'd18 );
end


// start pulse ------------------------------------------
always @(negedge SMBCi_DP51 or negedge rstb)
begin
        if ( ~ rstb )
                d_sta <= 1'b0;
        else
                d_sta <= sta;
end

assign sta_pulse = ! d_sta & sta ;    // for system reset


// detect stop condition -------------------------------
always @(posedge SMBDi_DP51 or negedge sta_rstb)
begin
        if ( ~ sta_rstb )
                sto <= 1'b0;
        else
                sto <= SMBCi_DP51;
end
always @( negedge SMBCi_DP51 or negedge rstb )
begin
        if ( ~ rstb )
                sr <= 24'h0;
        else if ( ( AckCycle == 0 ) & ( sta_pulse == 0 ) )
                sr <= { sr_P[22:0], SMBDi_DP51i };
end

wire set_Smb2xSramWe  = (Smb2xSramWr & set_Smb2We);

always @ (posedge set_Smb2xSramWe or negedge rst_Smb2xSramWe )
        if ( ~ rst_Smb2xSramWe )
                Smb2xSramWe_0 <= #1  1'b0;
        else
                Smb2xSramWe_0 <= #1  1'b1;

always @ (posedge clk_DP51 or negedge rstb )
        if ( ~ rstb )
                Smb2xSramWe_1 <= #1  1'b0;
        else
                Smb2xSramWe_1 <= #1  Smb2xSramWe_0;

always @ (posedge clk_DP51 or negedge rstb )
        if ( ~ rstb )
                Smb2xSramWe <= #1  1'b0;
        else
                Smb2xSramWe <= #1  Smb2xSramWe_1;


使用上面的程式來合成電路時,Design Compiler(DC)會出現一些訊息,來告訴你,有些DFF沒有constrains,所以無法檢查出它的timing. 而你在宣告clock來源,你要宣告在兩個地方,一個是SMBCi,另一個是SMBDi。亦或是在程式中,任意產生一個訊號來當成是另一個DFFclock source。對DC而言,這些行為會有跨clock domain的問題、DFF constrain不充足的問題等等。這些都是需要數位工程師一一去確認,是否這些不足的條件是沒有關係或是有關係?所以工程師要一一去檢查來自DCwarning message(以下只有一部份,紅色部份是因舉例的程式所特別挑出來的。).

以下是用DCcheck_timing的指令,所列出來的訊息。

Warning: Design 'A1133' contains unmapped cells.
        Use report_cell to list unmapped cells in the design. (OPT-309)

Warning: The following end-points are not constrained for maximum delay.

End point
---------------
MCU/PM/CLK_DIV/q3_reg/next_state
MCU/PM/CLK_DIV/q5_reg/next_state
MCU/PM/CLK_DIV/q7_reg/next_state
MCU/SM2RAM/ Smb2xSramWe_0_reg/next_state
MCU/Smbus/TSextCntEn_32K_reg/next_state
MCU/Smbus/d_sto_reg[0]/next_state
MCU/Smbus/re_sta_reg/next_state
MCU/Smbus/sta_reg/next_state
MCU/Smbus/sto_reg/next_state

Information: The clock network starting at 'MCU/TestMux/CLK_SW_32K/CLK' is gated by the
        following input pins.

Clock Output Pin        Clock Input Pin          Gating Input Pin
--------------------------------------------------------------------------------
MCU/TEST_RST/C32/Z_0    MCU/TEST_RST/C32/DATA1_0 MCU/TEST_RST/C32/DATA2_0
MCU/TEST_RST/C32/Z_0    MCU/TEST_RST/C32/DATA1_0 MCU/TEST_RST/C32/CONTROL1_0
MCU/TEST_RST/C32/Z_0    MCU/TEST_RST/C32/DATA1_0 MCU/TEST_RST/C32/CONTROL2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA1_0
MCU/CHIPDP8051/U_CLKCTRL/C266/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/CONTROL1_0
MCU/CHIPDP8051/U_CLKCTRL/C266/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA2_0           MCU/CHIPDP8051/U_CLKCTRL/C266/CONTROL2_0
MCU/CHIPDP8051/U_CLKCTRL/C275/Z
MCU/CHIPDP8051/U_CLKCTRL/C275/B
MCU/CHIPDP8051/U_CLKCTRL/C275/A
MCU/CHIPDP8051/U_CLKCTRL/C267/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA1_0
MCU/CHIPDP8051/U_CLKCTRL/C267/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C267/CONTROL1_0
MCU/CHIPDP8051/U_CLKCTRL/C267/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C267/CONTROL2_0
MCU/CHIPDP8051/U_CLKCTRL/C278/Z
MCU/CHIPDP8051/U_CLKCTRL/C278/B
MCU/CHIPDP8051/U_CLKCTRL/C278/A
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/Z_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA2_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA1_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/Z_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA2_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/CONTROL1_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/Z_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA2_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/CONTROL2_0
MCU/filter/C1371/Z      MCU/filter/C1371/A       MCU/filter/C1371/B
MCU/filter/C1383/Z      MCU/filter/C1383/A       MCU/filter/C1383/B

Information: The clock network starting at 'MCU/SM2RAM/SMB_CLK/SMBCi_DP51' is gated by the
        following input pins.

Clock Output Pin        Clock Input Pin          Gating Input Pin
--------------------------------------------------------------------------------
MCU/SM2RAM/C2184/Z_0    MCU/SM2RAM/C2184/DATA1_0 MCU/SM2RAM/C2184/DATA2_0
MCU/SM2RAM/C2184/Z_0    MCU/SM2RAM/C2184/DATA1_0 MCU/SM2RAM/C2184/CONTROL1_0
MCU/SM2RAM/C2184/Z_0    MCU/SM2RAM/C2184/DATA1_0 MCU/SM2RAM/C2184/CONTROL2_0
MCU/SM2RAM/C2185/Z_0    MCU/SM2RAM/C2185/DATA1_0 MCU/SM2RAM/C2185/DATA2_0
MCU/SM2RAM/C2185/Z_0    MCU/SM2RAM/C2185/DATA1_0 MCU/SM2RAM/C2185/CONTROL1_0
MCU/SM2RAM/C2185/Z_0    MCU/SM2RAM/C2185/DATA1_0 MCU/SM2RAM/C2185/CONTROL2_0
MCU/SM2RAM/C2186/Z_0    MCU/SM2RAM/C2186/DATA1_0 MCU/SM2RAM/C2186/DATA2_0
MCU/SM2RAM/C2186/Z_0    MCU/SM2RAM/C2186/DATA1_0 MCU/SM2RAM/C2186/CONTROL1_0
MCU/SM2RAM/C2186/Z_0    MCU/SM2RAM/C2186/DATA1_0 MCU/SM2RAM/C2186/CONTROL2_0
MCU/SM2RAM/C2187/Z_0    MCU/SM2RAM/C2187/DATA1_0 MCU/SM2RAM/C2187/DATA2_0
MCU/SM2RAM/C2187/Z_0    MCU/SM2RAM/C2187/DATA1_0 MCU/SM2RAM/C2187/CONTROL1_0
MCU/SM2RAM/C2187/Z_0    MCU/SM2RAM/C2187/DATA1_0 MCU/SM2RAM/C2187/CONTROL2_0
MCU/SM2RAM/C2189/Z_0    MCU/SM2RAM/C2189/DATA2_0 MCU/SM2RAM/C2189/DATA1_0
MCU/SM2RAM/C2189/Z_0    MCU/SM2RAM/C2189/DATA2_0 MCU/SM2RAM/C2189/CONTROL1_0
MCU/SM2RAM/C2189/Z_0    MCU/SM2RAM/C2189/DATA2_0 MCU/SM2RAM/C2189/CONTROL2_0
MCU/SM2RAM/C2188/Z_0    MCU/SM2RAM/C2188/DATA1_0 MCU/SM2RAM/C2188/DATA2_0
MCU/SM2RAM/C2188/Z_0    MCU/SM2RAM/C2188/DATA1_0 MCU/SM2RAM/C2188/CONTROL1_0
MCU/SM2RAM/C2188/Z_0    MCU/SM2RAM/C2188/DATA1_0 MCU/SM2RAM/C2188/CONTROL2_0
MCU/SM2RAM/C2174/Z_0    MCU/SM2RAM/C2174/DATA2_0 MCU/SM2RAM/C2174/DATA1_0
MCU/SM2RAM/C2174/Z_0    MCU/SM2RAM/C2174/DATA2_0 MCU/SM2RAM/C2174/CONTROL1_0
MCU/SM2RAM/C2174/Z_0    MCU/SM2RAM/C2174/DATA2_0 MCU/SM2RAM/C2174/CONTROL2_0

Information: The clock network starting at 'MCU/Smbus/SMB_CLK/SMBCi_DP51' is gated by the
        following input pins.

Clock Output Pin        Clock Input Pin          Gating Input Pin
--------------------------------------------------------------------------------
MCU/Smbus/C950/Z        MCU/Smbus/C950/B         MCU/Smbus/C950/A
MCU/Smbus/C978/Z        MCU/Smbus/C978/B         MCU/Smbus/C978/A
MCU/Smbus/C969/Z        MCU/Smbus/C969/B         MCU/Smbus/C969/A
MCU/Smbus/C973/Z        MCU/Smbus/C973/A         MCU/Smbus/C973/B
MCU/Smbus/C982/Z        MCU/Smbus/C982/A         MCU/Smbus/C982/B
MCU/Smbus/C925/Z_0      MCU/Smbus/C925/DATA1_0   MCU/Smbus/C925/DATA2_0
MCU/Smbus/C925/Z_0      MCU/Smbus/C925/DATA1_0   MCU/Smbus/C925/CONTROL1_0
MCU/Smbus/C925/Z_0      MCU/Smbus/C925/DATA1_0   MCU/Smbus/C925/CONTROL2_0


這麼長,又這麼多的訊息要用人工的方式檢查,是不是既累人又煩燥?
為什麼數位工程師要寫一個DC無法百分百辨識的程式?為什麼不順應DC的特性,寫一個它看懂的程式,既方便又安全。

以下是重寫原來的程式;做法是用一個比較快的clock當成唯一的clock source,而外部訊號SMBCi_DP51iSMBDi_DP51iclk_DP51的領域裏,都被當成是data 訊號處理。

wire SMBCi_DP51 = SMBCi_DP51i;
wire SMBDi_DP51 = SMBDi_DP51i;

//----------------------------------------------------------------------
// analyze SMBC and SMBD signal
//----------------------------------------------------------------------
reg SMBCi_DP51_d1t, SMBCi_DP51_d2t;
reg SMBDi_DP51_d1t, SMBDi_DP51_d2t;

always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
    begin
        SMBCi_DP51_d1t <=0;
        SMBCi_DP51_d2t <=0;
    end
    else
    begin
        SMBCi_DP51_d1t <=SMBCi_DP51;
        SMBCi_DP51_d2t <=SMBCi_DP51_d1t;
    end
end

always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
    begin
        SMBDi_DP51_d1t <=0;
        SMBDi_DP51_d2t <=0;
    end
    else
    begin
        SMBDi_DP51_d1t <=SMBDi_DP51;
        SMBDi_DP51_d2t <=SMBDi_DP51_d1t;
    end
end

wire SMBCi_DP51_rising, SMBCi_DP51_falling;
wire SMBDi_DP51_rising, SMBDi_DP51_falling;

assign SMBCi_DP51_rising  = (SMBCi_DP51  & (~SMBCi_DP51_d1t));
assign SMBCi_DP51_falling = (~SMBCi_DP51 & (SMBCi_DP51_d1t));

assign SMBDi_DP51_rising  = (SMBDi_DP51  & (~SMBDi_DP51_d1t));
assign SMBDi_DP51_falling = (~SMBDi_DP51 & (SMBDi_DP51_d1t));



// detect start condition -------------------------------
always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
        sta <=0;
    else if(SMBDi_DP51_falling)
        sta <= SMBCi_DP51;
    else
        sta <= sta;
end

always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
        re_sta <=0;
    else if(SMBDi_DP51_falling)
        re_sta <= SMBCi_DP51 & ( AdrCmdCnt == 6'd18 );
    else
        re_sta <= re_sta;
end


// start pulse ------------------------------------------
always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
        d_sta <=0;
    else if(SMBCi_DP51_falling)
        d_sta <=sta;
    else
        d_sta <= d_sta;
end


assign sta_pulse = ! d_sta & sta ;    // for system reset


// detect stop condition -------------------------------
always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
        sto <=0;
    else if(sta_pulse)
        sto <=0;
    else if(SMBDi_DP51_rising)
        sto <=SMBCi_DP51;
    else
        sto <= sto;
end

always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
    begin
        Smb2xSramWe_0 <= 0;
        Smb2xSramWe_1 <= 0;
    end
    else
    begin
        Smb2xSramWe_0 <= set_Smb2xSramWe;
        Smb2xSramWe_1 <= Smb2xSramWe_0;
    end
end

wire Smb2xSramWe_xor = (set_Smb2xSramWe ^ Smb2xSramWe_1) & Smb2xSramWe_1;

always@(posedge clk_DP51 or negedge rstb)
begin
    if(~rstb)
        Smb2xSramWe <= 0;
    else
        Smb2xSramWe <= Smb2xSramWe_xor;
end


使用新的程式重新合成新的電路,我們會發現DCreport出來的訊息裏,原來紅色字的訊息已經不見了。這表示DC百分百看懂你的程式,且因為constrain充足,所以它不會有無法辨別timing的情況。請看以下來自DCwarning message


Warning: Design 'A1133' contains unmapped cells.
        Use report_cell to list unmapped cells in the design. (OPT-309)

Warning: The following end-points are not constrained for maximum delay.

End point
---------------
MCU/PM/CLK_DIV/q3_reg/next_state
MCU/PM/CLK_DIV/q5_reg/next_state
MCU/PM/CLK_DIV/q7_reg/next_state
// No red words warning message
MCU/Smbus/TSextCntEn_32K_reg/next_state
MCU/Smbus/d_sto_reg[0]/next_state
MCU/Smbus/re_sta_reg/next_state
MCU/Smbus/sta_reg/next_state
MCU/Smbus/sto_reg/next_state


Information: The clock network starting at 'MCU/TestMux/CLK_SW_32K/CLK' is gated by the
        following input pins.

Clock Output Pin        Clock Input Pin          Gating Input Pin
--------------------------------------------------------------------------------
MCU/TEST_RST/C32/Z_0    MCU/TEST_RST/C32/DATA1_0 MCU/TEST_RST/C32/DATA2_0
MCU/TEST_RST/C32/Z_0    MCU/TEST_RST/C32/DATA1_0 MCU/TEST_RST/C32/CONTROL1_0
MCU/TEST_RST/C32/Z_0    MCU/TEST_RST/C32/DATA1_0 MCU/TEST_RST/C32/CONTROL2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA1_0
MCU/CHIPDP8051/U_CLKCTRL/C266/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/CONTROL1_0
MCU/CHIPDP8051/U_CLKCTRL/C266/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C266/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C266/CONTROL2_0
MCU/CHIPDP8051/U_CLKCTRL/C275/Z
MCU/CHIPDP8051/U_CLKCTRL/C275/B
MCU/CHIPDP8051/U_CLKCTRL/C275/A
MCU/CHIPDP8051/U_CLKCTRL/C267/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA1_0
MCU/CHIPDP8051/U_CLKCTRL/C267/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C267/CONTROL1_0
MCU/CHIPDP8051/U_CLKCTRL/C267/Z_0
MCU/CHIPDP8051/U_CLKCTRL/C267/DATA2_0
MCU/CHIPDP8051/U_CLKCTRL/C267/CONTROL2_0
MCU/CHIPDP8051/U_CLKCTRL/C278/Z
MCU/CHIPDP8051/U_CLKCTRL/C278/B
MCU/CHIPDP8051/U_CLKCTRL/C278/A
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/Z_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA2_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA1_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/Z_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA2_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/CONTROL1_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/Z_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/DATA2_0
MCU/CHIPDP8051/U_DP8051/U_TIMERS/C802/CONTROL2_0
MCU/filter/C1371/Z      MCU/filter/C1371/A       MCU/filter/C1371/B
MCU/filter/C1383/Z      MCU/filter/C1383/A       MCU/filter/C1383/B

// No red words warning message

Information: The clock network starting at 'MCU/Smbus/SMB_CLK/SMBCi_DP51' is gated by the
        following input pins.

Clock Output Pin        Clock Input Pin          Gating Input Pin
--------------------------------------------------------------------------------
MCU/Smbus/C950/Z        MCU/Smbus/C950/B         MCU/Smbus/C950/A
MCU/Smbus/C978/Z        MCU/Smbus/C978/B         MCU/Smbus/C978/A
MCU/Smbus/C969/Z        MCU/Smbus/C969/B         MCU/Smbus/C969/A
MCU/Smbus/C973/Z        MCU/Smbus/C973/A         MCU/Smbus/C973/B
MCU/Smbus/C982/Z        MCU/Smbus/C982/A         MCU/Smbus/C982/B
MCU/Smbus/C925/Z_0      MCU/Smbus/C925/DATA1_0   MCU/Smbus/C925/DATA2_0
MCU/Smbus/C925/Z_0      MCU/Smbus/C925/DATA1_0   MCU/Smbus/C925/CONTROL1_0
MCU/Smbus/C925/Z_0      MCU/Smbus/C925/DATA1_0   MCU/Smbus/C925/CONTROL2_0


IC design flow裏,是需要很多軟體的協助。因此,數位工程師在寫verilog 程式時,不應只想著要怎麼解決自己問題,同時也應該想想後段工程師及軟體的處境。想一想,應該怎麼寫,才能讓flow裏面所有的工程師都是可以順順利利的做事。這也是為什麼我之前要把數位工程師分門別類成不同風格。愈是可以讓design flow順暢的數位工程師,他的RTL code上就愈可以看出他的用心與堅持。
IC design的過程中,我們都會遇到許許多多奇怪的疑難雜症。我並不是堅持一定要用上述的方法解決問題。而是你的程式是要給DC合成,是否可以採用可以儘量減少這些需要人工檢查的訊息的程式風格?是否可以採用符合ATPGDRC rule的程式風格?減少後段工程師的負擔。這些都是數位工程師在front-end design時,就可以儘量避免的事情,為什麼不做?

多去想想在這個IC flow上其他工程師做的事情,有沒有自己可以在RTL階段時,就可以幫忙或是避免的做法?多了解後段工程師的想法,可以讓自己的RTL程式愈來愈適合後段的流程;同時,我們也可以把前段RTL的特性告訴後段工程師,讓他們更加了解,RTL並不是無敵的,它有無法做到的地方時,是否可以請後段工程師幫忙,做出符合產品要求的高品質的晶片。

IC design flow裏,並不是只有一個人在做,是由許多人一起合力完成。寫出讓大家都能順暢地工作的RTL程式,才是數位工程師應該要努力的方向。