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。