基于FPGA的跨時鐘域信號處理——MCU
說到異步時鐘域的信號處理,想必是一個FPGA設計中很關鍵的技術,也是令很多工程師對FPGA望而卻步的原因。但是異步信號的處理真的有那么神秘嗎?那么就讓特權同學和你一起慢慢解開這些所謂的難點問題,不過請注意,今后的這些關于異步信號處理的文章里將會重點從工程實踐的角度出發(fā),以一些特權同學遇到過的典型案例的設計為依托,從代碼的角度來剖析一些特權同學認為經典的跨時鐘域信號處理的方式。這些文章都是即興而寫,可能不會做太多的分類或者歸納,也有一些特例,希望網友自己把握。
本文引用地址:http://www.butianyuan.cn/article/268640.htm另外,關于異步時鐘域的話題,推薦大家不妨去看看這些不錯的文章,如《跨越鴻溝:同步世界中的異步信號》等。
首先說MCU與FPGA之間的異步通信,參加CPLD助學活動的朋友應該都注意到了那塊BJ-EPM板子上預留了16PIN的單片機接口,但是那個實驗里其實也沒有給出什么實驗代碼。究其原因,大概是特權同學有點自私了吧(呵呵~~~),因為當初剛接觸MCU與FPGA通信處理的時候,是為了做一個液晶控制板,用的是很老的EPM7128,資源很小,摸索了個把月才搞定,不過當時的處理方式上并不穩(wěn)妥,后來隨著不斷學習不斷積累經驗才尋覓到現在的處理方式。不想公開源碼自有所謂的“比較關鍵的技術”一說,現在想來蠻有些可笑的。網絡這么大一個平臺,憑什么你只索取不共享呢?所以,特權同學今后會努力把自己的點點滴滴設計經驗和大家分享。當然了,在提出自己的觀點和看法的同時,也一定會得到更多高人不同的也許更好的見解,幫助他人的同時自己也在進步,何樂而不為呢。
羅嗦了一大堆,步入正題吧……
首先,這個項目是基于單片機的應用,如果你對單片機的讀寫時序不是很熟練,不妨看看特權同學的一篇詳細討論51單片機擴展RAM讀寫時序的文章《單片機的擴展RAM讀寫時序》。下面簡單看下11.0592MHz的51單片機的讀寫時序圖吧。
![點擊看大圖](http://editerupload.eepw.com.cn/201501/201af01f360c63cb44dcbafeb3a9f737.jpg)
大體和上面的波形相差無幾,地址總線沒有畫出來,不過地址總線一般是會早于片選CS到來,并且晚于片選信號CS撤銷(這個說法不是絕對的,但是至少對于下面的應用是這樣)。
我們現在的工作是作為MCU的從機,即模擬MCU的擴展RAM。MCU若發(fā)出寫時序,FPGA就得在數據穩(wěn)定于數據總線時將其鎖存起來;MCU發(fā)出讀時序,FPGA就要在MCU鎖存數據的建立時間之前把數據放到數據總線上,并且到MCU鎖存數據的保持時間結束后才能將數據撤銷?;旧?,我們要干的就是這些活,下面討論verilog在設計上如何實現,但是限于篇幅,不對時序分析做討論,假定這是一個很理想的總線時序。
其實這個MCU的讀寫時序的時間相對還是很充裕的,因為我們的FPGA用的是50MHz的晶振。所以一個很基本的想法是要求我們把MCU端的信號同步到FPGA的時鐘域上,達到異步信號的同步處理。
verilog代碼:
//----------------------------------------------------------------------
//----------------------------------------------------------------------
input clk; //50MHz
input rst_n; //復位信號,低有效
input mcu_cs_n; //MCU片選信號,低有效
input mcu_wr_n; //MCU寫信號,低有效
input[3:0] mcu_addr; //MCU地址總線
input[7:0] mcu_db; //MCU數據總線
reg[3:0] mcu_addr_r; //mcu_addr鎖存寄存器
reg[7:0] mcu_db_r; // mcu_db鎖存寄存器
//////mcu_cs_n和mcu_wr_n同時拉低時wr_state拉低,表示片選并寫選通
wire wr_state = mcu_cs_n || mcu_wr_n; //寫狀態(tài)標志位,寫選通時拉底
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
mcu_addr_r <= 4’h0;
mcu_db_r <= 8’h00;
end
else if(!wr_state) begin
mcu_addr_r <= mcu_addr;// mcu_addr鎖存寄存器
mcu_db_r <= mcu_db;// mcu_db鎖存寄存器
end
wire pos_wr; // MCU寫狀態(tài)上升沿標志位
reg wr1,wr2; // MCU寫狀態(tài)寄存器
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
wr1 <= 1'b1;
wr2 <= 1'b1;
end
else begin
wr1 <= wr_state;
wr2 <= wr1;
end
assign pos_wr = ~wr2 && wr1; //寫選通信號上升沿pos_wr拉高一個時鐘周期
上面的代碼就是基于MCU發(fā)出的異步時序的一種同步處理。當然了,這種處理是基于特定的應用。MCU寫選通撤銷時,pos_wr信號(使用了脈沖邊沿檢測方法處理)會拉高一個時鐘周期,就可以利用此信號作為后續(xù)處理的狀態(tài)機中的一個指示信號。然后對已經鎖存在FPGA內部相應寄存器里的地址總線和數據總線進行處理。
另外,對于mcu_addr_r和mcu_db_r的鎖存為什么要在wr_state為低時進行,這個問題特權同學是這么考慮的:wr_state拉低期間即MCU片選和寫選通同時有效期間數據總線/地址總線一定是穩(wěn)定的,而為了有更充足的數據建立時間,比較常見的做法是用mcu_wr_n的上升沿鎖存數據,而如果用諸如posedge mcu_wr_n來做觸發(fā)鎖存數據/地址,那就很容易出現異步沖突的問題(這個問題的危害以后的文章詳細討論),達不到同步的效果,所以這里就用一個電平信號作為使能信號來得更加穩(wěn)妥。換個角度看,無非是wr_state上升沿的前0-20ns都有可能是最后鎖存下來的數據,這對于我們充足的MCU寫時序來說是綽綽有余了。理論上來說,wr_stata是一個總線使能信號,應該要做至少一級同步再使用更穩(wěn)妥一些,但是出于我們充裕的時序,即便是wr_stata沒有進行同步處理,退一步說,出現了wr_state的一個亞穩(wěn)態(tài)時在鎖存數據,那么此時的數據總線/地址總線的數據也不會受到影響,該什么值還是什么值。不同的應用中往往有允許非常規(guī)處理的時候,就像時序分析中的時序例外一樣。希望大家能理解這個部分,不理解也沒有關系,以后的文章會更深入探討異步時鐘域中亞穩(wěn)態(tài)這個大問題,到時再回頭看看也許你就明白了。
fpga相關文章:fpga是什么
51單片機相關文章:51單片機教程
晶振相關文章:晶振原理
評論