前端設計
數字系統設計中有三個重要的設計級別概念:行為級(Behavior Level)、寄存器傳輸級(Register Transfer Level)和門級(Gate level)。其中,
行為級通過行為級算法描述數字系統;
寄存器傳輸級通過寄存器之間的數據傳輸進行電路功能設計,例如有限狀態機;
門級按AND、OR、NOT、NAND等等描述,通常不會進行門級設計,門級網表一般是通過邏輯綜合的輸出。
RTL可以用Verilog或VHDL描述。Verilog是一種用于描述數字系統的硬件描述語言(HDL),例如Latches、Flip-Flops、組合邏輯、時序邏輯等。基本上,你可以使用Verilog來描述任何類型的數字系統。設計通常以自頂向下的方式編寫,系統具有層次結構,使得設計和調試更容易。verilog模塊的基本框架如下:
module top_module( input clk, input rst, input [7:0] in_data, output [7:0] out_data ); // Instantiate submodules here // Your code here endmodule
模塊實例化(module instance)時,需要指定被實例化的模塊名稱(例如NAND或INV)、實例名稱(在當前模塊中唯一標識該實例)和端口連接列表。模塊端口連接可以按照位置順序(位置映射)或者名稱對應(命名映射)給出。一般推薦使用命名映射,因為可以避免一些錯誤。
1.按名稱進行端口映射:
INV V2(.in(a), .out(abar));
2.按順序進行端口映射,這種情況下,端口列表的順序要和被實例化的模塊一致:
AND A1(a, b, d);
下面是一個簡單的D觸發器 Verilog示例代碼:
module dff (q, d, clk, rst); output q; input d, clk, rst; reg q; always @(posedge clk or posedge rst) if (rst) q <= 0; else q <= d; endmodule
數字電路設計分為組合邏輯和時序邏輯兩種。
用Verilog編寫的代碼并不一定都能綜合成電路。我們需要保證我們的代碼能綜合出我們想要的電路。在Verilog中,有些與時間相關的語句是不能綜合的。比如,wait, initial, delay等。
在Verilog中,可以用always語句塊來建模電平敏感和邊沿敏感的電路行為。
用always語句塊建模組合電路時,要注意每個輸出都要依賴于敏感列表。如果沒有完全指定組合電路,可能會綜合出鎖存器(latch)。
驗證
在數字系統設計完成后,要用仿真來驗證邏輯功能是否正確。在Verilog中,可以用testbench(測試平臺)來檢驗代碼。編寫testbench的一些基本原則如下:
1、Testbench要實例化設計的頂層模塊,并給它提供輸入激勵(stimulus)。
2、設計(DUT)的輸入激勵要用'reg'類型聲明。'reg'類型的數據可以在always或initial語句塊中改變。
3、設計(DUT)的輸出要用'wire'類型聲明。'wire'類型的數據不能在always或initial語句塊中賦值。
4、always和initial語句塊是兩種時序控制塊,它們是并行執行的。initial語句塊的一個例子如下:
module testbench; // 定義clk和reset信號 reg clk, reset; // 定義被測模塊的實例 dut dut_inst( .clk(clk), .reset(reset), // 其他端口 ); // 在initial塊中生成clk和reset激勵 initial begin // 初始化clk和reset為0 clk = 0; reset = 0; // 等待一段時間后釋放reset #10 reset = 1; // 每隔5個時間單位切換clk的值 forever #5 clk = ~clk; end endmodule
initial語句塊在仿真開始時(時間為0)按照“begin end”之間的語句順序執行。遇到延遲時,該語句塊暫停執行,等待延遲結束后繼續執行。上面的代碼是一個比較典型的復位和時鐘激勵生成的代碼。
5、系統任務。這些系統任務不會被綜合工具識別,所以可以在設計代碼中使用它們。系統任務以$符號開頭。一些常用的系統任務如下:
$display:在仿真過程中,在屏幕上顯示文本信息
$stop:暫停仿真。
$finish:結束仿真
$dumpvar,$dumpfile:生成波形文件,保存到指定的文件中。
6、tasks用于實現常用的驗證功能。tasks可以有輸入,輸出,并且可以包含時序控制。下面是一個task的例子:
// 定義一個帶有時序延遲的task task delay_task; input [7:0] data; // 輸入數據 input [3:0] delay; // 輸入延遲時間 output [7:0] result; // 輸出結果 reg [7:0] result; // 定義寄存器存儲結果 begin #delay result = data; // 延遲賦值 $display("data = %b, delay = %d, result = %b", data, delay, result); // 打印結果 end endtask // 定義一個模塊調用task module test; reg [7:0] data; // 定義數據信號 reg [3:0] delay; // 定義延遲信號 wire [7:0] result; // 定義結果信號 initial begin data = 8'b10101010; // 初始化數據 delay = 4'd10; // 初始化延遲 delay_task(data, delay, result); // 調用task #20 $finish; // 結束仿真 end endmodule
上面的代碼的功能是定義一個帶有時序延遲的task,然后在一個模塊中調用它。
7、編譯指令`timescale設置時間單位和時間精度
`timescale 10ns/1 ns // 單位 10 ns,精度 1 ns
8、Verilog測試平臺可以使用包含C語言描述的編程語言接口(PLI)。
9、在編寫testbench之前,了解設計規范(spec),并且創建所有可能的測試用例列表非常重要。
10、可以根據波形檢查信號值是否正確。
11、在編寫testbench時,可以設置斷點,也可以單步執行。
12、進行功能仿真時,最好進行受約束的隨機仿真。受約束的隨機仿真可以提供有效輸入的隨機組合。當隨機仿真運行很長時間時,它可以覆蓋大部分的corner cases。在verilog中,可以使用$random在testbench中創建隨機變量。
13、覆蓋率統計:觀察存在多少種可能性以及有多少種可能性已經通過仿真。
13.1、行覆蓋率:代碼中的行仿真覆蓋百分比,由仿真工具統計。
13.2、條件覆蓋:它檢查代碼中的各種條件語句覆蓋百分比。
13.3、狀態機覆蓋率:檢查狀態轉換覆蓋百分比。
14、回歸測試(Regression):將新的模塊添加到已驗證的代碼中。回歸測試是一種驗證方法,用于確保修改或更新后的代碼不會影響原有的功能和性能。
仿真目標
功能正確:通過驗證來驗證設計的功能,主要的test cases(主要功能)和corner cases(特殊條件下)。功能正確是仿真的基本要求,確保設計符合規范和預期。例如,可以使用assertions來檢查設計的輸出是否與預期相符。
設計的錯誤處理:通過驗證來檢測設計中可能存在的錯誤或異常情況,并測試設計如何應對或恢復。設計的錯誤處理是仿真的重要目標,提高了設計的可靠性和安全性。例如,可以使用fault injection來模擬設計中可能發生的故障,并觀察設計的反應和行為。
性能:通過驗證來評估設計的性能指標,如時延,吞吐量,功耗等,并與設計目標進行比較。性能是仿真的重要目標,影響了設計的效率和優化。例如,可以使用profiling tools來分析設計中各個部分的資源占用和執行時間,并找出性能瓶頸和改進點。
真實世界仿真
在軟件的功能仿真之后,如何在真實世界中仿真你的設計呢?
FPGA原型:加快驗證速度。
硬件加速器:將一些可綜合的代碼映射到FPGA上。其他不可綜合的部分,如testbench用仿真工具驅動。當設計非常大時,這種硬件加速驗證方法能大幅度提高驗證效率。
后端實現
在數字物理設計流程中需要對多個目標進行優化,包括面積,走線長度和功耗,以及需要確保物理實現之后的網表滿足設計的時序要求。以下將概述芯片數字后端的基本步驟:
物理設計的第一步是floor planning,定義芯片(die&core)的寬度和高度,也就是芯片的面積。
“core”是芯片的核心區域,用于放置(place)設計的基本邏輯單元。芯片是從晶圓(wafer)上切割出來的,晶圓是一種圓形的硅片,上面可以制造多個芯片(die)。
在布局布線(P&R)階段,工具會根據約束條件來放置邏輯單元。在正式進行P&R之前,需要先確定一些關鍵模塊的位置,例如RAM,ROM等。這些模塊被稱為“預放置單元(preplaced cells)”。
將關鍵模塊擺放之后,圍繞關鍵模塊擺放Decap(decoupling capacitors),提高了芯片的可靠性和效率。
在電路原理圖中,我們通常只看到一個“Vdd”和一個’Vss’,表示電源和地。但是,在芯片上,我們需要構建一個電源網絡,將電源和地分布到各個模塊。在floorplan階段,我們還需要放置引腳(pin)或焊盤(pad),用于與外部設備連接。引腳是模塊級別的接口,焊盤是芯片級別的接口。
在floorplan確定(freeze)后,就可以開始布局布線(P&R)了。P&R工具的輸入包括綜合后的門級網表,時序庫,物理庫和設計約束。P&R工具根據設計約束(constraints),例如時鐘頻率,時序裕度(margin),最大電容等,用算法來確定標準單元(Flipflops,AND,OR,BUFFER等)的位置,并把它們放在core里。
假設時鐘網絡的最大電容限制是2F。看看上面的圖,時鐘節點’B’連著4個觸發器的’clk’腳。假設每個觸發器的’clk’腳的電容是1F。那么,PNR工具就會算出節點’B’的總電容是4F。然后它會把這個電容和約束文件里的最大電容2F比較。
因為節點’B’的電容超過了2F,工具就會用2個buffer把節點’B’的負載分開,就像圖上那樣。它從庫里選buffer(假設每個buffer的輸入電容是1F),并建一個樹(時鐘樹),來滿足設計的最大電容約束。這個過程叫做’時鐘樹綜合(Clock tree synthesis)'。
最后,物理設計完成后,PNR工具會對原來的網表做一些修改。比如:加buffer,調整單元大小(size)等。然后,可以提取電阻和電容的值RC(resistances、capacitance),把它們保存在一個文件里,一般叫做SPEF(Standard Parasitic Extraction Format)文件。
最后,要用靜態時序分析(STA)工具做timing sign off。靜態時序分析(STA)工具會檢查設計的各條路徑是否符合約束文件里的時序要求,包括建立時間檢查,保持時間檢查,最大電容檢查和過渡時間檢查等(Setup check,Hold check, Max Capacitance check 和 Transition Check)。
設計約束
3、指定設計約束
SDC(Synopsys Design Constraints)是一種基于Tcl的格式。SDC文件里的所有命令都遵循Tcl的語法規則。SDC文件用來告訴EDA工具設計的意圖,包括時序、面積和功耗等。SDC文件包含以下信息:
?版本(可選)
?單位(可選)
?約束值
?約束對象
?注釋(可選)
SDC文件里不包含加載或鏈接設計的命令。所以,在讀取SDC文件之前必須先讀取你的設計。
1、指定SDC版本
如果沒有指定SDC版本,那么版本就取決于讀取SDC文件的EDA工具。為了保證SDC文件在不同工具之間的兼容性,可以在文件開頭用以下命令指定SDC版本:
set sdc_version value
2、指定SDC單位
set_units命令指定SDC文件里的電容,電阻,時間,電壓,電流和功耗等單位。
3、指定設計約束
用約束命令來指定設計約束。如果命令太長,可以用反斜杠字符()把命令分成多行。SDC約束命令有下表這些。
4、指定約束對象
大多數約束命令都需要設計對象作為命令參數。
如果當前設計中有一個名為U1的單元,可以通過命令
[get_cells U1]
找到。下表SDC格式中尋找設計對象的命令。
同時,可以使用Tcl列表或通配符(?、*)指定多個對象。默認情況下,當前設計約束的參考點是頂級設計。我們可以使用分隔符(/)來約束層次結構化設計。
5、添加注釋
可以使用#將注釋添加到SDC文件中。
例如,
# This is an SDC comment line.
create_clock -period 10 [get_ports CLK] ; #comment fragment
6、管理大型項目SDC文件
當設計非常大時,SDC文件可能會得很大。減少SDC文件大小的一種方法是壓縮文件
read_sdc命令自動檢測gzip壓縮文件并解壓縮,然后讀取它們的文件。例如,
read_sdc design.sdc.gz
審核編輯:湯梓紅
-
asic
+關注
關注
34文章
1199瀏覽量
120439 -
Verilog
+關注
關注
28文章
1351瀏覽量
110077 -
HDL
+關注
關注
8文章
327瀏覽量
47378 -
數字設計
+關注
關注
0文章
46瀏覽量
22295 -
前端設計
+關注
關注
0文章
19瀏覽量
10049
原文標題:ASIC數字設計:前端設計、驗證、后端實現
文章出處:【微信號:數字芯片實驗室,微信公眾號:數字芯片實驗室】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論