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程式,才是數位工程師應該要努力的方向。


2014年5月25日 星期日

什麼是DMA ?

什麼是DMA?
如果你上網搜尋DMA,相信你可以找到很詳細的解釋。例如下方的解釋。

直接記憶體存取Direct Memory AccessDMA)是電腦科學中的一種記憶體存取技術。它允許某些電腦內部的硬體子系統(電腦外設),可以獨立地直接讀寫系統記憶體,而不需繞道中央處理器CPU

簡單來說,就是搬資料,不需要用到CPU的指令。換言之,搬資料時,CPU不用知道。要怎麼做可以確保搬的資料不會錯。

1.要知道原始資料的位置。
2.要知道目地的位置。
3.要知道要搬多少資料長度。

這個跟你找搬家公司一樣。你要先告訴搬家公司你家的地址。然後告訴他你新家的地址。然後再告訴他,你家的哪些搬東西要搬走。之後搬家公司就可以開始搬。主人不用每一樣都要告訴他怎麼搬。

所以搬家公司就是控制器(controller),舊家是地址,新家是目地。傢俱是資料。詳細清楚搬家內容後,就開始搬,這就是DMA

所以要看懂DMA的設計,就是找兩個地址一個資料長度。然後就沒有了。很多人告訴我,他設計的DMA有多複雜又多複雜。很難看懂。我請他畫 Bus,請他告訴我定址空間。然後請他告訴我,他的DMA控制器的哪一段是記錄兩個地址和資料長度。之後我在 Bus diagram上,告訴他DMA如何在 Bus上移動。一清二楚,有沒有做錯,一目瞭然。
那兩個地址,一個資料長度誰給?誰給不重要,重要是「搬資料時,CPU不用知道」,這就是DMA

或許有人覺得他設計的DMA比較複雜,較難懂。就像有人家裏東西多、種類多。所以找比較多搬家公司,有人專門負責搬黃金、有人專門搬傢俱、有人專門搬家電,搬家時,你家會不會很熱鬧?當然會,只看搬黃金的,會很複雜嗎?只看搬傢俱的,會很複雜嗎?做好一套DMA後,再來就簡單了。初學者不用擔心會很複雜。

另外會增加DMA複雜度的是arbter(仲裁器),它會決定是哪個DMA的需求會被滿足。把這個部份程式和DMA的程式分開來研讀,相信初學者就可以解決DMA的問題。

2014年5月18日 星期日

數位工程師對DC-compiler的觀念是什麼?

數位工程師是離不開 DC-compiler,他需要 DC-compiler幫他合成 netlist,所以 DC-compiler對數位工程師而言是一個很重要的工具,但是數位工程師有用正確的態度來使用 DC-compiler嗎?
DC-compiler公司因為不曉得你的想法,不曉得你的晶片設計是什麼,所以他們絕大多數都不會用error message來告訴你,你的晶片有什麼問題。他們用warning message來告訴你,你的晶片有什麼異常,請你自己去看,由你自己去判斷。他們用error message來告訴你,你操作DC-compiler的方法是錯的,例如:語法錯、指令錯等等,這是他們肯定知道錯的,所以用error message來告知。

曾有數位工程師跟我說,那只是warning message,又不是 error message,有什麼關係,不用看。我聽了著實嚇了一大跳,一個D-flip-flop沒有辦法 report timing,無法得知它的setup-timehold-time,會叫做「沒有關係」嗎?。在 DC-compiler裏,它只會列出一大堆沒有辦法計算的 timing D-flip-flop,不會告訴你那是 error message。數位工程師要自己去判斷。那你或許會說,為什麼要數位工程師自己判斷,電腦為什麼不自己判斷,DC-compiler有那麼差嗎?

是的,電腦會判斷,但前提是數位工程師要提供完整的條件告訴DC-compiler。曾有數工程師說,DC-compiler會幫你檢查 timing,如果他們的clock是同源的。乍聽下是對的,我就問,DC-compiler有怎麼知道他們是同源的?他回答:「一看就知道。」忽然間我感到不對勁,再問:「要怎麼看?它是電腦,又沒有眼睛。」他回答:「他應該就是會知道。」原來他認為,他所有的 design寫好後,DC-compiler就是會從RTL code知道,不用寫條件,只要create clock 就會知道。這下子,我才明白,原來 DC-compiler還是一個有極高度智慧的AI程式。我想DC-compiler公司聽到這些話,應該會高興到跳起來,因為有人給予DC-compiler這麼高評價。

