第一篇:FPGA中同步FIFO的使用小結
FPGA中同步FIFO的使用小結
FPGA中的FIFO,分為同步FIFO,異步FIFO和雙向FIFO。同步FIFO一般用于數據的緩存,異步FIFO一般用于跨時鐘域的同步上。在這里只討論同步FIFO的使用。
由于課題中要用FPGA做圖像處理,生成3*3的模板。首先我們來分析圖像數據的傳輸方式,線陣CCD1209D為2048個有效像元,經AD采樣,每行有2048個圖像數據,以串行數據流的形式來傳輸的,一個時鐘周期傳輸一個像素數據。圖像在交由算法模塊處理之前要將得到的串行數據變成并行數據,3*3模板就是一個串并轉換模塊,串行數據經過此模塊后變為并行輸出。在圖像處理算法中的實現過程若選用3*3模板,該滑動窗在某一個時刻讀取圖像的某個像素和其相鄰像素,經過相關的處理后,用處理結果取代模板中間位置的像素值并傳送到下一個模塊。之后,每校正完一個像素,模板將不斷右移或換行,直到將一幅灰度圖像的數據陣列中的所有像素全部處理完。為了使窗中的3行3列共9個像素能夠在一個時刻同時輸出,便于之后的圖像處理算法模塊進行流水線處理,在3*3模板的硬件設計中,將采用兩個FIFO存儲器linebuffer1和linebuffer2。其中FIFO地址寬度為圖像寬度,這樣每個FIFO正好可以存儲一行圖像數據。模板生成模塊的設計框圖如下圖所示:
這里我們要用到FPGA中的同步FIFO去做linebuffer。選用Verilog HDL語言。
下面介紹使用Quartus II 9.0中的宏模塊生成FIFO的過程: 第一步,選megafunctions-> lmp_fifo –> storage->
然后點OK,接著,選Verilog語言,點下一步
注意:在這里設置,FIFO的數據位,FIFO的深度以及同步時鐘。
接著下一步,在此處可選擇設置如果你前面選擇了同步FIFO,那么這一步你需要設置FIFO的握手信號與狀態信號有full(滿),empty(空),almostfull(幾乎滿),almostempty(幾乎空),Asynchronous clear(異步清零),如果你選擇了異步FIFO,那么在讀與寫兩邊就要單獨設置,讀寫兩邊均有 full, empty, usedwide(使用深度)3個信號。
接著點下一步:
一個是FIFO的輸出的兩種形式,一種是傳統的同步方式,即你在有readreq='1'的一個周期后才能讀取數取,另一種為show ahead,即為你在readreq='0'時,數據口就一直有一個數據,在讀取數據時不用等待一個周期。第二個設置就是綜合出FIFO是用一般邏輯單元,還是使用專用的M4K塊(當然這需要在該器件有M4K塊才可以)。
接著,一直下一步,直到完成,就生成如下所示的一個同步FIFO。
這樣的話,主要問題就是讀寫使能的產生,很關鍵!!
圖中的L_VA是CCD的行數據標志,為讀使能; 寫使能是這樣的assign rdreq = L_VA &&(usedw>2047);
注意:盡量不要使FIFO滿,那樣很難控制FIFO讀寫,容易丟數據,如果FPGA存儲器允許,FIFO使用4096字節的深度。
最后,希望大家多多實驗,不斷摸索,不斷前進~~~
第二篇:LabVIEW FPGA編程小結
LabVIEW FPGA編程小結
NI PXI-7813R為FPGA卡,板卡上引出4個端口,每個端口有40路引腳,共160路DIO,使用LabVIEW FPGA模塊進行編程控制。當FPGA程序復雜度變大或是使用的DIO端口數增多時,可能面臨的主要問題包括FPGA空間不夠用以及實際循環時間過長等。之前編寫的 FPGA程序示意圖如下,采集循環與輸出循環獨立,均采用控件形式與RT程序通訊,兩塊板卡均使用了近120路DIO口。基于7813R板卡編程實踐及涉及到的幾個瓶頸問題,簡要做了一下總結:
1)使用FIFO還是使用控件?
FPGA與RT通訊時,常用的方法是使用讀寫FIFO或是使用輸入輸出控件。這兩者的特點是:
a)兩者在速度上無明顯差別。這是建立在不使用For循環的基礎上的,但實際中FIFO通常都要配合For循環來使用,For循環相當于串行操作,當同類端口較多時,使用for將導致循環時間變長,故運行速度上FIFO并沒有多少優勢。b)FIFO使用合理時不丟數,而控件不能保證。
通過配置FPGA與RT中讀寫FIFO的超時以及FIFO大小,讀寫方式等手段,通常可保證FIFO傳遞數據不丟數(可能要經過多次嘗試);而使用控件則可能會有丟數的情況。當不嚴格要求每次while循環都不丟數時,可考慮使用控件,例如對DO輸出的配置,用戶可能很久才會去配置一次,而且配置后不會要求馬上生效,稍微晚幾個循環周期(us級)再使配置生效也不會有很大影響,這種時候使用讀取控件值是合理的。c)FIFO可使用的數據類型有限,而控件幾乎無限制。
就7813R而言,FIFO只能傳遞指定的幾種類型的數據,而使用控件時,可使用包括簇數組在內的自定義控件。
所以,還是根據實際需要來選擇吧,雖然這句話跟沒說一樣~ 2)用不用For循環?
端口較多時,很容易就遇到連續幾個都是要求采集脈寬的,而另外連續幾個要求采集電平即可。這時候很自然想到使用For循環對多個端口一起進行操作,例如下圖:
如上面所說,使用FOR循環相當于使端口操作(上圖中所說的操作是指將采集到的布爾轉成U32數值)變為串行;另外,要使用For,通常就得配合數組操作,例如上圖中創建數組等,這樣就更加導致循環時間變長。當發現循環時間不滿足使用要求時,這種處理方法可能就不能使用了,每一路單獨處理就省掉了創建數組及For,節省了循環時間,但這樣又使重復代碼變多,工作量加大。
3)怎么使用子VI?
輸出脈沖時,脈沖的產生可以封裝成一個子VI,供多路端口進行使用;采集脈寬時,脈寬采集可以封裝成一個子VI供多路端口進行調用。然而,默認情況下,子VI的執行是串行的(因為并沒有設置VI屬性為“可重入執行”),子VI在同一時間內只能被一路端口所占用,可能導致的結果是循環時間變長,精度降低。如果設置子VI為可重入執行,又可能導致FPGA空間占用率過高,編譯無法通過。我想到的一種折中的辦法是:使用幾個程序框圖一樣的子VI(功能完全一樣,將子VI多另存為幾個所生成)來代替原先一個子VI,替換之后,相當于減少了串行運行的子VI數量,循環用時減少明顯。下圖中使用6個子VI A,如果用2個B與2個C替換其中的4個A,循環時間可能減少為原來的1/3。
While循環方式1:子VI A子VI A子VI A子VI A子VI A子VI AWhile循環方式2:子VI A子VI A子VI B子VI B子VI C子VI C
4)精打細算
這一點可能只會在FPGA空間不夠用時才會被重視,下圖是邏輯片不夠用時導致的FPGA編譯失敗錯誤:
因此,當資源有限時,盡量使用能滿足使用要求的最小長度的數據類型來實現,能使用U16滿足要求的堅決不用U32!另一方面,暫時還沒有發現數據類型變長時對FPGA循環運行時間產生明顯影響。
5)循環延時考慮
脈沖輸出及采集均需要根據實際循環時間來計算,若參與運算的值不是實際的循環時間,輸出或采集的結果自然不會準確。例如可配置脈沖或電平輸出的端口,若輸出電平,其算法簡單,所需時間較少,而配置為脈沖輸出時,算法復雜。配置為單路脈沖輸出可能不會有明顯的影響循環時間,但當多路脈沖一起輸出時,可能影響到循環時間增加1~2us甚至更長。故實際配置循環時間時,需按照可能的最復雜算法進行運行測試,并依此來設置循環時間,以保證循環時間的確定性已經算法運算的正確性。
總而言之,設計時還是應該根據實際需要,綜合考慮數據完整性、FPGA板卡資源大小、循環時間等因素,已達到滿意效果。
第三篇:Linux進程通信:命名管道FIFO小結(范文模版)
Linux下進程之間通信可以用命名管道FIFO完成。命名管道是一種特殊類型的文件,因為Linux中所有事物都是文件,它在文件系統中以文件名的形式存在。
在程序中,我們可以使用兩個不同的函數調用來建立管道:
#include
#include
int mkfifo(const char *filename, mode_t mode);
int mknode(const char *filename, mode_t mode | S_IFIFO,(dev_t)0);
下面先來創建一個管道:
view plaincopy to clipboardprint? #include
#include
#include
#include
int main()
{
int res = mkfifo(“/tmp/my_fifo”, 0777);
if(res == 0)
{
printf(“FIFO createdn”);
}
exit(EXIT_SUCCESS);
}
#include
int main(){
int res = mkfifo(“/tmp/my_fifo”, 0777);
if(res == 0)
{
printf(“FIFO createdn”);
}
exit(EXIT_SUCCESS);}
編譯這個程序:
gcc –o fifo1.c fifo
運行這個程序:
$./fifo1
用ls命令查看所創建的管道
$ ls-lF /tmp/my_fifo
prwxr-xr-x 1 root root 0 05-08 20:10 /tmp/my_fifo|
注意:ls命令的輸出結果中的第一個字符為p,表示這是一個管道。最后的|符號是由ls命令的-F選項添加的,它也表示是這是一個管道。
雖然,我們所設置的文件創建模式為“0777”,但它被用戶掩碼(umask)設置(022)給改變了,這與普通文件創建是一樣的,所以文件的最終模式為755。
打開FIFO一個主要的限制是,程序不能是O_RDWR模式打開FIFO文件進行讀寫操作,這樣做的后果未明確定義。這個限制是有道理的,因為我們使用FIFO只是為了單身傳遞數據,所以沒有必要使用O_RDWR模式。如果一個管道以讀/寫方式打開FIFO,進程就會從這個管道讀回它自己的輸出。如果確實需要在程序之間雙向傳遞數據,最好使用一對FIFO,一個方向使用一個。
當一個Linux進程被阻塞時,它并不消耗CPU資源,這種進程的同步方式對CPU而言是非常有效率的。
有關Linux下命名管道FIFO的讀寫規則可以參見之前所寫的一篇文章:Linux命名管道FIFO的讀寫規則。
一、實驗:使用FIFO實現進程間通信
兩個獨立的程序:
1.生產者程序,它在需要時創建管道,然后盡可能快地向管道中寫入數據。
2.消費者程序,它從FIFO中讀取數據并丟棄它們。
生產者程序fifo2.c:
view plaincopy to clipboardprint? #include
#include
#include
#include
#include
#include
#include
#define FIFO_NAME “/tmp/Linux/my_fifo”
#define BUFFER_SIZE PIPE_BUF
#define TEN_MEG(1024 * 1024 * 10)
int main()
{
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes = 0;
char buffer[BUFFER_SIZE + 1];
if(access(FIFO_NAME, F_OK)==-1)
{
res = mkfifo(FIFO_NAME, 0777);
if(res!= 0)
{
fprintf(stderr, “Could not create fifo %sn”, FIFO_NAME);
exit(EXIT_FAILURE);
}
}
printf(“Process %d opening FIFO O_WRONLYn”, getpid());
pipe_fd = open(FIFO_NAME, open_mode);
printf(“Process %d result %dn”, getpid(), pipe_fd);
if(pipe_fd!=-1)
{
while(bytes < TEN_MEG)
{
res = write(pipe_fd, buffer, BUFFER_SIZE);
if(res ==-1)
{
fprintf(stderr, “Write error on pipen”);
exit(EXIT_FAILURE);
}
bytes += res;
}
close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf(“Process %d finishn”, getpid());
exit(EXIT_SUCCESS);
}
#include
#define FIFO_NAME “/tmp/Linux/my_fifo” #define BUFFER_SIZE PIPE_BUF #define TEN_MEG(1024 * 1024 * 10)
int main(){
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes = 0;
char buffer[BUFFER_SIZE + 1];
if(access(FIFO_NAME, F_OK)==-1)
{
res = mkfifo(FIFO_NAME, 0777);
if(res!= 0)
{
fprintf(stderr, “Could not create fifo %sn”, FIFO_NAME);
exit(EXIT_FAILURE);
}
}
printf(“Process %d opening FIFO O_WRONLYn”, getpid());
pipe_fd = open(FIFO_NAME, open_mode);
printf(“Process %d result %dn”, getpid(), pipe_fd);
if(pipe_fd!=-1)
{
while(bytes < TEN_MEG)
{
res = write(pipe_fd, buffer, BUFFER_SIZE);
if(res ==-1)
{
fprintf(stderr, “Write error on pipen”);
exit(EXIT_FAILURE);
}
bytes += res;
}
close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf(“Process %d finishn”, getpid());
exit(EXIT_SUCCESS);}
消費者程序fifo3.c:
view plaincopy to clipboardprint? #include
#include
#include
#include
#include
#include
#include
#define FIFO_NAME “/tmp/Linux/my_fifo”
#define BUFFER_SIZE PIPE_BUF
int main()
{
int pipe_fd;
int res;
int open_mode = O_RDONLY;
char buffer[BUFFER_SIZE + 1];
int bytes = 0;
memset(buffer, ' 主站蜘蛛池模板: 成人国产片视频在线观看| 18禁黄污无遮挡无码网站| …日韩人妻无码精品一专区| 强摸秘书人妻大乳BD| 亚洲国产欧美在线看片一国产| 亚洲日韩国产一区二区三区在线| 国产裸体歌舞一区二区| 色婷婷综合久色aⅴ五区最新| 性夜夜春夜夜爽aa片a| 日日碰狠狠躁久久躁96avv| 久久棈精品久久久久久噜噜| 国产玖玖玖九九精品视频靠爱| 国产精品无卡毛片视频| 玩弄丰满少妇xxxxx性多毛| 华人少妇被黑人粗大的猛烈进| 亚洲乱码中文字幕综合| 色五月丁香五月综合五月亚洲| 欧美一区内射最近更新| 国产在线视频一区二区三区98| 亚洲区综合区小说区激情区| 免费看成人aa片无码视频吃奶| 亚洲色欲色欲www在线看| 狠狠色综合久久久久尤物| 免费无码又爽又刺激毛片| 少妇的渴望hd高清在线播放| 国产情侣作爱视频免费观看| 国内精品久久人妻无码网站| 午夜无码区在线观看| 国产午夜人做人免费视频中文| 黄网站色成年片在线观看| 国产午夜无码视频在线观看| 亚洲日韩va在线视频| 国产亚洲精品久久777777| 亚洲欧美日韩国产制服另类| 婷婷色爱区综合五月激情| 亚洲国产精品人人做人人爱| 丰满熟妇乱又伦在线无码视频| 亚洲日产aⅴ中文字幕无码| 天天天欲色欲色www免费| 亚洲丰满熟女一区二区v| 精品亚洲国产成人蜜臀优播av|