轉自http://ninghechuan.com
你要的FPGA&數字前端筆面試題來了
FPGA&ASIC基本開發流程
題目:簡述ASIC設計流程,並列舉出各部分用到的工具。
勘誤:Calibre是Mentor公司的
ASIC開發基本流程
芯片架構,考慮芯片定義、工藝、封裝
RTL設計,使用Verilog、System Verilog、VHDL進行描述
功能仿真,理想情況下的仿真
驗證,UVM驗證方法學、FPGA原型驗證
綜合,邏輯綜合,將描述的RTL代碼映射到基本邏輯單元門、觸發器上
DFT技術,插入掃描鏈
等價性檢查,使用形式驗證技術
STA,靜態時序分析
布局規划,保證沒有太多的內部交互,避免布線上的擁堵和困擾
時鍾樹綜合,均勻地分配時鍾,減少設計中不同部分間的時鍾偏移
DRC,設計規則檢查
LVS,布線圖和原理圖進行比較
生成GDSII
這整個流程稱為RTL2GDSII,利用GDSII來生產芯片的過程稱作流片(Tapeout),以上是一個Fabless公司的簡易設計流程,最后將GDSII送至Foundry生產芯片。
題目:簡述FPGA的開發流程。
FPGA開發基本流程
系統規划,系統功能,功能模塊划分
RTL設計,使用Verilog、System Verilog、VHDL進行描述
功能仿真,理想情況下的仿真
綜合、編譯、布局布線,FPGA廠商自帶工具完成
時序仿真,時序分析約束
板級驗證
題目:名詞解釋:
ROM:Read Only Memory,只讀存儲器,手機、計算機等設備的存儲器,但現在的所說的ROM不只是Read Only了,也是可以寫入的。
RAM:Random Access Memory,隨機存取存儲器,手機、計算機的運行內存。
SRAM:Static Random-Access Memory,靜態隨機存取存儲器,只要供電數據就會保持,但斷電數據就會消失,也被稱為Volatile Memory
DRAM:Dynamic Random Access Memory,動態隨機存儲器,主要原理是利用電容存儲電荷的多少來代表一個bit是0還是1,由於晶體管的漏電電流現象,電容會放電,所以要周期性的給電容充電,叫刷新。SRAM不需要刷新也會保持數據丟失,但是兩者斷電后數據都會消失,稱為Volatile Memory
SDRAM:Synchronous Dynamic Random Access Memory,同步動態隨機存儲器,同步寫入和讀出數據的DRAM。
EEPROM:Electrically Erasable Programmable Read Only Memory,電可擦除可編程只讀存儲器,
DDR:Double Data Synchronous Dynamic Random Access Memory,雙倍速率同步動態隨機存儲器,雙倍速率傳輸的SDRAM,在時鍾的上升沿和下降沿都可以進行數據傳輸。我們電腦的內存條都是DDR芯片。
FLASH: Flash Memory,閃存,非易失性固態存儲,如制成內存卡或U盤。
數字電路基礎
題目:數制轉換
R進制數轉換為十進制數:按權展開,相加
十進制數轉化為R進制數:整數部分,除R取余法,除到商為0為止。小數部分,乘R取整法,乘到積為0為止。
二進制數轉化八進制數:三位一組,整數部分左邊補0,小數部分右邊補0。反之亦然。
二進制數轉化十六進制數:四位一組,整數部分左邊補0,小數部分右邊補0。反之亦然。
題目:邏輯函數及其化簡
公式法
卡諾圖法
題目:什么是冒險和競爭,如何消除?
下面這個電路,使用了兩個邏輯門,一個非門和一個與門,本來在理想情況下F的輸出應該是一直穩定的0輸出,但是實際上每個門電路從輸入到輸出是一定會有時間延遲的,這個時間通常叫做電路的開關延遲。而且制作工藝、門的種類甚至制造時微小的工藝偏差,都會引起這個開關延遲時間的變化。
實際上如果算上邏輯門的延遲的話,那么F最后就會產生毛刺。信號由於經由不同路徑傳輸達到某一匯合點的時間有先有后的現象,就稱之為競爭,由於競爭現象所引起的電路輸出發生瞬間錯誤的現象,就稱之為冒險,FPGA設計中最簡單的避免方法是盡量使用時序邏輯同步輸入輸出。
-
加濾波電容,消除毛刺的影響
-
加選通信號,避開毛刺
-
增加冗余項,消除邏輯冒險。
題目:用與非門等設計一個全加法器
題目:MOS邏輯門
與非門:上並下串(上為PMOS,下為NMOS)
或非門:上串下並
反相器
練習:畫出Y = A·B + C的CMOS電路圖
Y = (A·B + C)” = ((A·B)’·C’)’,一個反相器,兩個而輸入與非門。
題目:用D觸發器帶同步高置數和異步高復位端的二分頻的電路,畫出邏輯電路,Verilog描述。
reg Q; always @(posedge clk or posedge rst)begin if(rst == 1'b1) Q <= 1'b0; else if(set == 1'b1) Q <= 1'b1; else Q <= ~Q; end
題目:ASIC中低功耗的設計方法和思路(不適用於FPGA)
-
合理規划芯片的工作模式,通過功耗管理模塊控制芯片各模塊的Clock,Reset起到控制功耗的目的。
-
門控時鍾(Clockgateing):有效降低動態功耗
-
多電壓供電:通過控制模塊的電壓來降低功耗
-
多閾值電壓
時序邏輯電路基礎
題目:簡述建立時間和保持時間,作圖說明
建立時間Tsu(setup):觸發器在時鍾上升沿到來之前,其數據輸入端的數據必須保持不變的最小時間。
保持時間Th(hold):觸發器在時鍾上升沿到來之后,其數據輸入端的數據必須保持不變的最小時間。
題目:說明D觸發器與Latch的區別。
鎖存器對電平信號敏感,在輸入脈沖的電平作用下改變狀態。
D觸發器對時鍾邊沿敏感,檢測到上升沿或下降沿觸發瞬間改變狀態。
https://www.vlsifacts.com/difference-latch-flip-flop/
題目:最小周期計算
Tco:寄存器更新延遲。clock output delay,時鍾觸發到數據輸出的最大延遲時間
最小時鍾周期:Tmin = Tco + Tdata + Tsu - Tskew。最快頻率Fmax = 1/Tmin
Tskew = Tclkd – Tclks。
題目:什么是Clock Jitter和Clock Skew,這兩者有什么區別。
時鍾抖動(Clock Jitter):指芯片的某一個給定點上時鍾周期發生暫時性變化,使得時鍾周期在不同的周期上可能加長或縮短。
時鍾偏移(Clock Skew):是由於布線長度及負載不同引起的,導致同一個時鍾信號到達相鄰兩個時序單元的時間不一致。
區別:Jitter是在時鍾發生器內部產生的,和晶振或者PLL內部電路有關,布線對其沒有影響。Skew是由不同布線長度導致的不同路徑的時鍾上升沿到來的延時不同。
題目:什么是亞穩態,產生的原因,如何消除?
亞穩態:是指觸發器無法在某個規定時間段內達到一個確定的狀態。
原因:由於觸發器的Tsu和Th不滿足,當觸發器進入亞穩態,使得無法預測該單元的輸出,這種不穩定是會沿信號通道的各個觸發器級聯傳播。
消除:兩級或多級寄存器同步。理論上亞穩態不能完全消除,只能降低,一般采用兩級觸發器同步就可以大大降低亞穩態發生的概率,再加多級觸發器改善不大。
題目:同步和異步
同步復位和異步復位的區別
同步復位是復位信號隨時鍾邊沿觸發有效。異步復位是復位信號有效和時鍾無關。
同步邏輯和異步邏輯的區別
同步邏輯是時鍾之間有固定的因果關系。異步邏輯是各時鍾之間沒有固定的因果關系
同步電路和異步電路區別
同步電路有統一的時鍾源,經過PLL分頻后的時鍾驅動的模塊,因為是一個統一的時鍾源驅動,所以還是同步電路。異步電路沒有統一的時鍾源。
跨時鍾域處理
題目:談談對Retiming技術的理解
Retiming就是重新調整時序,例如電路中遇到復雜的組合邏輯,延遲過大,電路時序不滿足,這個時候采用流水線技術,在組合邏輯中插入寄存器加流水線,進行操作,面積換速度思想。
數字集成電路
題目:反相器的速度與哪些因素有關?什么是轉換時間(transition time)和傳播延遲(propagation delay)?
反相器的速度與哪些因素有關。
-
電容(負載電容、自載電容、連線電容)較小,漏端擴散區的面積應盡可能小。輸入電容要考慮: (1)Cgs 隨柵壓而變化(2)密勒效應(3)自舉效應
-
加大晶體管的尺寸(驅動能力),使晶體管的等效導通電阻(輸出電阻)較小。但這同時加大自載電容和負載電容(下一級晶體管的輸入電容)。
-
提高電源電壓,提高電源電壓可以降低延時,即用功耗換取性能但超過一定程度后改善有限。電壓過高會引起可靠性問題(氧化層擊穿、熱電子等)。
Transition Time(轉換時間):上升時間:從10%Vdd上升到90%Vdd的時間,下降時間L從90%Vdd下降到10%dd的時間。上升時間和下降時間統稱為Transition Time,也有定義為20%到80%。
Propagation Delay(傳播延時):在輸入信號變化到50%Vdd到輸出信號變化到50%Vdd之間的時間。
### 題目:什么是高阻態
高阻態:電路的一種輸出狀態,既不是高電平也不是低電平,如果高阻態再輸入下一級電路的話,對下級電路無任何影響,可以理解為斷路,不被任何東西所驅動,也不驅動任何東西
### 題目:什么是open-drain output?
Open-Drain Output漏極開路輸出,稱為OD門,兩個OD門並聯可以實現線與功能,輸出端外接的上拉電阻提高驅動能力
題目:相同面積的cmos與非門和或非門哪個更快?
電子遷移率是空穴的2.5倍(在硅基CMOS工藝中),運算就是用這些大大小小的MOS管驅動后一級的負載電容,翻轉速度和負載大小一級前級驅動能力相關。為了上升延遲和下降延遲相同,PMOS需要做成NMOS兩倍多大小。
載流子的遷移率,對PMOS而言,載流子是空穴;對NMOS而言,載流子是電子。
PMOS采用空穴導電,NMOS采用電子導電,由於PMOS的載流子的遷移率比NMOS的遷移率小,所以,同樣尺寸條件下,PMOS的充電時間要大於NMOS的充電時間長,在互補CMOS電路中,與非門是PMOS管並聯,NMOS管串聯,而或非門正好相反,所以,同樣尺寸條件下,與非門的速度快,所以,在互補CMOS電路中,優先選擇與非門。
題目:畫出clock gating cell的原理圖。
http://vlsi.pro/integrated-clock-gating-cell/
題目:解釋一下亞穩態。
亞穩態指觸發器的輸出無法再某個規定時間段內達到一個可以確定的狀態,介於0和1之間,如圖中的2號小球既可能回到1狀態,也可能達到3狀態,亞穩態也是可以傳輸的,導致邏輯誤判系統不穩定。亞穩態有恢復時間。解決亞穩態的方法
- 降低系統時鍾
- 用更快的FF
- 引入同步機制,防止亞穩態傳播
- 改善時鍾質量
解釋一下Latch的建立時間與保持時間。
在Latch的輸入開關斷開和環路開關閉合時,有效的D輸入信號在跳變前(建立時間)和跳變后(保持時間)的短時間內不能發生變化。以保證數據被鎖存。
RTL代碼
題目:多時鍾域設計中,如何處理跨時鍾域
-
單bit:兩級觸發器同步(適用於慢到快)
-
多bit:采用異步FIFO,異步雙口RAM
-
加握手信號
-
格雷碼轉換
題目:編寫Verilog代碼描述跨時鍾域信號傳輸,慢時鍾域到快時鍾域
reg [1:0] signal_r; //------------------------------------------------------- // always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin signal_r <= 2'b00; end else begin signal_r <= {signal_r[0], signal_in}; end end assign signal_out = signal_r[1];
題目:編寫Verilog代碼描述跨時鍾域信號傳輸,快時鍾域到慢時鍾域
跨時鍾域處理從快時鍾域到慢時鍾域,如果是下面第一個圖,cklb則可以采樣到signal_a_in,但是如果只有單脈沖,如第二個圖,則不能確保采樣掉signal_a_in。這個時候用兩級觸發器同步是沒有用的。
代碼如下: //Synchronous module Sync_Pulse( input clka, input clkb, input rst_n, input pulse_ina, output pulse_outb, output signal_outb ); //------------------------------------------------------- reg signal_a; reg signal_b; reg [1:0] signal_b_r; reg [1:0] signal_a_r; //------------------------------------------------------- //在clka下,生成展寬信號signal_a always @(posedge clka or negedge rst_n)begin if(rst_n == 1'b0)begin signal_a <= 1'b0; end else if(pulse_ina == 1'b1)begin signal_a <= 1'b1; end else if(signal_a_r[1] == 1'b1) signal_a <= 1'b0; else signal_a <= signal_a; end //------------------------------------------------------- //在clkb下同步signal_a always @(posedge clkb or negedge rst_n)begin if(rst_n == 1'b0)begin signal_b <= 1'b0; end else begin signal_b <= signal_a; end end //------------------------------------------------------- //在clkb下生成脈沖信號和輸出信號 always @(posedge clkb or negedge rst_n)begin if(rst_n == 1'b0)begin signal_b_r <= 2'b00; end else begin signal_b_r <= {signal_b_r[0], signal_b}; end end assign pulse_outb = ~signal_b_r[1] & signal_b_r[0]; assign signal_outb = signal_b_r[1]; //------------------------------------------------------- //在clka下采集signal_b[1],生成signal_a_r[1]用於反饋拉低signal_a always @(posedge clka or negedge rst_n)begin if(rst_n == 1'b0)begin signal_a_r <= 2'b00; end else begin signal_a_r <= {signal_a_r[0], signal_b_r[1]}; end end endmodule
這部分代碼參考:
作者:肉娃娃
出處:https://home.cnblogs.com/u/rouwawa/
慢到快,單脈沖
慢到快,長信號傳遞
快到慢,單脈沖
單脈沖,長信號傳遞
上述代碼可以實現快到慢,慢到快時鍾域任意轉換,pulse_outb會輸出單個脈沖,signal_outb輸出信號時間長度最少為clkb的四個周期,當signal_a_in的信號長度大於clkb的四個周期,signal_outb輸出與signal_a_in時間長度相同。
題目:用Verilog實現1bit信號邊沿檢測功能,輸出一個周期寬度的脈沖信號。
- 上升沿
- 下降沿
- 上升沿或下降沿
input clk, rst_n, data; output data_edge;
module Edge_Detect( input clk, input rst_n, input data, output pos_edge, output neg_edge, output data_edge ); reg [1:0] data_r; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin data_r <= 2'b00; end else begin data_r <= {data_r[0], data}; end end assign pos_edge = ~data_r[1] & data_r[0]; assign neg_edge = data_r[1] & ~data_r[0]; assign data_edge = pos_edge | neg_edge; endmodule
怎么記憶:上升沿之前是0,現在變成1,所以上個周期傳輸到的signal_r[1]是0所以取反。反之亦然。
題目:用Verilog實現串並轉換
- lsb優先
- msb優先
input clk, rst_n, data_i; output [7:0] data_o;
module Deserialize( input clk, input rst_n, input data_i, output reg [7:0] data_o ); //lsb first /* always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin data_o <= 8'b0; end else begin data_o <= {data_o[6:0], data_i}; end end */ //msb first reg [2:0] cnt; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin data_o <= 8'b0; cnt <= 3'd0; end else begin data_o[7 - cnt] <= data_i; cnt <= cnt + 1'b1; end end endmodule
題目:序列檢測器:有“101”序列輸入時輸出為1,其他輸入情況下,輸出為0。畫出狀態轉移圖,並用Verilog描述。
input clk, rst_n, data; output flag_101;
module Detect_101( input clk, input rst_n, input data, output flag_101 ); parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3; reg [1:0] state; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin state <= S0; end else begin case(state) S0: if(data == 1) state <= S1; else state <= S0; S1: if(data == 0) state <= S2; else state <= S1; S2: if(data == 1) state <= S3; else state <= S0; S3: if(data == 1) state <= S1; else state <= S2; endcase end end assign flag_101 = (state == S3)? 1'b1: 1'b0; endmodule
題目:用Verilog實現一個異步雙端口ram,深度16,位寬8bit。A口讀出,B口寫入。支持片選,讀寫請求,要求代碼可綜合。
module dpram_16x8 ( input clk_a, input [3:0] addr_a, output [7:0] dout_a, ... input clk_b, input [7:0] din_b, input [3:0] addr_b, ... ); ... endmodule
module Dual_Port_Sram #( parameter ADDR_WIDTH = 4, parameter DATA_WIDTH = 8, parameter DATA_DEPTH = 1 << ADDR_WIDTH ) ( input clka, input clkb, input rst_n, input csen_n, //Port A Signal input [ADDR_WIDTH-1:0] addra, output reg [DATA_WIDTH-1:0] data_a, input rdena_n, //Port B Signal input [ADDR_WIDTH-1:0] addrb, input wrenb_n, input [DATA_WIDTH-1:0] data_b ); integer i; reg [DATA_WIDTH-1:0] register[DATA_DEPTH-1:0]; always @(posedge clkb or negedge rst_n)begin if(rst_n == 1'b0)begin for(i = 0; i < DATA_DEPTH; i = i + 1) register[i] <= 'b0000_1111; end else if(wrenb_n == 1'b0 && csen_n == 1'b0) register[addrb] <= data_b; end always @(posedge clka or negedge rst_n)begin if(rst_n == 1'b0)begin data_a <= 0; end else if(rdena_n == 1'b0 && csen_n == 1'b0) data_a <= register[addra]; else data_a <= data_a; end endmodule
題目:用Verilog實現三分頻電路,要求輸出50%占空比。
module Div_three( input clk, input rst_n, output div_three ); reg [1:0] cnt; reg div_clk1; reg div_clk2; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin cnt <= 0; end else if(cnt == 2) cnt <= 0; else begin cnt <= cnt + 1; end end always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin div_clk1 <= 0; end else if(cnt == 0)begin div_clk1 <= ~div_clk1; end else div_clk1 <= div_clk1; end always @(negedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin div_clk2 <= 0; end else if(cnt == 2)begin div_clk2 <= ~div_clk2; end else div_clk2 <= div_clk2; end assign div_three = div_clk2 ^ div_clk1; endmodule
題目:用Verilog實現glitch free時鍾切換電路。輸入sel,clka,clkb,sel為1輸出clka,sel為0輸出clkb。
part1是比較垃圾的寫法
part2 是兩個時鍾源是倍數的關系
part3是兩個時鍾源為異步時鍾的關系
module Change_Clk_Source( input clk1, input clk0, input select, input rst_n, output outclk ); //------------------------------------------------------- //part 1 //assign outclk = (clk1 & select) | (~select & clk0); //------------------------------------------------------- //part 2 reg out1; reg out0; always @(negedge clk1 or negedge rst_n)begin if(rst_n == 1'b0)begin out1 <= 0; end else begin out1 <= ~out0 & select; end end always @(negedge clk0 or negedge rst_n)begin if(rst_n == 1'b0)begin out0 <= 0; end else begin out0 <= ~select & ~out1; end end assign outclk = (out1 & clk1) | (out0 & clk0); /* //------------------------------------------------------- //part 3 reg out_r1; reg out1; reg out_r0; reg out0; always @(posedge clk1 or negedge rst_n)begin if(rst_n == 1'b0)begin out_r1 <= 0; end else begin out_r1 <= ~out0 & select; end end always @(negedge clk1 or negedge rst_n)begin if(rst_n == 1'b0)begin out1 <= 0; end else begin out1 <= out_r1; end end always @(posedge clk0 or negedge rst_n)begin if(rst_n == 1'b0)begin out_r0 <= 0; end else begin out_r0 <= ~select & ~out1; end end always @(negedge clk0 or negedge rst_n)begin if(rst_n == 1'b0)begin out0 <= 0; end else begin out0 <= out_r0; end end assign outclk = (out1 & clk1) | (out0 & clk0); */ endmodule
兩個時鍾源頻率呈倍數關系
兩個時鍾源是異步時鍾。
題目:用Verilog實現異步復位同步釋放電路。
module Sys_Rst( input clk, input rst, output sys_rst ); reg rst_r0; reg rst_r1; always @(posedge clk or posedge rst)begin if(rst)begin rst_r0 <= 1'b1; rst_r1 <= 1'b1; end else begin rst_r0 <= 1'b0; rst_r1 <= rst_r0; end end assign sys_rst = rst_r1; endmodule
題目:用Verilog實現按鍵抖動消除電路,抖動小於15ms,輸入時鍾12MHz。
module debounce( input clk,//12Mhz input rst_n, input key_in, output key_flag ); parameter JITTER = 240;//12Mhz / (1/20ms) reg [1:0] key_r; wire change; reg [15:0] delay_cnt; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin key_r <= 0; end else begin key_r <= {key_r[0],key_in}; end end assign change = (~key_r[1] & key_r[0]) | (key_r[1] & ~key_r[0]); always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin delay_cnt <= 0; end else if(change == 1'b1) delay_cnt <= 0; else if(delay_cnt == JITTER) delay_cnt <= delay_cnt; else delay_cnt <= delay_cnt + 1; end assign key_flag = ((delay_cnt == JITTER - 1) && (key_in == 1'b1))? 1'b1: 1'b0; endmodule
題目:用Verilog實現一個同步FIFO,深度16,數據位寬8bit。
module Syn_fifo #( parameter DATA_WIDTH = 8, parameter ADDR_WIDTH = 4, parameter RAM_DEPTH = (1 << ADDR_WIDTH) ) ( input clk, input rst_n, input [DATA_WIDTH-1:0] data_in, input wr_en, input rd_en, output reg [DATA_WIDTH-1:0] data_out, output empty, //fifo empty output full //fifo full ); reg [ADDR_WIDTH-1:0] wr_cnt; reg [ADDR_WIDTH-1:0] rd_cnt; reg [ADDR_WIDTH-1:0] status_cnt; reg [DATA_WIDTH-1:0] data_ram; //------------------------------------------------------- assign full = (status_cnt == (RAM_DEPTH-1))? 1'b1: 1'b0; assign empty = (status_cnt == 0)? 1'b1: 1'b0; //Syn reg rd_en_r; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin rd_en_r <= 0; end else begin rd_en_r <= rd_en; end end //------------------------------------------------------- always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin wr_cnt <= 0; end else if(wr_cnt == RAM_DEPTH-1) wr_cnt <= 0; else if(wr_en)begin wr_cnt <= wr_cnt + 1'b1; end else wr_cnt <= wr_cnt; end always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin rd_cnt <= 0;