1. 程式人生 > 其它 >FPGA面試筆試題

FPGA面試筆試題

1、什麼是同步邏輯和非同步邏輯?

同步邏輯是時鐘之間有固定的因果關係。非同步邏輯是各時鐘之間沒有固定的因果關係。

〔補充〕:

同步時序邏輯電路的特點:各觸發器的時鐘端全部連線在一起,並接在系統時鐘端,只有當時鍾脈衝到來時,電路的狀態才能改變。改變後的狀態將一直保持到下一個時鐘脈衝的到來,此時無論外部輸入有無變化,狀態表中的每個狀態都是穩定的。

非同步時序邏輯電路的特點:電路中除可以使用帶時鐘的觸發器外,還可以使用不帶時鐘的觸發器和延遲元件作為儲存元件,電路中沒有統一的時鐘,電路狀態的改變由外部輸入的變化直接引起。

2、同步電路和非同步電路的區別是什麼?

同步電路:儲存電路中所有觸發器的時鐘輸入端都接同一個時鐘脈衝源,因而所有觸發器的狀態的變化都與所加的時鐘脈衝訊號同步。

非同步電路:電路沒有統一的時鐘,有些觸發器的時鐘輸入端與時鐘脈衝源相連,這有這些觸發器的狀態變化與時鐘脈衝同步,而其他的觸發器的狀態變化不與時鐘脈衝同步。

3、時序設計的實質:

電路設計的難點在時序設計,時序設計的實質就是滿足每一個觸發器的建立/保持時間的而要求。

4、建立時間與保持時間的概念?

建立時間:觸發器在時鐘上升沿到來之前,其資料輸入端的資料必須保持不變的時間。

保持時間:觸發器在時鐘上升沿到來之後,其資料輸入端的資料必須保持不變的時間。 不考慮時鐘的偏移,D2的建立時間不能大於(時鐘週期T-D1資料最遲到達時間T1max+T2max);保持時間不能大於(D1資料最快到達時間T1

min+T2min);否則D2的資料將進入亞穩態並向後級電路傳播。

5、什麼是亞穩態?為什麼兩級觸發器可以防止亞穩態傳播?

亞穩態是指觸發器無法在某個規定的時間段內到達一個可以確認的狀態。 使用兩級觸發器來使非同步電路同步化的電路其實叫做“一步同位器”,他只能用來對一位非同步訊號進行同步。 兩級觸發器可防止亞穩態傳播的原理:假設第一級觸發器的輸入不滿足其建立保持時間,它在第一個脈衝沿到來後輸出的資料就為亞穩態,那麼在下一個脈衝沿到來之前,其輸出的亞穩態資料在一段恢復時間後必須穩定下來,而且穩定的資料必須滿足第二級觸發器的建立時間,如果都滿足了,在下一個脈衝沿到來時,第二級觸發器將不會出現亞穩態,因為其輸入端的資料滿足其建立保持時間。同步器有效的條件:同步器有效的條件:第一級觸發器進入亞穩態後的恢復時間+第二級觸發器的建立時間 <= 時鐘週期。 更確切地說,輸入脈衝寬度必須大於同步時鐘週期與第一級觸發器所需的保持時間之和。最保險的脈衝寬度是兩倍同步時鐘週期。所以,這樣的同步電路對於從較慢的時鐘域來的非同步訊號進入較快的時鐘域比較有效,對於進入一個較慢的時鐘域,則沒有作用。

6、對競爭冒險的理解,以及如何消除?

在組合邏輯中,由於門的輸入訊號通路中經過了不同的延時,導致到達該門的時間不一致叫競爭。產生毛刺叫冒險。如果布林式中有相反的訊號則可能產生競爭和冒險現象。

解決方法:一是添加布爾式的消去項,二是在晶片外部加電容。

7、FPGA結構一般分為三部分:

可程式設計邏輯塊(CLB)、可程式設計I/O模組和可編內部連線。

8、用VHDL/Veilog HDL語言開發可程式設計邏輯電路的完整流程:

文字編輯享有→功能模擬→邏輯綜合→佈局佈線→時序模擬。