DC-compiler是一個很棒的工具,但是它不是人工智慧的程式

DC-compiler並不是一個會自我成長的程式,所以,當你使用它的時候,你一定給足所有的條件,讓它來幫你工作。所以它不會「本來就知道」你的設計想法,它需要你「告訴它你的設計想法是什麼」。所以,如果是同源的clock,就是要宣告generated clock。而 Multi-cycle path,一定要寫出來不然它不會曉得。每個 D-flip-flopclock port都是要接到一個被宣告的clock描述語法上,如果沒有,那它就不知道怎麼做,所以會被列到沒有timing constrain的地方。

DC-compilerwarning message是要請您補足你的constrain不是要你每次用人工看message是對或是不對:

DC-compiler是依照一個複雜的演算法來幫忙計算timing的,當它無法用你給的條件來計算時,應該是你要補足constrain條件或是修正你的RTL code,而不是都用人工的方式來看待warning message。或許你會覺得修正你的RTL code是一件很誇張的事;但是,你知道嗎?在十年前,DC-compiler甚至看不懂「function」的verilog語法,所以數位工程師都被禁止使用「 function」這個語法。而現在它看懂了,所以你可以用「function」語法。換句話說,是你去適應它的能力,而不是它來適應你的能力。所以如果你的RTL coding style沒有辦法被看懂時,理應修正RTL code

DC-compiler很笨

有很多工程師認為DC-compiler很笨,常常把假錯(fault error)的 timing列出來。害工程師要多做一次檢查。是的,DC-compiler是很笨,但那是因為你給的constrain不足,所以它無法算出正確的timing給你,所以只好列出來給你看,以免你合出錯的 netlist。所以,是你讓它變笨。

Input delayoutput delay都是別人家的delay

DC-compiler裏,set_input_delayset_output_delay都是在說明別人使用多少delay
例如:如果有一個clock20ns為週期的,

set_input_delay –clock clk_20  15 portA;
set_output_delay –clock clk_20  15 portB;

portA20ns週期的clk_20上,只能用到5ns(20ns-15ns)的時間。portB20ns週期的clk_20上,只能用到5ns(20ns-15ns)的時間。以前有個工程師跟我爭論,set_input_delay這個指令是設別人的delayset_output_delay是設自己的delay。現在我把這個重要的觀念再說一次,大家一定要清楚明白set_input_delayset_output_delay都是設定別人所用的delay;如果要知道自己可以使用多少時間,一定要自己計算( T – delay time)。這個算法,到目前為止(2014/04/21)DC-compiler都還是用這個方法。如果他們有改版,不用這個方法時,我再告訴大家新的計算方法是什麼,不然,它們就是這麼計算的。

DC-compiler的正確態度是什麼?

1. create clock很重要(每個D-flip-flopclock port都會連到的clock),告訴 DC-compiler 每個clock之間的關係,即使用同源的也宣告清楚。

2.每個input delayoutput delay都要確實宣告。你不宣告,它一定是不會知道的。

3. 如果不需要檢查timing的,也要宣告訴清楚,因為它的演算法會幫你做更多事,幫你檢查更詳盡,而你可以更省力。

4. drivingloading要記得給,這對合出準確的 netlist是有幫助的。

5. 只要有warning message就想辦法消除,因為這對DC-compiler合成netlist是有幫助的。

6. 只要是DC-compiler有看不懂RTL code的疑慮,一定要改RTL code來適應它。

7. 數位工程師都是看balance treetiming report。不balance treetiming report也是屬於某段balance treetiming report,所以如果有不balance treetiming report需要檢查時,請把條件寫出來,然後再以balance tree的角度看待timing report

8. resetclock同樣重要,要記得宣告。


DC-compiler是工具,不是一個AI程式,它不會知道你的想法。你必須把設計時的所有條件以及你想要遮罩的條件,一一寫入DC script檔案中。DC才能照你的想法合成 netlist。所有的coding style都是為了讓 DC看懂你的程式,進而合出你的 netlist。

2014年5月4日 星期日

從 IC流程中探索數位工程師的風格--III

在上述的 IC流程中,還有其他工程師也是參與其中;而你是數位工程師,你對其他工程師的責任是什麼你有清楚嗎?

