下個星期是端午連假,所以就提早把下個星期要發佈,提早發佈!
今天我跟大家說明一下,寫RTL程式時,我們應該要去怎麼思索verilog code的寫法。我並不是想說明verilog 的語法,而是你的verilog程式,在合成時,Design Compiler(DC)怎麼去看待你的程式,它是怎麼解讀你的程式。畢竟我們寫出來的程式,是要給Design Compiler(DC)合出正確的的電路。
以下來原來原始程式的一部份,因為保密原則,我只能給一點點範例來說。下以的電路設計是一個SmartBus slaver的verilog code。SMBCi_DP51i是clock訊號,是input訊號。SMBDi_DP51i是data訊號,也是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。亦或是在程式中,任意產生一個訊號來當成是另一個DFF的clock source。對DC而言,這些行為會有跨clock domain的問題、DFF constrain不充足的問題等等。這些都是需要數位工程師一一去確認,是否這些不足的條件是沒有關係或是有關係?所以工程師要一一去檢查來自DC的warning message(以下只有一部份,紅色部份是因舉例的程式所特別挑出來的。).
以下是用DC的check_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_DP51i和SMBDi_DP51i在clk_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
使用新的程式重新合成新的電路,我們會發現DC所report出來的訊息裏,原來紅色字的訊息已經不見了。這表示DC百分百看懂你的程式,且因為constrain充足,所以它不會有無法辨別timing的情況。請看以下來自DC的warning 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合成,是否可以採用可以儘量減少這些需要人工檢查的訊息的程式風格?是否可以採用符合ATPG的DRC rule的程式風格?減少後段工程師的負擔。這些都是數位工程師在front-end design時,就可以儘量避免的事情,為什麼不做?
多去想想在這個IC flow上其他工程師做的事情,有沒有自己可以在RTL階段時,就可以幫忙或是避免的做法?多了解後段工程師的想法,可以讓自己的RTL程式愈來愈適合後段的流程;同時,我們也可以把前段RTL的特性告訴後段工程師,讓他們更加了解,RTL並不是無敵的,它有無法做到的地方時,是否可以請後段工程師幫忙,做出符合產品要求的高品質的晶片。
IC design flow裏,並不是只有一個人在做,是由許多人一起合力完成。寫出讓大家都能順暢地工作的RTL程式,才是數位工程師應該要努力的方向。