綜合其目的是將多個模組化設計檔案合併為一個網表文件,供佈局佈線使用,網表中包含了目標器件中的邏輯單元和互連的資訊。

佈局佈線就是根據設計者指定的約束條件(如面積、延時、時鐘等)、目標器件的結構資源和工藝特性,以最優的方式對邏輯元件佈局,並準確地實現元件間的互連,完成實現方案(網表)到使實際目標器件(FPGA或CPLD)的變換。

9、FPGA過程中的模擬有三種:

行為模擬、邏輯模擬、時序模擬。

10、鎖存器(latch)和觸發器(flip-flop)區別?

電平敏感的儲存期間稱為鎖存器。可分為高電平鎖存器和低電平鎖存器,用於不同時鐘之間的訊號同步。

有交叉耦合的門構成的雙穩態的儲存原件稱為觸發器。分為上升沿觸發和下降沿觸發。可以認為是兩個不同電平敏感的鎖存器串連而成。前一個鎖存器決定了觸發器的建立時間,後一個鎖存器則決定了保持時間。

11、系統最高速度計算(最快時鐘頻率)和流水線設計思想:

同步電路的速度是指同步系統時鐘的速度,同步時鐘愈快,電路處理資料的時間間隔越短,電路在單位時間內處理的資料量就愈大。假設Tco是觸發器的輸入資料被時鐘打入到觸發器到資料到達觸發器輸出端的延時時間;Tdelay是組合邏輯的延時;Tsetup是D觸發器的建立時間。假設資料已被時鐘打入D觸發器,那麼資料到達第一個觸發器的Q輸出端需要的延時時間是Tco,經過組合邏輯的延時時間為Tdelay,然後到達第二個觸發器的D端,要希望時鐘能在第二個觸發器再次被穩定地打入觸發器,則時鐘的延遲必須大於Tco+Tdelay+Tsetup,也就是說最小的時鐘週期Tmin=Tco+Tdelay+Tsetup,即最快的時鐘頻率Fmax=1/Tmin。FPGA開發軟體也是通過這種方法來計算系統最高執行速度Fmax。因為Tco和Tsetup是由具體的器件工藝決定的,故設計電路時只能改變組合邏輯的延遲時間Tdelay,所以說縮短觸發器間組合邏輯的延時時間是提高同步電路速度的關鍵所在。由於一般同步電路都大於一級鎖存,而要使電路穩定工作,時鐘週期必須滿足最大延時要求。故只有縮短最長延時路徑,才能提高電路的工作頻率。可以將較大的組合邏輯分解為較小的N塊,通過適當的方法平均分配組合邏輯,然後在中間插入觸發器,並和原觸發器使用相同的時鐘,就可以避免在兩個觸發器之間出現過大的延時,消除速度瓶頸,這樣可以提高電路的工作頻率。這就是所謂"流水線"技術的基本設計思想,即原設計速度受限部分用一個時鐘週期實現,採用流水線技術插入觸發器後,可用N個時鐘週期實現,因此係統的工作速度可以加快,吞吐量加大。注意,流水線設計會在原資料通路上加入延時,另外硬體面積也會稍有增加。

12、用D觸發器實現2倍分頻的Verilog描述?

module divide2( clk , clk_o, reset);
input   clk , reset;
output  clk_o;
wire  in;  
reg   out ;
always @ ( posedge clk or posedge reset)
begin
    if ( reset)
        out <= 0;
    else
        out <= in;
end
assign in = ~out;
assign clk_o = out;
endmodule            

13、用Verilog或VHDL寫一段程式碼,實現10進位制計數器。

`timescale 1ns/10ps
module counter10(clk,rst,count);
    input        clk,rst;
    output       [3:0]    count;
    reg          [3:0]    q;
assign count = q;
always@(posedge clk or negedge rst)
begin
    if(!rst)
        q <= 0;
    else if(q >= 4'd9)
    q <= 0;
    else
    q <= q + 1;
end
endmodule 

14、請用Verilog描述四位的全加法器。

module add_4(
    input     [3:0]    a,b,
    output    [3:0]    sum,
    output    cout,
    input     cin
);
assign{cout,sum} = a+b+cin;
endmodule

15、畫出可以檢測10010串的狀態圖,並用verilog實現。

module     seq_dect(
    input    wire    clk,
    input    wire    rst_n,
    input    wire    num_in,
    output   wire    res
);
    parameter   Idle      =    3'b000,    //
                s1        =    3'b001,    //1
                s2        =    3'b010,    //10
                s3        =    3'b011,    //100
                s4        =    3'b100,    //1001
                s5        =    3'b101,    //10010
                s6        =    3'b110,    //10001
                s7        =    3'b111;    //1000

    reg[2:0]    current_state;
    reg[2:0]    next_state;
    
    always@(posedge    clk    or    posedge    rst_n)
    begin
        if(rst_n    ==    1'b0)
        begin
            current_state    =    Idle;
            next_state       =    Idle;
        end
        else    begin
            current_state    =     next_state;
        end
    end
    
    assign res =   (current_state==s4 && num_in==0)? 1 : 0;
    
    always@(posedge    clk    or    negedge    rst_n)
    begin
        if(rst_n    ==    1'b0)
        begin
            current_state    <=      Idle;
        end
        else    begin
            case(current_state)
                    Idle:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  Idle;
                        else
                            next_state    <=  s1;    
                    end
                    s1:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s2;
                        else
                            next_state    <=  s1;    
                    end
                    s2:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s3;
                        else
                            next_state    <=  s1;    
                    end
                    s3:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s7;
                        else
                            next_state    <=  s4;
                    end
                    s4:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s5;
                        else
                            next_state    <=  s1;
                    end
                    s5:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s3;
                        else
                            next_state    <=  s1;
                    end
                    s6:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s2;
                        else
                            next_state    <=  s1;
                    end
                    s7:begin
                        if(num_in    ==    1'b0)
                            next_state    <=  s7;
                        else
                            next_state    <=  s1;
                    end
                    default:begin
                        current_state    <=  Idle;
                    end
            endcase
        end    
    end
endmodule

16、用Verilog設計一個5分頻器。

方法一:5分頻,奇數分頻都可以類似這麼做,只需要改div1和div2的引數。div1為奇數分頻除2的餘數。採用上升延和下降延分別觸發不同波形,最後疊加的方式產生奇數分頻。

    module divfreq(clk, clk1x, rst, clk1xpose, clk1xnege, coutpose, coutnege);

        input clk;
        input rst; 
        output clk1x;
        output clk1xpose;
        output clk1xnege;
        output[2:0] coutpose;
        output[2:0] coutnege;
        reg clk1xpose;
        reg clk1xnege;
        reg[2:0] coutpose;
        reg[2:0] coutnege;
        
        parameter div1 = 2 , div2 = 4;
        // div1 = ( 5 - 1 ) / 2, div2 = 5 - 1
        assign clk1x = clk1xpose | clk1xnege;
        always@(posedge clk or negedge rst)
        begin    
            if(!rst)
                clk1xpose = 0;
            else if(coutpose == div1)
                clk1xpose = ~clk1xpose;
            else if(coutpose == div2)
                clk1xpose = ~clk1xpose;
            else
                clk1xpose = clk1xpose;
        end
        
        always@(negedge clk or negedge rst)
        begin
            if(!rst)
                clk1xnege = 0;
            else if(coutnege == div1)
                clk1xnege = ~clk1xnege;
            else if(coutnege == div2)
                clk1xnege = ~clk1xnege;
            else
                clk1xnege = clk1xnege; 
        end
        
        always@(posedge clk or negedge rst)
        begin
            if(!rst)
                coutpose = 0;
            else if(coutpose == div2)
                outpose = 0;
            else
                coutpose = coutpose + 1; 
        end
        
        always@(negedge clk or negedge rst) 
        begin
            if(!rst)
                coutnege = 0;
            else if(coutnege == div2)
                coutnege = 0;    
            else
                coutnege = coutnege + 1; 
        end
    endmodule