所謂邊沿檢測(cè)(又叫沿提取),就是檢測(cè)輸入信號(hào)的上升沿和下降沿。在設(shè)計(jì)數(shù)字系統(tǒng)時(shí),邊沿檢測(cè)是一種很重要的思想,實(shí)際編程時(shí)用的最多的時(shí)序電路應(yīng)該就是邊沿檢測(cè)電路和分頻電路了。
那么,邊沿檢測(cè)電路該如何實(shí)現(xiàn)呢?
我們知道,在always塊的敏感信號(hào)列表中可以直接用posedge和negedge來提取上升沿和下降沿,但是如果要在always程序塊的內(nèi)部檢測(cè)上升沿或者下降沿呢?還是用poesedge和negedge嗎?顯然是不可以的,因?yàn)檫@樣的語(yǔ)句不可綜合,我在QuartusII中嘗試了,編譯時(shí)提示 ”multiple event control statements not supported for synthesis !“,意思就是不可綜合。實(shí)際上,posedge和negedge只能用在always塊的敏感信號(hào)列表中或者testbench中,所以我們還是通過其他的辦法來實(shí)現(xiàn)吧。
要實(shí)現(xiàn)邊沿檢測(cè),最直接的想法是用兩級(jí)寄存器,第二級(jí)寄存器鎖存住某個(gè)時(shí)鐘上升沿到來時(shí)的輸入電平,第一級(jí)寄存器鎖存住下一個(gè)時(shí)鐘沿到來時(shí)的輸入電平,如果這兩個(gè)寄存器鎖存住的電平信號(hào)不同,就說明檢測(cè)到了邊沿,具體是上升沿還是下降沿可以通過組合邏輯來實(shí)現(xiàn)。如下圖所示:
圖1? 用兩級(jí)寄存器實(shí)現(xiàn)邊沿檢測(cè)
上圖使用 block 圖表示的,也可以用verilog編寫出來,代碼如下:
//邊沿檢測(cè)電路 //2014/12/10 module edge_cap ( input clk, rst_n, input pulse, output pos_edge, output neg_edge ); reg pulse_r1, pulse_r2; always @ (posedge clk or negedge rst_n) if(!rst_n) begin pulse_r1 <= 1'b0; pulse_r2 <= 1'b0; end else begin pulse_r1 <= pulse; pulse_r2 <= pulse_r1; end assign pos_edge = (pulse_r1 && ~pulse_r2) ?1:0; assign neg_edge = (~pulse_r1 && pulse_r2) ?1:0; endmodule
當(dāng)檢測(cè)到上升沿時(shí), pos_edge信號(hào)輸出一個(gè)時(shí)鐘周期的高電平; 檢測(cè)到下降沿時(shí),neg_edge輸出一個(gè)時(shí)鐘周期的高電平。
乍一看,這個(gè)電路似乎很簡(jiǎn)單地實(shí)現(xiàn)了邊沿檢測(cè)的功能,但是仔細(xì)分析就可以發(fā)現(xiàn)這種方法存在一個(gè)潛在的風(fēng)險(xiǎn):當(dāng)待測(cè)信號(hào)pulse是一個(gè)異步信號(hào)時(shí),輸出可能是亞穩(wěn)態(tài),如果pulse信號(hào)的變化剛好發(fā)生在clk時(shí)鐘的建立時(shí)間和保持時(shí)間之內(nèi),那么第一級(jí)寄存器的輸出 pulse_r1 就會(huì)進(jìn)入亞穩(wěn)態(tài),而pulse_r1的亞穩(wěn)態(tài)會(huì)立即傳遞給pos_edge和neg_edge信號(hào),從而使得整個(gè)電路的輸出進(jìn)入亞穩(wěn)態(tài),進(jìn)而影響下一級(jí)電路的正常工作,甚至導(dǎo)致整個(gè)系統(tǒng)崩潰!
因此,在進(jìn)行異步信號(hào)邊沿提取時(shí),不能直接使用上面的這種電路,而應(yīng)該先將異步信號(hào)同步化,一般采用多加一級(jí)寄存器的方法來減小亞穩(wěn)態(tài)的發(fā)生概率,如下圖所示:
圖2? 異步信號(hào)邊沿檢測(cè)
也可以用verilog編寫出來,代碼如下:
//異步信號(hào)邊沿檢測(cè)電路,三級(jí)寄存器實(shí)現(xiàn) //2014/12/08 module edge_cap ( input clk, rst_n, input pulse, output pos_edge, output neg_edge ); reg pulse_r1, pulse_r2, pulse_r3; always @ (posedge clk or negedge rst_n) if(!rst_n) begin pulse_r1 <= 1'b0; pulse_r2 <= 1'b0; pulse_r3 <= 1'b0; end else begin pulse_r1 <= pulse; pulse_r2 <= pulse_r1; pulse_r3 <= pulse_r2; end assign pos_edge = (pulse_r2 && ~pulse_r3) ?1:0; assign neg_edge = (~pulse_r2 && pulse_r3) ?1:0; endmodule
經(jīng)過這樣的同步處理后, 可以大大減小電路進(jìn)入亞穩(wěn)態(tài)的概率,如果第一級(jí)寄存器進(jìn)入了亞穩(wěn)態(tài),一般也會(huì)在一個(gè)clk周期內(nèi)穩(wěn)定下來(可能穩(wěn)定為0也可能穩(wěn)定為1),如下圖所示:
圖中pulse信號(hào)的改變剛好發(fā)生在 clk 的建立時(shí)間和保持時(shí)間之內(nèi),因而第一級(jí)寄存器的輸出pulse_r1可能會(huì)進(jìn)入亞穩(wěn)態(tài),圖中Tco為第一級(jí)寄存器pulse_r1的狀態(tài)建立時(shí)間(即clock to output),一般情況下,亞穩(wěn)態(tài)的決斷時(shí)間(即從進(jìn)入亞穩(wěn)態(tài)到穩(wěn)定下來的時(shí)間)不會(huì)超過一個(gè)時(shí)鐘周期,因此在下一個(gè)clk上升沿到來之前,pulse_r1已經(jīng)穩(wěn)定下來(可能穩(wěn)定到0也可能穩(wěn)定到1),這樣第二級(jí)寄存器就會(huì)采集到一個(gè)穩(wěn)定的狀態(tài),從而把亞穩(wěn)態(tài)限制在第二級(jí)寄存器之前,保證了整個(gè)電路輸出的穩(wěn)定性。
綜上所述,在異步信號(hào)邊沿檢測(cè)電路中,至少需要采用三級(jí)寄存器來實(shí)現(xiàn),在對(duì)系統(tǒng)穩(wěn)定性要求較高的數(shù)字系統(tǒng)中,可以采用更多級(jí)的寄存器來減小亞穩(wěn)態(tài)發(fā)生概率,提高系統(tǒng)穩(wěn)定性。
評(píng)論
查看更多