案例分享:
在這個 IC流程中,數位工程師會需要類比工程師的幫忙部份,絕大部份是在synthesis LIB的參考和simulation時的模型建立。曾經遇過類比工程師需要數位工程師幫忙驗證他們建立的LIB是否正確?在這個IC流程中,確實可以幫類比工程師驗證LIB。但是當初在規劃行程時,有把這個時間算進去嗎?而且整個design在進入synthesis階段時,在很多的synthesis條件都沒有穩定的情況下,拿去幫類比工程師驗證 LIB是否是正確的選擇?所得到的結果是否會是正確?不正確的話,又需要多少時間收斂?所以類比工程師的LIB 驗證,應該是要在他自己的環境下去完成,而不應該在整合的環境中去做驗證。

IC流程裏,它不是幫類比工程師驗證LIB,它是依據類比工程師提供正確的LIB來做合成的工作。所以在synthesis之前,數位工程師就應要求類比工程師提供正確的LIB,不然就無法合出最合適的netlist。

為什麼synthesis時,要有正確的LIB
DC-compiler依據LIB上的資訊,利用它的演算法,計算出哪一個gate是最合適的,計算出所有pathtiming,告訴你哪一個是很緊的。依據這種概念,合出來的netlist才會是最接近真實的情況。

以下是案例的分享: 
類比工程師進度落後,告訴數位工程師,你用設delay方法來收斂 timing,類比工程師會按規格要求,處理好 interface timing,之後就可以tape-outLIB部份,類比工程師會用手動的方式建立,讓整個 synthesis 流程順暢。 結果晶片回來後,在某些頻率下,會容易出錯。問題查了很多,原因是data出錯;所以數位工程師不可避免的成為主要的負責人。從designsynthesis,然後再到primetime check,之後還check floor-plan。結果發現,是類比工程師在設計介面時,使用推力不足cell,所以在頻率快的情形下,setup-time violation。但這完全查不出來,因為LIB是非常完美的LIB,它不是擷取類比電路所計算出來的。它是人工的,所以在這個流程中,數位工程師當然查不到setup-time violation的報告。

合成時為什麼需要LIB?當然是想要在最接近真實的情況下,合出適合的netlist。因為LIB太過理想,所以合出來的netlist當然也是太過理想。

為什麼國外大廠的晶片穩定度高?技術好是一個原因。另外一個是他們嚴格要求IC流程的模擬要符合真實情況。所以他們一定用軟體來擷取類比電路,計算出正確timing後,才會公佈 LIB給數位工程師使用。儘量讓所有的數據都是最接近真實情況。

說完IC流程後。我大約分類一下風格,大家或許就可以知道我所說的是什麼意思。希望藉由這些分類,可以更了解你的工程師伙伴在想什麼?

1. Front-end RTL level數位工程師:遇到問題時,想盡辦法在RTL-level解決,並在RTL-simulation確保function的正確性。其寫出來的RTL code都是synthesizable,了解RTL code限制,也知道如何在DC環境下,寫出適合的constrain,也知道怎麼看懂的所有的timing report。其程式風格像前面RTL code的解決方式一.

2.Front-end post-level數位工程師:程式的風格像前面的RTL code的解決方式二,需要CAD的工程師幫忙保證 timing,無法在RTL-level就保證其timing和正確性。

3.Front-end artificial數位工程師,程式的風格像前面的 RTL code的 interrupt machine的原始範例,用人腦推論;對於DC-compiler提出來的 timing violation時,人工確認是否為假錯( false-error )

4. cell-base數位工程師:使用verilog語法並參照standard cell/customized cell,畫出電路,不是用寫程式的觀念來寫程式的。

5. Back-end數位工程師: 熟悉DC的指令、primetime指令。對做ATPG, IO scan非常清楚,但是對RTL-coding觀念比較薄弱,因為對DC和 primetime指令熟悉,所以較適合做IP整合工作。

其實還有其他種類的數位工程師,在此就不一 一敘述,我就針對以後我的分享風格做一個說明,讓大家知道我為什麼這樣做,我的原因有在哪裏?我的要求在哪裏?

做為一個數位工程師,你會遇到的問題和困難一定會很多,有時候你無法保證一定可以在RTL level就把它解決,這其中包括 timing。 而 timing的部份,你可能需要別人的協助,才能把問題解決。但是我希望所有的問題盡量在RTL-level就解決完,除非不能解決時,才會請CAD幫忙保證 timing。之後如果我有分享程式時,你會看到我程式都會在RTL-level解決問題。每個程式也都一定會知道怎麼寫 timing constrain和看它的 timing report。