jackmafan
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee
  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    1
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # NYCU ICLAB 第一人稱修課體驗 ## CREDITS TO https://medium.com/mirkat-x-blog/iclab-交大修課心得-b60f272c2f32 ~~我拿到同學的md id後就會慢慢補上~~ ## 前言 哈囉大家好,這裡是傑克麻煩。交大電子研究所李鎮宜教授授課的**積體電路設計實驗**(**又稱 ICLAB**),一直是一門傳說中的課程,已經不知多少人午夜在 LAB 當中揮霍,也不知多少個 IC 設計的美夢葬送在一大疊退選單中。身為一個合格的交大電機學生,不修個 ICLAB ~~就跑去臺大~~簡直是浪費青春,加上剛好有機會看到學長過去的修課心得,而且有幸找了一群最頂尖的同屆組隊討論,有感而發想做一個第一視角回顧 ICLAB,修課內容和最詳細設計講解的系列筆記。 ## 那開始囉! **積體電路設計實驗 2023 Autum 教學大綱** | | Lecture | Lab | | ----- | ----------------------------- | --------------------- | | [Week1](https://hackmd.io/@jackmafan/HyvZkizZ6) | Cell Based Design Methodology | Combinational Circuit| | [Week2](https://hackmd.io/@jackmafan/iclabhacker2) | Finite State Machine | Sequential Circuit | | Week3 | Verification & Simulation | Protocol & Pattern| | Week4 | Sequential Circuit II (STA + Pipeline) | AI Chip (Float op) | | Week5 | Memory & Memory Compiler | Image Processing (Memory) | | Week6 | Synthesis Methodology | Network IP Design| | Midterm Project | \ | Algorithm Based ASIC| | Week7 | Timing: Cross Clock Domain + Synthesis Static Time Analysis | FIFO Design | | Week8 | Power: Low Power Design | Clock/Power Gating| | Week9 | System Verilog I (Design) | OOP Design| | Week10 | System Verilog II (Verification) | Checker| | Week11 | System Verilog (Formal Verification) | ABVIP| | Week12 | APR I : From RTL to GDSII | Physical Design| | Week13 | APR II : IR-Drop Analysis +Advanced IC Design Methodology| IR Drop Analysis| | Final Project | \ | General Purpose IC| |==ADFP==| ==FinFET Design== | ==FinFET Design== | 上半學期從 verilog 開始,囊括組合電路(Combinational Circuit)、時序電路(Sequential Circuit)、模擬及驗證(Verification)的基本語法,還有實體 RAM/ROM 的呼叫語法(Memory Compiler)、以及合成設定(Synthesis)。下半學期則包含多時脈電路分析、低功耗設計、Syetemverilog語法、甚至還要做確定佈局後的電路分析(APR)、以及最後的重頭戲:使用先進製程檔案操作的 FinFET Design(因保密協定、此系列文章將不會講解該堂課程),紮紮實實地訓練數位積體電路設計端的操作流程。 接下來的講解將預設讀者們已經有基礎的數位邏輯設計概念和 C/C++ 撰寫能力,避免過長的篇幅及冗餘的講解。 ## Lecture 01 --- Cell Based Design Methodology ### 從抽象邏輯閘到實體電路 在學習邏輯設計的一開始,我們可能會用真值表、基礎的 AND 閘 OR 閘、還有反向器來描述一個電路。例如下面的布林函數 C=~(AB),對你而言可能是長這個樣子的: ![](https://hackmd.io/_uploads/S1tM62f-6.png =50%x) | A | B| C| | -------- | -------- | -------- | | 0 | 0 | 1 | | 0 | 1 | 1 | | 1 | 0 | 1 | | 1 | 1 | 0 | 但實體層面來說,製造廠(~~就是那家TS什麼C的~~)要做的卻是以下四個電晶體的電路,這個電路會在輸入端是高電位(Vdd、對應邏輯1)或低電位(GND,對應邏輯0)時,讓輸出端產生如真值表的輸出。 ##### schematic&Layout of NAND ![](https://hackmd.io/_uploads/Bybe1TGZ6.png =30%x)![](https://hackmd.io/_uploads/rkFx1Tfbp.png =23%x) 看到右上那張 layout 裡面花花綠綠的矩形了嗎?如果你修過VLSI實驗或類似名字的課程,肯定是對這些長方形刻骨銘心,因為修課學生會像在設計晶片時採用**全客製化方式設計(Full Custom Design)** 的工程師一樣,一個一個拉那些長方形,並產生右上這樣的圖層檔 ### 數位電路設計方法 可能有些人覺得,拉個長方形又沒什麼,但如果想像一下你是要自己用長方形拼出以下 layout 呢? https://medium.com/@akurian.2001/ic-layout-6232a0144629 ![](https://hackmd.io/_uploads/SyIMZafb6.jpg =70%x) 顯然是天方夜譚對吧,所以現在主流的數位晶片設計方式是使用所謂 **Cell based** 的設計流程,也就是 1. **使用硬體描述語言描述電路的行為** 2. **交由設計自動化軟體將所描述的電路映射至製程廠提供的標準邏輯單元(Standard Cell)** 3. **設計自動化軟體會接著產生如上圖的layout** 4. **使用產生的實際電路做後續驗證** 5. ....... 以下就來實際比較不同設計流程以及各自的優缺點 #### FPGA FPGA 是一種比較特別的設計流程,當向製程廠下線晶片並不是很划算時,就可以採用 FPGA。本人並不是很熟悉相關的步驟,但一樣透過特定的軟體和各大硬體商提供的 FPGA 開發板,就可以在上面客製化屬於自己的電路。優點是不用等待極久極繁瑣的下線過程就可以得到一個可做測試的電路,缺點是電路的複雜性有其侷限,而且工作頻率最多只能達到百萬赫茲等級 **(note:目前個人電腦的工作頻率普遍可以到4G左右)** #### Full Custom vs Cell Based 如同前述的優缺點,Full Custom 就像是裝潢時房子時從原木開始打造家具,優點是格局、雕飾、選材都可以客製化,但缺點是耗時極長;另一方面,Cell Based 就有點像是去某知名瑞典家具~~玩偶~~商買來自己組合和搭配,缺點就是多少有些缺點,有時候色澤差一點、有時候少一個夾層......但設計速度相對快非常多,而且效能不會比 Full Custom 差到非常多,~~當然是指手刻layout還是可行的那個年代,現在已經不可能這樣做了~~。 所以本門課程的一大重點就是學習如何使用 verilog 描述欲合成之電路行為(**RTL level design & Gate level synthesis**),以及怎麼去驗證這個電路的行為是符合預期的(**Pattern & Verification**)。 ### Verilog & Combinational Circuit 在開始學習 verilog 之前,請讀者務必注意以下重點 :::info verilog 是用來"描述"你心中想好的電路,而不是想辦法寫到讓模擬跑過,剩下交給EDA tool把電路通靈出來 ::: :::info verilog 一開始發展的契機真的是用來描述電路並且做驗證,讓設計者用 c-style 寫 pattern 再對 gate level 的 netlist 進行驗證,所以從 verilog 程式碼合成電路的規範是後來才慢慢發展出來的,因此如果你對 verilog 那莫名其妙的變數型別和時序元件呼叫方法感到非常疑惑,純屬正常現象。 ::: #### reg & wire verilog 中有以下兩種型別的變量,reg 和 wire,宣告時必須一同宣告其bit數,如下述代碼。 ```verilog= reg [31:0] my_first_reg; //32 bits width wire [31:0] my_first_wire; //32 bits width ``` 這兩種型別的變數具體而言差在哪裡呢?絕對不是合程階段保證合成出節點和暫存器的差別,而是 :::info 能夠在always敘述句中被放在左值賦予變量的只有reg型別的變數,能夠在assign敘述句中放在左值的只有wire型別的變數 ::: 如下代碼 ```verilog= assign my_first_wire = 32'd0; always(*)begin my_first_reg = my_first_wire; end ``` #### constant 在verilog中表示常數需要使用如下的表示式 *位元數* '*進制*_*值* ```verilog= wire [7:0] constant_wire; assign constant_wire = 8'b00100001; //代表binary的00100001 assign constant_wire = 8'd12;//代表decimal的12 自動補0到滿足8個bits assign constant_wire = 6'b100001;//代表binary的100001 //assign給左值時會補0補到8個bits assign constant_wire = -8'd12;//將-12的2補數assign給左值 也就是8'b11110100 ``` #### assign assign 是一個常用於組合電路的關鍵字,用法如下 ```verilog= wire [7:0] assign_example; wire [7:0] r_value1; reg [7:0]r_value2; assign assign_example/*wire型別*/ = r_value1 & r_value2; //可以看到不論變數是reg/wire,其實並不影響右值運算的合法性 assign assign_example = r_value1 | r_value2; //Error: one wire cannot be assigned by two drivers ``` assign 會讓左值像是被放在一個組合邏輯單元的輸出端一樣,每當右值出現變動時也會出現相對應的變動。 #### assignment in always block always 完整的語法的語法如下 ```verilog= always @(/*sensitivity list*/) begin //event end ``` sensitivity list 可以寫入一個訊號,或者某個訊號的正負緣,這樣每當沒有指定正負緣的訊號發生改變,或指定的訊號來到正負緣時,就會執行always內的敘述。但在撰寫組合邏輯的時候,建議一律填入*,這代表所有在該 always block 右值出現的訊號發生改變時,都會觸發此區塊——這也是組合邏輯的特性:每當輸入發生改變,輸出就會嘗試改變。 另外 always 當中,有所謂的non-blocking assignment 和 blocking assignment,這是什麼意思呢?我們先來看看下方的程式碼 ```verilog= //this is a blocking assignment block //remember only use blocking assignment in combinational circuit reg a,b,c; always@(*)begin a = ~b; a = a&c; end //this is a non-blocking assignment block //remember only use blocking assignment on Flip-Flop reg d,e,f; always@(posedge clk)begin d <= e; e <= f; end ``` 首先,雖然我們在第一個 block 當中寫了很像是 combinational loop 的東西,但它是一個**可以被合成**的電路。因為只有這個區塊中不論 b/c 誰先發生變動,電路都會先做 a=~b 再做 a=a&c,所以它等效於 ![](https://hackmd.io/_uploads/ByfPLbYba.png =60%x) 而第二個 block 則會在 clk 的正緣來臨時,將 e/f 在正緣前的值,更新到d/e 在正緣後的值,所以其實是如下 2 個 DFF 的結構。 ![](https://hackmd.io/_uploads/S1spDbtbp.png =70%x) 其實從這樣的敘述中也可以看的出 non-blocking assignment 和 blocking assignment 的差別了。我自己的理解是,**non-blocking assignment 會將 r-value 在 trigger 前的值送到 trigger 後的 l-value,而 blocking assignment 則會尋找最"新"的 r-value 送到 l-value**。所以兩種 assignment style 當然不能用在同一個 l-value 上,甚至有些編譯器會禁止在同一個 always block 同時出現 "=" 和 "<="。(**即使不禁止你也應該避免使用**) ### Condition: If & Case 有時候在輸出並不只是輸入彼此之間的簡單運算,例如現在有 ctrl、a、b 訊號,當 ctrl 不同時,要輸出諸如 a+b、a-b、a&b,要描述這種 branching 的行為,在 verilog 中可以用 If 或者 Case 完成,範例如下。 ```verilog= //Case reg a,b,c,select; always@(*)begin case(select) 1'b0:begin c = a&b; end 1'b1:begin c = a|b; end //when the value before ':' is the same as value in (), //the statement after ':' will be executed endcase //using 'case'-'endcase' as begin-end token end //If else reg d,e,f; always@(*)begin if(select == 1'b0)begin f = d&e; end else begin f = d|e; end end ``` 要注意的是,If 代表的是一個不同條件有階級之分的電路,Case 裡面的不同條件則是平等的。這個差別通常在合成階段才會明顯表現出來,因為 If 所描述的電路的長相感覺會是這樣 ![](https://hackmd.io/_uploads/rkE_1juM6.png =40%x) 而 Case 的電路則會感覺像這樣 ![](https://hackmd.io/_uploads/HkrKJi_zp.png =20%x) If 電路的**關鍵路徑 (critical path)** 在合成初階段步看下來是會比較大的。雖然很多時候If之間彼此的條件是互斥的,或者一個本質上是平行條件的電路硬用If-style寫出來,合成器這時會去做適當的化簡,但是如果這些限制是使用者知道但合成器看不出來的話,最後還是會合出一個有階級條件的電路。 ### 其他常見眉眉角角 礙於篇幅,其他 verilog 的基本語法(如 module declaration 和 port connection、signed/unsigned arithmetic)就不在此贅述。這一小段著重於分享我在撰寫 Combinational Logic 時的常見錯誤和debug方法 #### 意外產生 latch Latch 是一種由控制訊號鎖存訊號的電路結構。當控制訊號 HIGH,輸出會等於輸入;控制訊號 LOW,輸出則會被"鎖"在控制訊號仍為 HIGH 的值,是最基本的"維持"狀態的電路單位。在學校的課程當中通常不希望出現 Latch 的原因如下 ::: info 1. 難以進行靜態時序分析。對於時序元件,都需要在控制訊號切換前後要求輸入保持穩定狀態,如果 Latch 的控制訊號是由組合電路產生,此時會很難分析輸入該在什麼時候之前保持穩定。 2. 即使使用時鐘訊號做控制,實際運行時的 Latch 本身仍是一個容易產生 glitch 的結構。 3. 更多時候是因為在我們預期根本不應該出現 Latch 的地方被合成出 Latch —— 例如組合邏輯。 ::: 要確認有沒有合成出 Latch 只要去看 syn.log 就可以了。如果某個變量被判定有出現 **"Latch Inference"** ,就記得去修改賦值該變量代碼的 always block 即可。 通常出現 Latch 的地方會在帶有條件判斷的變量上,**當經過一系列的條件判斷,某個 reg 變量有可能沒有被賦值**,就會被合成 tool 判定為你在寫一個 Latch 的行為,**因為不給值它就只好維持舊有的值嘛!** 拿上面的代碼來說 ```verilog= //Case reg a,b,c,select; always@(*)begin case(select) 1'b0:begin c = a&b; end //1'b1:begin //c = a|b; //end //Latch Inference!! when select = 1'b1 //c will not be assigned endcase end //If else reg d,e,f; always@(*)begin if(select == 1'b0)begin f = d&e; end //else begin //f = d|e; //end //Latch Inference!! when select = 1'b1 //f will not be assigned end ``` 要去掉這種簡單或更複雜代碼的 Latch 也很簡單。 ```verilog= //Case reg a,b,c,select; always@(*)begin case(select) 1'b0:begin c = a&b; end default:begin c = a|b; end //use default statement to catch the exceptional cases //so that you dont have to enumerate all exceptional cases endcase end //If else: style 1 reg d,e,f; always@(*)begin if(select == 1'b0)begin f = d&e; end else begin //always append a else block after if-else-if structure f = d|e; end end //If else: style 2 reg f2; always@(*)begin f2 = d|e;//assign the value at initial //so that the value is still assigned when condition is not met if(select == 1'b0)begin f2 = d&e; end end ``` #### 接錯port 其實通常在模擬階段就能抓出呼叫 module 時接錯線的錯誤了。為了避免此類錯誤,請盡量使用 **naming mapping** 的方式呼叫 module。此外有時候仔細看合成訊息也能發現一些 debug 方法,例如有時候我會接收到某些 module 的 pin 腳只被接了 1 bit wire上去,這時我就大概可以知道我這個變量沒改到名字(因為合成器會自動判定沒被宣告過的變量為 1bit 寬)。 此外我在後續 Lab 也有發生非常離奇的錯誤,在合成階段時因為 RTL 沒有使用naming mapping接線(但線寬順序都對),導致合出錯誤電路的結果。 PS:附上助教回應 ![](https://hackmd.io/_uploads/Hyh3Q3_Gp.png =70%x) ## Lab01 MOS Caculator ### Description 本週的 Lab 是要撰寫一個簡單的邏輯電路,在輸入給定一系列關於 MOS 的參數後以及控制訊號後,需要計算出 MOS 們的 IDS 或者 gm 並排序,再選擇對大三數取加權平均或小三數取平均並輸出。Pin腳大致如下 ::: success **Input** W_0, V_GS_0, V_DS_0, ... W_5, V_GS_5, V_DS_5,(6顆MOS的參數) Mode (bit0選擇計算ids或gm,bit1選擇計算大三數加權平均或小三數加權平均) **Output** out (計算結果) ::: ### Strategy 根據助教在講義中指定的的公式,在 saturation 和 triode region 下 Ids 和 gm 的公式分別是 $$ Triode(V_{gs}-1>V_{ds}) $$ $$ I_{ds}={W \over 3}[2(V_{gs}-1)V_{ds}-V_{ds}^2] $$ $$ g_{m}={2WV_{ds} \over 3} $$ $$ Saturation(V_{gs}-1 \le V_{ds}) $$ $$ I_{ds}={W \over 3}(V_{gs}-1)^2 $$ $$ g_{m}={2W(V_{gs}-1) \over 3} $$ 但如果在 Vds 進來後對它做所謂的限制,壓縮到不比 Vgs-1 大,就可以把公式變成 $$ I_{ds}={W \over 3}[2(V_{gs}-1)V_{ds'}-V_{ds'}^2] $$ $$ g_{m}={W(2V_{ds'}) \over 3} $$ 注意到其實可以對W後的第二個運算單元做多工,這樣就只需要一組乘法器,要壓縮面積的話,甚至可以直接根據 mode+Vgs+Vds 寫一個 case 的電路,給出乘法單元的第二個運算元(也就是要算電流的話,不用乘法器跟減法器去做2(Vgs-1)Vds....這件事情)。 ### Sample Code 以下這段程式碼則可以給出一個排序 6 個 unsigned input 的電路,欲了解具體架構可以搜尋關鍵字 **sorting network**,應該就能找到容易參數化或最佳化的各種排序網絡。可以注意到"唯一"的 always block內有很多變量都被重複給值,這就是應用到 always 依序執行的特性,讓我可以重複利用相同名字的變量堆出複雜結構。 ```verilog= module sorter( //using odd even mergesort algorithm //input mode, i0,i1,i2,i3,i4,i5, //output o0,o1,o2 ); input mode; input [7:0] i0,i1,i2,i3,i4,i5; output reg [7:0] o0,o1,o2; reg [7:0] s0,s1,s2,s3,s4,s5; //eventually, s0 is largest, and s5 is smallest always@(*) begin {s0,s1,s2,s3,s4,s5} = {i0,i1,i2,i3,i4,i5}; //level1 {s0,s1} = (s0>s1)?{s0,s1}:{s1,s0}; {s2,s3} = (s2>s3)?{s2,s3}:{s3,s2}; {s4,s5} = (s4>s5)?{s4,s5}:{s5,s4}; //level2 {s0,s2} = (s0>s2)?{s0,s2}:{s2,s0}; {s1,s3} = (s1>s3)?{s1,s3}:{s3,s1}; //level3 {s1,s2} = (s1>s2)?{s1,s2}:{s2,s1}; //level4 {s0,s4} = (s0>s4)?{s0,s4}:{s4,s0}; {s1,s5} = (s1>s5)?{s1,s5}:{s5,s1}; //level5 {s2,s4} = (s2>s4)?{s2,s4}:{s4,s2}; {s3,s5} = (s3>s5)?{s3,s5}:{s5,s3}; //level6 {s1,s2} = (s1>s2)?{s1,s2}:{s2,s1}; {s3,s4} = (s3>s4)?{s3,s4}:{s4,s3}; //output {o0,o1,o2} = (mode)?{s0,s1,s2}:{s3,s4,s5}; //mode[1]: 0-> work on smaller results 1->work on larger result end endmodule ``` ### Performance Area:36k $um^2$ Rank:22/149

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully