白駒過隙,寒假已經餘額不足,回頭想想,也就是看了兩本書,做了幾個並不大的工程,看著QQ群裡面一些大神們聊天,時不時有的沒的還插幾句,一句話沒人理也是正常事情。有時候還幫同是菜鳥的網友解決問題,好不尷尬!在大神們的隻言片語中,也汲取出來一點對行業的認識,數電、模電和信號處理這幾門課沒有系統的學習沒有學 ...
白駒過隙,寒假已經餘額不足,回頭想想,也就是看了兩本書,做了幾個並不大的工程,看著QQ群裡面一些大神們聊天,時不時有的沒的還插幾句,一句話沒人理也是正常事情。有時候還幫同是菜鳥的網友解決問題,好不尷尬!在大神們的隻言片語中,也汲取出來一點對行業的認識,數電、模電和信號處理這幾門課沒有系統的學習沒有學確實基礎比較差,被前輩指教後也是深深認識到自己太急於求成了,晚上的博文魚龍混雜、千篇一律,所以還不如靜下心來讀一本好書。學到的只是就應該用出來,才能成為自己的東西,下麵的非同步複位,同步釋放機制,是我根據自己的理解總結出來的。
D觸發器的兩種表示形式
同步複位
1 always @(posedge mclk) 2 begin 3 if(!rst_n)//if(rst_p) 4 q <= 1’b0; 5 else 6 q <= d; 7 end
非同步複位
1 always @(posegde mclk or negdege rst_n) 2 或always @(posedge mclk or posedge rst_n) 3 begin 4 if(!rst_n)//if(rst_p) 5 q <= 1’b0; 6 else 7 q <= d; 8 end
同步複位即複位信號隨系統時鐘的邊沿觸發起作用,非同步複位即複位信號不隨系統時鐘的邊沿觸發起作用,rst_n表示低電平複位與rst_p表示高電平複位,記得當時還被同步置數和非同步置數困擾了好久,現在順便也總結一下吧!
D觸發器同步置數,非同步置數。
非同步複位,同步置數
1 always @(posegde mclk or negedge rst_n) 2 begin 3 if(!rst_n) 4 q <= 1’b0 5 else if(en)//enable使能信號,當en為高電平時D觸發器觸發 6 q <= d; 7 else 8 q <= q; 9 end
非同步複位,非同步置數
1 always @(posedge mclk or posedge en or negedge rst_n) 2 begin 3 if(!rst_n) 4 q <= 1’b0; 5 else if(en) //enable使能信號,當en為高電平時D觸發器觸發 6 q <= d; 7 else 8 q <= q; 9 end
同步非同步無非就是一個是否受系統時鐘邊沿觸發,如果想要非同步就直接加一個敏感信號就好了。不過一般工程中的書寫形式就是非同步複位,不過這種設計方法也有弊端,所以下麵總結一下非同步複位、同步釋放的設計思想。(競爭與冒險)
非同步複位、同步釋放機制。
這是非同步複位的結構圖,D觸發器是複位優先順序高於clk優先順序,所以採用通非同步複位的方法,但是非同步複位D觸發器存在競爭與冒險,比如當clk的上升沿和rst_n的下降沿同時來臨的時候這時候系統應該聽誰的,同樣當clk的上升沿和rst_n的上升沿同時來臨的時候容易使寄存器出現亞穩態。
再來看看同步複位的邏輯結構圖,同步複位雖然解決了當clk的邊沿來臨的時候rst_n的邊沿也正好來臨所出現的冒險與競爭,但是從綜合的電路上可以看出,多了一個組合邏輯,選擇器(MUX),可想而知如果所有的複位都是這樣,那會多浪費多少資源。那麼有沒有更好的解決辦法呢?答案是有,那就是非同步複位同步釋放機制。
1 always @(posedge mclk or negedge rst_n)//asynchronous reset synchronous release 2 begin 3 if(!rst_n)begin 4 rst_n1 <= 1'b0; 5 rst_n2 <= 1'b0; 6 end 7 else begin 8 rst_n1 <= rst_n; 9 rst_n2 <= rst_n1; 10 end 11 end
這是複位信號同步化代碼,系統時鐘不變化,還是採用非同步複位的方法,但是當複位信號操作時會進入一個同步寄存器,使得複位信號同步化,這樣既避免了非同步複位的冒險與競爭,又避免了同步複位耗費太多資源。只需要將複位信號同步化編寫成獨立模塊,然後頂層例化就好了。系統時鐘信號不變化。
上電延時
開發板接通電源後會有一小段不穩定的狀態,在比較大的工程中,邏輯資源利用的比較多的情況下,如果加上電源後直接進行複位操作,同樣會使寄存器不穩定,所以,類似於按鍵消抖的方法,我們也給板子加電源後延時50ms,當系統穩定後在進行複位操作,再看bingo的書時,他是將這兩個個分成兩個模塊然後實例化到一起,但為了提高代碼的可移植性,我將非同步複位同步釋放和上電延時50ms寫在一個模塊。具體實現如下。
1 module sys_ctrl( 2 input mclk, 3 input rst_n, 4 output sys_clk, 5 output sys_rst_n 6 ); 7 8 parameter SYS_DELAY = 24'd2500000;//delay50ms 9 //parameter SYS_DELAY = 24'd25;//just test 10 11 wire delay_done;//delay 50ms finish flag 12 reg rst_n1; 13 reg rst_n2; 14 reg [23:0] cnt;//count system delay 50ms 15 16 always @(posedge mclk or negedge rst_n)//asynchronous reset synchronous release 17 begin 18 if(!rst_n)begin 19 rst_n1 <= 1'b0; 20 rst_n2 <= 1'b0; 21 end 22 else begin 23 rst_n1 <= rst_n; 24 rst_n2 <= rst_n1; 25 end 26 end 27 28 always @(posedge mclk)//It don't depend on rst_n when power up 29 begin 30 if(cnt == SYS_DELAY - 1'b1) 31 cnt <= cnt; 32 else if(cnt < SYS_DELAY - 1'b1) 33 cnt <= cnt + 1'b1; 34 else 35 cnt <= 24'd0; 36 end 37 assign delay_done = (cnt == SYS_DELAY - 1'b1)?1'b1:1'b0; 38 39 assign sys_clk = mclk; 40 assign sys_rst_n = delay_done & rst_n2; 41 42 endmodulesys_ctrl
對於較小的工程,進行這些操作與否也就無可厚非,如果對於一個項目,需要要求必須盡善盡美,FPGA的優勢便是數字信號處理,速度快,我們在保持速度的前提下,還需要使其準確率也提高,儘量占用少量的資源。這樣非同步複位,同步釋放的機制就體現出來了。