本(běn)文(wén)为(wèi)明(míng)德揚原創及(jí)录(lù)用(yòng)文(wén)章(zhāng),轉(zhuǎn)载請注明(míng)出(chū)处!
案(àn)例編号(hào):000900000024
1.1 總(zǒng)體(tǐ)設計(jì)
1.1.1 概述
串行接口(kǒu)簡稱串口(kǒu),也(yě)稱串行通(tòng)訊接口(kǒu)或(huò)者(zhě)串行通(tòng)信(xìn)接口(kǒu),是(shì)采用(yòng)串行通(tòng)信(xìn)方(fāng)式的(de)擴展(zhǎn)接口(kǒu)。串行接口(kǒu)是(shì)指數據(jù)一(yī)位一(yī)位地(dì)順序傳送 ,其特(tè)點(diǎn)是(shì)通(tòng)信(xìn)線(xiàn)路(lù)簡單,只(zhī)要(yào)一(yī)对(duì)傳輸線(xiàn)就(jiù)可(kě)以(yǐ)实現(xiàn)双(shuāng)向(xiàng)通(tòng)信(xìn)(可(kě)以(yǐ)直(zhí)接利用(yòng)電(diàn)話(huà)線(xiàn)作为(wèi)傳輸線(xiàn)),從而(ér)大大降低了(le)成(chéng)本(běn),特(tè)别适合用(yòng)于(yú)遠(yuǎn)距離通(tòng)信(xìn),但傳送速度(dù)較慢(màn)。一(yī)条(tiáo)信(xìn)息的(de)各(gè)位數據(jù)被(bèi)逐位按順序傳送的(de)通(tòng)信(xìn)方(fāng)式稱作串行通(tòng)信(xìn)。串行通(tòng)信(xìn)的(de)特(tè)點(diǎn)是(shì):數據(jù)位的(de)傳送,按位順序進(jìn)行,最(zuì)少(shǎo)只(zhī)需要(yào)一(yī)根(gēn)傳輸線(xiàn)即可(kě)完成(chéng);成(chéng)本(běn)低,但傳送速度(dù)慢(màn)。串行通(tòng)信(xìn)的(de)距離可(kě)以(yǐ)從幾(jǐ)米(mǐ)到(dào)幾(jǐ)千(qiān)米(mǐ);根(gēn)據(jù)信(xìn)息的(de)傳送方(fāng)向(xiàng),串行通(tòng)信(xìn)可(kě)以(yǐ)進(jìn)一(yī)步分(fēn)为(wèi)單工、半双(shuāng)工和(hé)全(quán)双(shuāng)工三(sān)種(zhǒng)。
串口(kǒu)的(de)出(chū)現(xiàn)是(shì)在(zài) 1980 年(nián)前(qián)後(hòu),數據(jù)傳輸率是(shì) 115kbps~230kbps。串口(kǒu)出(chū)現(xiàn)的(de)初期(qī)是(shì)为(wèi)了(le)实現(xiàn)連(lián)接計(jì)算機(jī)外(wài)設的(de)目的(de),初期(qī)串口(kǒu)一(yī)般用(yòng)来(lái)連(lián)接鼠标(biāo)和(hé)外(wài)置 Modem 以(yǐ)及(jí)老(lǎo)式攝像头(tóu)和(hé)写字(zì)板等設備。
串口(kǒu)也(yě)可(kě)以(yǐ)應(yìng)用(yòng)于(yú)两(liǎng)台(tái)計(jì)算機(jī)(或(huò)設備)之間(jiān)的(de)互聯及(jí)數據(jù)傳輸。由(yóu)于(yú)串口(kǒu)不(bù)支持(chí)热(rè)插拔及(jí)傳輸速率較低,部(bù)分(fēn)新主(zhǔ)板和(hé)大部(bù)分(fēn)便攜電(diàn)腦已開(kāi)始取(qǔ)消該接口(kǒu)。串口(kǒu)多(duō)用(yòng)于(yú)工業控制和(hé)测量(liàng)設備以(yǐ)及(jí)部(bù)分(fēn)通(tòng)信(xìn)設備中(zhōng)。
1.1.2 設計(jì)目标(biāo)
本(běn)練習要(yào)求实現(xiàn)串口(kǒu)回(huí)环(huán)功能(néng),具體(tǐ)功能(néng)要(yào)求如(rú)下(xià):
1、 上(shàng)位機(jī)于(yú) FPGA 之間(jiān)通(tòng)过(guò)串口(kǒu)進(jìn)行通(tòng)信(xìn),規定(dìng)波(bō)特(tè)率为(wèi) 9600,數據(jù)位为(wèi) 8bit,无奇偶校(xiào)
验(yàn)位,停止位为(wèi) 1。
2、 FPGA 內(nèi)部(bù)有(yǒu)一(yī)个(gè)可(kě)保存 128 字(zì)节(jié)的(de) FIFO。
3、 FPGA 從上(shàng)位機(jī)接收(shōu)到(dào)數據(jù)後(hòu),将數據(jù)保存到(dào) FIFO 中(zhōng)。
4、 當 FIFO 保存的(de)數據(jù)超过(guò) 60 个(gè)數據(jù)时(shí),啟動(dòng)發(fà)送數據(jù)操作:读(dú)取(qǔ) FIFO 的(de)數據(jù),将數據(jù)返
回(huí)給(gěi)上(shàng)位機(jī)。
5、 在(zài)啟動(dòng)發(fà)送數據(jù)操作过(guò)程中(zhōng),如(rú)果(guǒ) FIFO 變(biàn)空,結束(shù)發(fà)送操作,等待下(xià)一(yī)次(cì)的(de)啟動(dòng)。
注意(yì):上(shàng)位機(jī)接收(shōu)到(dào)的(de)數據(jù)與(yǔ)發(fà)送的(de)數據(jù)相同(tóng),不(bù)能(néng)多(duō)也(yě)不(bù)能(néng)少(shǎo)。
1.1.3 系(xì)統結構框图(tú)
系(xì)統結構框图(tú)如(rú)下(xià)所(suǒ)示:
1.1.4 模块(kuài)功能(néng)
➢ 串口(kǒu)接收(shōu)模块(kuài)实現(xiàn)功能(néng)
1、 将輸入(rù)數據(jù)進(jìn)行同(tóng)步化(huà)处理。
2、 解(jiě)析串口(kǒu)时(shí)序,将有(yǒu)效數據(jù)進(jìn)行串并轉(zhuǎn)換。
➢ 數據(jù)处理模块(kuài)实現(xiàn)功能(néng)
1、 包(bāo)含一(yī)个(gè) FIFO,用(yòng)来(lái)存儲接收(shōu)到(dào)的(de)數據(jù)。
2、 滿足發(fà)送条(tiáo)件(jiàn)後(hòu),读(dú)出(chū) FIFO 的(de)數據(jù)送給(gěi)下(xià)遊模块(kuài)。
➢ 串口(kǒu)發(fà)送模块(kuài)实現(xiàn)功能(néng)
1、 将接收(shōu)到(dào)的(de)數據(jù)進(jìn)行并串轉(zhuǎn)換,發(fà)送給(gěi)上(shàng)位機(jī)。
1.1.5 頂层信(xìn)号(hào)
1.1.6 參考代(dài)碼
下(xià)面(miàn)是(shì)本(běn)工程的(de)頂层代(dài)碼:
1. module com_prj(
2. rst_n ,
3. clk ,
4. rx_uart,
5. tx_uart
6. );
7. parameter BPS = 5208;
8.
9. input rst_n ;
10. input clk ;
11. input rx_uart ;
12. output tx_uart ;
13.
14. wire [7:0] uart_in ;
15. wire uart_in_vld ;
16. wire [7:0] uart_out ;
17. wire uart_out_vld;
18. wire rdy ;
19.
20. uart_rx#(.BPS(BPS)) uart_rx(
21. .clk (clk ),
22. .rst_n (rst_n ),
23. .din (rx_uart ),
24. .dout (uart_in ),
25. .dout_vld(uart_in_vld)
26. );
27. uart_tx#(.BPS(BPS)) uart_tx(
28. .clk (clk ),
29. .rst_n (rst_n ),
30. .din (uart_out ),
31. .din_vld (uart_out_vld),
32. .rdy (rdy ),
33. .dout (tx_uart )
34. );
35. data_handle u_data_handle(
36. .clk (clk ),
37. .rst_n (rst_n ),
38. .din (uart_in ),
39. .din_vld (uart_in_vld ),
40. .dout (uart_out ),
41. .dout_vld(uart_out_vld),
42. .rdy (rdy )
43. );
44.
45. endmodule
1.2 串口(kǒu)接收(shōu)模块(kuài)設計(jì)
1.2.1 接口(kǒu)信(xìn)号(hào)
1.2.2 設計(jì)思(sī)路(lù)
➢ UART 异(yì)步串行口(kǒu)簡介
數據(jù)通(tòng)信(xìn)的(de)基本(běn)方(fāng)式可(kě)分(fēn)为(wèi)并行通(tòng)信(xìn)和(hé)串行通(tòng)信(xìn)两(liǎng)種(zhǒng):
并行通(tòng)信(xìn):
是(shì)指利用(yòng)多(duō)条(tiáo)數據(jù)線(xiàn)将一(yī)个(gè)資料的(de)各(gè)位同(tóng)时(shí)傳送。特(tè)點(diǎn)是(shì)傳輸速度(dù)快(kuài),适合用(yòng)于(yú)短(duǎn)距
離通(tòng)信(xìn),但要(yào)求通(tòng)信(xìn)速率較高(gāo)的(de)應(yìng)用(yòng)场合。
串行通(tòng)信(xìn):
是(shì)指利用(yòng)一(yī)条(tiáo)傳輸線(xiàn)将資料一(yī)位位的(de)順序傳送。特(tè)點(diǎn)是(shì)通(tòng)信(xìn)線(xiàn)路(lù)簡單,利用(yòng)簡單的(de)線(xiàn)
缆(lǎn)就(jiù)可(kě)以(yǐ)实現(xiàn)通(tòng)信(xìn),減低成(chéng)本(běn),适用(yòng)于(yú)遠(yuǎn)距離通(tòng)信(xìn),但傳輸速度(dù)慢(màn)的(de)應(yìng)用(yòng)场合。
在(zài) FPGA 看(kàn)来(lái),串口(kǒu)只(zhī)有(yǒu)两(liǎng)根(gēn)線(xiàn),一(yī)根(gēn)線(xiàn)用(yòng)于(yú)接收(shōu),一(yī)根(gēn)線(xiàn)用(yòng)于(yú)發(fà)送。
➢ UART 异(yì)步串行口(kǒu)的(de)傳輸格式
异(yì)步通(tòng)信(xìn)以(yǐ)一(yī)个(gè)字(zì)符为(wèi)傳輸單位,通(tòng)信(xìn)中(zhōng)两(liǎng)个(gè)字(zì)符間(jiān)的(de)时(shí)間(jiān)間(jiān)隔是(shì)不(bù)固定(dìng)的(de),然而(ér)在(zài)同(tóng)一(yī)个(gè)字(zì)符
中(zhōng)的(de)两(liǎng)个(gè)相鄰位代(dài)碼間(jiān)的(de)时(shí)間(jiān)間(jiān)隔是(shì)固定(dìng)的(de)。
通(tòng)信(xìn)協議(通(tòng)信(xìn)規程):是(shì)指通(tòng)信(xìn)双(shuāng)方(fāng)約定(dìng)的(de)一(yī)些規則。在(zài)使用(yòng)异(yì)步串行口(kǒu)傳送一(yī)个(gè)字(zì)符的(de)信(xìn)息
时(shí),对(duì)資料格式有(yǒu)如(rú)下(xià)規定(dìng):規定(dìng)有(yǒu)空閑位、起始位、數據(jù)位、奇偶校(xiào)验(yàn)位、停止位。通(tòng)訊时(shí)序图(tú)如(rú)
下(xià):
每一(yī)个(gè)數據(jù)位的(de)宽(kuān)度(dù)等于(yú)傳送波(bō)特(tè)率的(de)倒數。微機(jī)异(yì)步串行通(tòng)信(xìn)中(zhōng),常用(yòng)的(de)波(bō)特(tè)率为(wèi) 110,150,
300,600,1200,2400,4800,9600 ,19200,38400,115200 等。代(dài)表(biǎo)每个(gè)碼元(yuán)傳輸的(de)速
率。在(zài)二(èr)進(jìn)制數據(jù)傳輸中(zhōng),波(bō)特(tè)率和(hé)比特(tè)率相同(tóng)都是(shì)为(wèi)每个(gè)比特(tè)數據(jù)傳輸的(de)速率,其倒數为(wèi) 1bit
數據(jù)的(de)宽(kuān)度(dù),也(yě)就(jiù)是(shì) 1bit 數據(jù)持(chí)續的(de)时(shí)間(jiān)。确定(dìng)这(zhè)一(yī)时(shí)間(jiān),就(jiù)可(kě)用(yòng) FPGA 構造計(jì)數器实現(xiàn)比特(tè)
周期(qī)的(de)延时(shí),從而(ér)实現(xiàn)特(tè)定(dìng)波(bō)特(tè)率的(de)數據(jù)傳輸。
➢ 開(kāi)始前(qián),線(xiàn)路(lù)处于(yú)空閑狀态,送出(chū)連(lián)續"1"。傳送開(kāi)始时(shí)首先(xiān)發(fà)一(yī)个(gè)"0"作为(wèi)起始位,
然後(hòu)出(chū)現(xiàn)在(zài)通(tòng)信(xìn)線(xiàn)上(shàng)的(de)是(shì)字(zì)符的(de)二(èr)進(jìn)制編碼數據(jù)。
➢ 每个(gè)字(zì)符的(de)數據(jù)位长可(kě)以(yǐ)約定(dìng)为(wèi) 5 位、6 位、7 位或(huò) 8 位。
➢ 後(hòu)面(miàn)是(shì)奇偶校(xiào)验(yàn)位,顧名思(sī)義,檢验(yàn)位适用(yòng)于(yú)數據(jù)校(xiào)验(yàn)。分(fēn)为(wèi)奇校(xiào)验(yàn)和(hé)偶校(xiào)验(yàn)。奇校(xiào)验(yàn)需
要(yào)保證傳輸數據(jù)總(zǒng)共(gòng)有(yǒu)奇數个(gè)邏輯高(gāo)電(diàn)平,偶校(xiào)验(yàn)則需要(yào)保證傳輸數據(jù)有(yǒu)偶數个(gè)邏輯高(gāo)電(diàn)
平。即"奇偶"指的(de)是(shì)數據(jù)中(zhōng)(包(bāo)括該校(xiào)验(yàn)位)1 的(de)个(gè)數。例如(rú):傳輸的(de)數據(jù)是(shì) 01000011,
如(rú)果(guǒ)校(xiào)验(yàn)方(fāng)式是(shì)奇校(xiào)验(yàn),則校(xiào)验(yàn)位为(wèi) 0 ,若是(shì)偶校(xiào)验(yàn)則校(xiào)验(yàn)位是(shì) 1.傳輸中(zhōng)校(xiào)验(yàn)位不(bù)是(shì)必須
項,双(shuāng)方(fāng)可(kě)以(yǐ)約定(dìng)不(bù)要(yào)校(xiào)验(yàn)位,或(huò)者(zhě)使用(yòng)奇/偶校(xiào)验(yàn)方(fāng)式。
➢ 最(zuì)後(hòu)是(shì)表(biǎo)示停止位的(de)"1"信(xìn)号(hào),这(zhè)个(gè)停止位可(kě)以(yǐ)約定(dìng)持(chí)續 1 位、1.5 位或(huò) 2 位的(de)时(shí)間(jiān)宽(kuān)
度(dù)。由(yóu)于(yú)每台(tái)設備有(yǒu)其自(zì)己的(de)时(shí)鐘(zhōng),很可(kě)能(néng)再通(tòng)信(xìn)中(zhōng)两(liǎng)台(tái)設備間(jiān)出(chū)現(xiàn)小小的(de)不(bù)同(tóng)步。因(yīn)此(cǐ)
停止位不(bù)僅僅是(shì)表(biǎo)示傳輸的(de)結束(shù),并且提(tí)供一(yī)个(gè)校(xiào)正(zhèng)时(shí)鐘(zhōng)同(tóng)步的(de)機(jī)会(huì),讓從機(jī)可(kě)以(yǐ)正(zhèng)确的(de)
識别下(xià)一(yī)轮數據(jù)的(de)起始位。停止位的(de)位數越多(duō),不(bù)同(tóng)时(shí)鐘(zhōng)同(tóng)步的(de)容忍程度(dù)就(jiù)越大,但是(shì)數
據(jù)傳輸速率也(yě)越慢(màn)。
➢ 至(zhì)此(cǐ)一(yī)个(gè)字(zì)符傳送完畢,線(xiàn)路(lù)又進(jìn)入(rù)空閑,持(chí)續为(wèi)"1"。經(jīng)过(guò)一(yī)段(duàn)随機(jī)的(de)时(shí)間(jiān)後(hòu),下(xià)一(yī)个(gè)
字(zì)符開(kāi)始傳送才又發(fà)出(chū)起始位。
➢ 架構設計(jì)
上(shàng)位機(jī)發(fà)送的(de)數據(jù)会(huì)按照上(shàng)图(tú)所(suǒ)示串口(kǒu)的(de)时(shí)序图(tú)的(de)順序过(guò)来(lái),因(yīn)此(cǐ)我(wǒ)们(men)需要(yào)按照其对(duì)應(yìng)的(de)格式進(jìn)
行接收(shōu)。發(fà)送 8 位數據(jù) data 前(qián),串口(kǒu)接收(shōu)數據(jù)線(xiàn)会(huì)先(xiān)變(biàn) 0 并持(chí)續一(yī)段(duàn)时(shí)間(jiān)(起始位),然後(hòu)發(fà)送 da
ta[0]、data[1],以(yǐ)此(cǐ)類(lèi)推直(zhí)至(zhì)發(fà)送完 data[7],發(fà)送每位數據(jù)时(shí)都会(huì)持(chí)續一(yī)段(duàn)时(shí)間(jiān),發(fà)送完畢後(hòu)數據(jù)
線(xiàn)会(huì)變(biàn)为(wèi) 1 并持(chí)續一(yī)段(duàn)时(shí)間(jiān)(結束(shù)位)。至(zhì)此(cǐ),完成(chéng)數據(jù)的(de)發(fà)送。可(kě)以(yǐ)看(kàn)出(chū)每段(duàn)有(yǒu)效信(xìn)号(hào)的(de)開(kāi)始前(qián)和(hé)
結束(shù)後(hòu),都会(huì)有(yǒu)特(tè)殊信(xìn)号(hào):有(yǒu)效數據(jù)開(kāi)始前(qián)会(huì)有(yǒu)一(yī)段(duàn)變(biàn) 0 的(de)信(xìn)号(hào),用(yòng)以(yǐ)告知 FPGA 開(kāi)始傳送數據(jù);
結束(shù)後(hòu)会(huì)有(yǒu)一(yī)段(duàn)變(biàn) 1 的(de)信(xìn)号(hào),告知 FPGA 此(cǐ)數據(jù)傳送結束(shù)。
由(yóu)上(shàng)面(miàn)时(shí)序分(fēn)析可(kě)知,當我(wǒ)们(men)檢测到(dào)數據(jù)線(xiàn)從高(gāo)電(diàn)平(空閑位)變(biàn)为(wèi)低電(diàn)平(起始位)就(jiù)表(biǎo)示開(kāi)
始數據(jù)的(de)傳輸了(le),因(yīn)此(cǐ)需要(yào)進(jìn)行下(xià)降沿的(de)檢测,檢测方(fāng)法如(rú)下(xià):
該檢测方(fāng)法主(zhǔ)要(yào)利用(yòng) D 觸發(fà)器打(dǎ)拍来(lái)实現(xiàn)。
din:輸入(rù)串口(kǒu)數據(jù)。
din_ff0:輸入(rù)串口(kǒu)數據(jù)經(jīng)过(guò)一(yī)級緩存之後(hòu)的(de)信(xìn)号(hào),目的(de)是(shì)为(wèi)了(le)将异(yì)步信(xìn)号(hào)同(tóng)步化(huà)。
din_ff1:輸入(rù)串口(kǒu)數據(jù)經(jīng)过(guò)二(èr)級緩存之後(hòu)的(de)信(xìn)号(hào),目的(de)是(shì)为(wèi)了(le)減少(shǎo)亞稳态造成(chéng)的(de)影響。
din_ff2:輸入(rù)串口(kǒu)數據(jù)經(jīng)过(guò)三(sān)級緩存之後(hòu)的(de)信(xìn)号(hào),目的(de)是(shì)为(wèi)了(le)檢测信(xìn)号(hào)的(de)下(xià)降沿。
flag_add:接收(shōu)狀态指示信(xìn)号(hào),當在(zài)时(shí)鐘(zhōng)上(shàng)升(shēng)沿檢测到(dào) din_ff1 等于(yú) 0 并且 din_ff2 等于(yú) 1 的(de)时(shí)候
表(biǎo)示檢测到(dào)了(le)下(xià)降沿,此(cǐ)时(shí)将 flag_add 信(xìn)号(hào)拉高(gāo),表(biǎo)示進(jìn)入(rù)到(dào)接收(shōu)狀态。
根(gēn)據(jù)串口(kǒu)时(shí)序,可(kě)以(yǐ)提(tí)出(chū)两(liǎng)个(gè)計(jì)數器的(de)架構,如(rú)下(xià)图(tú)所(suǒ)示:
該架構由(yóu)两(liǎng)个(gè)計(jì)數器組成(chéng):时(shí)鐘(zhōng)計(jì)數器 cnt 和(hé)數據(jù)計(jì)數器 data_num。
时(shí)鐘(zhōng)計(jì)數器 cnt:用(yòng)于(yú)計(jì)數發(fà)送 1bit 數據(jù)所(suǒ)需要(yào)的(de)时(shí)間(jiān),加一(yī)条(tiáo)件(jiàn)为(wèi) flag_add,表(biǎo)示進(jìn)入(rù)接收(shōu)狀
态时(shí)就(jiù)開(kāi)始計(jì)數;結束(shù)条(tiáo)件(jiàn)为(wèi)數 5208 个(gè),開(kāi)發(fà)板晶振时(shí)鐘(zhōng)是(shì) 50M,对(duì)應(yìng)周期(qī)为(wèi) 20ns,每位數據(jù)的(de)
持(chí)續时(shí)間(jiān)为(wèi) 104166ns/20ns=5208.3 个(gè)时(shí)鐘(zhōng)周期(qī),近(jìn)似为(wèi) 5208 个(gè)时(shí)鐘(zhōng)周期(qī)。
數據(jù)計(jì)數器 data_num:用(yòng)于(yú)对(duì)接收(shōu)的(de)每一(yī)比特(tè)數據(jù)進(jìn)行計(jì)數,加一(yī)条(tiáo)件(jiàn)为(wèi) end_cnt,表(biǎo)示接收(shōu)
到(dào) 1bit 的(de)數據(jù)就(jiù)加一(yī);結束(shù)条(tiáo)件(jiàn)为(wèi)數 9 个(gè),一(yī)个(gè)起始位加上(shàng)八(bā)个(gè)數據(jù)位,共(gòng) 9 位,數完就(jiù)清(qīng)零(líng)。
➢ 注意(yì)事(shì)項
1、 串口(kǒu)接收(shōu)模块(kuài)中(zhōng)的(de)數據(jù)計(jì)數器一(yī)定(dìng)不(bù)要(yào)把停止位也(yě)數上(shàng)去(qù),否則在(zài)接受的(de)數據(jù)的(de)时(shí)
候会(huì)出(chū)錯。感(gǎn)興趣的(de)同(tóng)学可(kě)以(yǐ)使用(yòng) signaltap 抓取(qǔ)信(xìn)号(hào)進(jìn)行分(fēn)析(仿真(zhēn)沒(méi)有(yǒu)用(yòng))。
2、 由(yóu)于(yú)工程中(zhōng)串口(kǒu)的(de)每 1bit 數據(jù)傳輸所(suǒ)需要(yào)的(de)时(shí)間(jiān)是(shì)近(jìn)似值,也(yě)就(jiù)是(shì)存在(zài)誤差,因(yīn)此(cǐ)
串口(kǒu)接收(shōu)在(zài)采集數據(jù)的(de)时(shí)候,需要(yào)在(zài)數據(jù)的(de)中(zhōng)間(jiān)时(shí)刻進(jìn)行采樣(yàng),这(zhè)樣(yàng)才能(néng)保證數據(jù)
的(de)正(zhèng)确性(xìng)。
1.2.3 參考代(dài)碼
下(xià)面(miàn)是(shì)使用(yòng)明(míng)德揚的(de)計(jì)數器模板等写出(chū)来(lái)的(de)本(běn)模块(kuài)代(dài)碼。
1. always @ (posedge clk or negedge rst_n) begin
2. if(!rst_n) begin
3. din_ff0 <= 1'b1;
4. din_ff1 <= 1'b1;
5. din_ff2 <= 1'b1;
6. end
7. else begin
8. din_ff0 <= din;
9. din_ff1 <= din_ff0;
10. din_ff2 <= din_ff1;
11. end
12. end
13.
14. always @ (posedge clk or negedge rst_n)begin
15. if(!rst_n) begin
16. flag_add <= 1'b0;
17. end
18. else if(din_ff2 & ~din_ff1) begin
19. flag_add <= 1'b1;
20. end
21. else if(data_num==4'd8&&end_cnt) begin
22. flag_add <= 1'b0;
23. end
24. end
25.
26. always @ (posedge clk or negedge rst_n)begin
27. if(!rst_n)begin
28. cnt <= 0;
29. end
30. else if(add_cnt)begin
31. if(end_cnt)begin
32. cnt <= 0;
33. end
34. else begin
35. cnt <= cnt+1'b1;
36. end
37. end
38. else begin
39. cnt <= 0;
40. end
41. end
42. assign add_cnt = flag_add;
43. assign end_cnt = add_cnt && cnt == BPS-1;
44.
45.
46.
47. always @(posedge clk or negedge rst_n) begin
48. if (rst_n==0) begin
49. data_num <= 0;
50. end
51. else if(add_data_num) begin
52. if(end_data_num)
53. data_num <= 0;
54. else
55. data_num <= data_num+1 ;
56. end
57. end
58. assign add_data_num = end_cnt;
59. assign end_data_num = add_data_num && data_num == 9-1 ;
60.
61. always @ (posedge clk or negedge rst_n)begin
62. if(!rst_n) begin
63. dout <= 8'd0;
64. end
65. else if(add_cnt && cnt==BPS_P-1 && data_num!=0) begin
66. dout<={din,{dout[7:1]}};
67. end
68. else begin
69. dout<=dout;
70. end
71. end
72.
73. always @ (posedge clk or negedge rst_n)begin
74. if(!rst_n) begin
75. dout_vld <= 1'b0;
76. end
77. else if(add_data_num && data_num == 4'd8) begin
78. dout_vld <= 1'b1;
79. end
80. else begin
81. dout_vld <= 1'b0;
82. end
83. end
1.3 數據(jù)处理模块(kuài)設計(jì)
1.3.1 接口(kǒu)信(xìn)号(hào)
1.3.2 設計(jì)思(sī)路(lù)
➢ FIFO 原理簡介
FIFO(first input first output),即先(xiān)進(jìn)先(xiān)出(chū)的(de)數據(jù)緩存器,本(běn)質(zhì)上(shàng)還(huán)是(shì) RAM,與(yǔ)普通(tòng)存儲器的(de)區(qū)别:沒(méi)有(yǒu)外(wài)部(bù)读(dú)写地(dì)址線(xiàn),这(zhè)樣(yàng)使用(yòng)起来(lái)非(fēi)常簡單。特(tè)點(diǎn)就(jiù)是(shì)只(zhī)能(néng)順序写入(rù)數據(jù),順序读(dú)出(chū)數據(jù),其數據(jù)地(dì)址由(yóu)內(nèi)部(bù)读(dú)写指針(zhēn)自(zì)動(dòng)加一(yī)完成(chéng),不(bù)能(néng)像普通(tòng)存儲器那(nà)樣(yàng)可(kě)以(yǐ)由(yóu)地(dì)址線(xiàn)決定(dìng)读(dú)取(qǔ)或(huò)写入(rù)某个(gè)指定(dìng)的(de)地(dì)址。
FIFO 根(gēn)據(jù)读(dú)写时(shí)鐘(zhōng)的(de)區(qū)别,分(fēn)为(wèi)同(tóng)步 FIFO 和(hé)异(yì)步 FIFO。同(tóng)步 FIFO 读(dú)写共(gòng)用(yòng)一(yī)个(gè)相同(tóng)的(de)时(shí)鐘(zhōng);
异(yì)步 FIFO 读(dú)写可(kě)以(yǐ)使用(yòng)不(bù)同(tóng)的(de)时(shí)鐘(zhōng)。由(yóu)于(yú)异(yì)步 FIFO 內(nèi)部(bù)存在(zài)同(tóng)步化(huà)電(diàn)路(lù),因(yīn)此(cǐ)資源占用(yòng)要(yào)比同(tóng)步FIFO 大。
再 FPGA 中(zhōng),FIFO 的(de)使用(yòng)主(zhǔ)要(yào)有(yǒu)两(liǎng)種(zhǒng)场合,應(yìng)用(yòng)于(yú)緩存和(hé)跨时(shí)鐘(zhōng)域处理。FIFO 本(běn)身(shēn)就(jiù)是(shì)存儲器,自(zì)然可(kě)以(yǐ)用(yòng)作數據(jù)的(de)緩存,只(zhī)不(bù)过(guò)在(zài)選擇上(shàng)需要(yào)跟普通(tòng)的(de) RAM 區(qū)分(fēn)開(kāi)。又由(yóu)于(yú)异(yì)步 FIFO 的(de)存
在(zài),可(kě)以(yǐ)使得其写側和(hé)读(dú)側时(shí)鐘(zhōng)不(bù)同(tóng),因(yīn)此(cǐ)又可(kě)用(yòng)作跨时(shí)鐘(zhōng)域处理。
更(gèng)多(duō)關(guān)于(yú) FIFO 的(de)內(nèi)容,可(kě)以(yǐ)關(guān)注明(míng)德揚 FIFO 專題(tí)課,或(huò)者(zhě)是(shì)明(míng)德揚免費的(de) FIFO 課程
➢ 架構設計(jì)
按照功能(néng)要(yào)求,本(běn)模块(kuài)需要(yào)对(duì)接收(shōu)的(de)數據(jù)進(jìn)行存儲,當存够 60 个(gè)的(de)时(shí)候開(kāi)始發(fà)送,下(xià)面(miàn)是(shì)本(běn)模
块(kuài)的(de)架構图(tú)。
本(běn)模块(kuài)大致(zhì)分(fēn)为(wèi)三(sān)部(bù)分(fēn):FIFO 的(de)写控制電(diàn)路(lù)、FIFO、FIFO 的(de)读(dú)控制電(diàn)路(lù)。
写控制電(diàn)路(lù):只(zhī)要(yào)輸入(rù)數據(jù)有(yǒu)效,就(jiù)将數據(jù)写進(jìn) FIFO,主(zhǔ)要(yào)信(xìn)号(hào)为(wèi)写數據(jù) data 和(hé)写使能(néng) wrreq。
FIFO ip 核:存儲數據(jù)。
读(dú)控制電(diàn)路(lù):當 FIFO 內(nèi)部(bù)有(yǒu) 60 个(gè)數據(jù)、FIFO 非(fēi)空并且下(xià)遊模块(kuài)準備好(hǎo)接收(shōu)數據(jù)的(de)时(shí)候,就(jiù)開(kāi)
始读(dú)。主(zhǔ)要(yào)信(xìn)号(hào)为(wèi)輸出(chū)數據(jù) q、FIFO 有(yǒu)效數據(jù)量(liàng)指示信(xìn)号(hào) usedw、空指示信(xìn)号(hào) empty、读(dú)使能(néng) rdreq。
1.3.3 參考代(dài)碼
84. assign data = din ;
85. assign wrreq = din_vld ;
86.
87.
88. my_fifo u_my_fifo (
89. .clock(clk ),
90. .data (data ),
91. .rdreq(rdreq),
92. .wrreq(wrreq),
93. .empty(empty),
94. .q (q ),
95. .usedw(usedw)
96. );
97.
98.
99. always@(*)begin
100. if(rd_flag && empty==1'b0 && rdy)
101. rdreq = 1'b1;
102. else
103. rdreq = 1'b0;
104. end
105.
106. always@(posedge clk or negedge rst_n)begin
107. if(rst_n==1'b0)begin
108. rd_flag <= 1'b0;
109. end
110. else if(rd_flag==1'b0 && usedw>=60) begin
111. rd_flag <= 1'b1;
112. end
113. else if(rd_flag==1'b1 && empty)begin
114. rd_flag <= 1'b0;
115. end
116. end
117.
118. always @(posedge clk or negedge rst_n)begin
119. if(rst_n==1'b0)begin
120. dout <= 0;
121. end
122. else begin
123. dout <= q;
124. end
125. end
126.
127. always @(posedge clk or negedge rst_n)begin
128. if(rst_n==1'b0)begin
129. dout_vld <= 1'b0;
130. end
131. else begin
132. dout_vld <= rdreq;
133. End
134. end
1.4 串口(kǒu)發(fà)送模块(kuài)設計(jì)
1.4.1 接口(kǒu)信(xìn)号(hào)
1.4.2 設計(jì)思(sī)路(lù)
串口(kǒu)發(fà)送就(jiù)是(shì)要(yào)按照串口(kǒu)的(de)时(shí)序,对(duì)數據(jù)進(jìn)行并串轉(zhuǎn)換,在(zài)介紹架構之前(qián),先(xiān)来(lái)描述一(yī)下(xià)本(běn)模块(kuài)
一(yī)些重(zhòng)要(yào)的(de)信(xìn)号(hào)的(de)含義:
工作狀态指示信(xìn)号(hào) tx_flag:初始狀态为(wèi) 0,表(biǎo)示处于(yú)空閑狀态,當檢测到(dào)輸入(rù)數據(jù)有(yǒu)效的(de)时(shí)候,
該信(xìn)号(hào)變(biàn)为(wèi) 1,表(biǎo)示处于(yú)工作狀态,當數據(jù)發(fà)送完之後(hòu),重(zhòng)新拉低,進(jìn)入(rù)空閑狀态,等待下(xià)一(yī)个(gè)數據(jù)的(de)輸入(rù)。
數據(jù)鎖存信(xìn)号(hào) tx_data_tmp:位宽(kuān)为(wèi) 8bit,初始狀态为(wèi) 0,當模块(kuài)处于(yú)空閑狀态,并且輸入(rù)數據(jù)
有(yǒu)效的(de)时(shí)候,就(jiù)接收(shōu)輸入(rù)的(de)數據(jù)進(jìn)行鎖存。由(yóu)于(yú)輸入(rù)數據(jù)在(zài)串口(kǒu)發(fà)送的(de)时(shí)間(jiān)內(nèi)都需要(yào)用(yòng)到(dào),因(yīn)此(cǐ)为(wèi)了(le)防止數據(jù)發(fà)生(shēng)變(biàn)化(huà),導致(zhì)串口(kǒu)發(fà)送出(chū)現(xiàn)問(wèn)題(tí),所(suǒ)以(yǐ)引入(rù)此(cǐ)信(xìn)号(hào)進(jìn)行數據(jù)的(de)鎖存。
準備好(hǎo)接收(shōu)指示信(xìn)号(hào) rdy:當接收(shōu)到(dào)輸入(rù)數據(jù),或(huò)者(zhě)模块(kuài)处于(yú)發(fà)送狀态的(de)时(shí)候,此(cǐ)信(xìn)号(hào)为(wèi) 1,表(biǎo)
示不(bù)能(néng)接收(shōu)數據(jù),其他(tā)情(qíng)況为(wèi) 1,表(biǎo)示準備好(hǎo)接收(shōu)數據(jù)了(le)。由(yóu)于(yú)上(shàng)遊模块(kuài)數據(jù)輸出(chū)速率要(yào)比串口(kǒu)發(fà)送模块(kuài)發(fà)送的(de)速度(dù)快(kuài)得多(duō),所(suǒ)以(yǐ)需要(yào)此(cǐ)信(xìn)号(hào)来(lái)控制上(shàng)遊模块(kuài)的(de)輸出(chū),當串口(kǒu)發(fà)送模块(kuài)收(shōu)到(dào)有(yǒu)效數據(jù)的(de)时(shí)候,需要(yào)立刻把此(cǐ)信(xìn)号(hào)拉高(gāo),所(suǒ)以(yǐ)需要(yào)用(yòng)組合邏輯産生(shēng)。
我(wǒ)们(men)可(kě)以(yǐ)得到(dào)两(liǎng)个(gè)計(jì)數器組成(chéng)的(de)計(jì)數器架構,如(rú)下(xià)图(tú)所(suǒ)示:
該架構由(yóu)两(liǎng)个(gè)計(jì)數器組成(chéng):时(shí)鐘(zhōng)計(jì)數器 cnt 和(hé)數據(jù)計(jì)數器 data_num。
时(shí)鐘(zhōng)計(jì)數器 cnt:用(yòng)于(yú)計(jì)數發(fà)送 1bit 數據(jù)所(suǒ)需要(yào)的(de)时(shí)間(jiān),加一(yī)条(tiáo)件(jiàn)为(wèi) tx_flag,表(biǎo)示進(jìn)入(rù)工作狀态
时(shí)就(jiù)開(kāi)始計(jì)數;結束(shù)条(tiáo)件(jiàn)为(wèi)數 5208 个(gè),開(kāi)發(fà)板晶振时(shí)鐘(zhōng)是(shì) 50M,对(duì)應(yìng)周期(qī)为(wèi) 20ns,每位數據(jù)的(de)持(chí)
續时(shí)間(jiān)为(wèi) 104166ns/20ns=5208.3 个(gè)时(shí)鐘(zhōng)周期(qī),近(jìn)似为(wèi) 5208 个(gè)时(shí)鐘(zhōng)周期(qī)。
數據(jù)計(jì)數器 data_num:用(yòng)于(yú)对(duì)接收(shōu)的(de)每一(yī)比特(tè)數據(jù)進(jìn)行計(jì)數,加一(yī)条(tiáo)件(jiàn)为(wèi) end_cnt,表(biǎo)示發(fà)送
1bit 的(de)數據(jù)就(jiù)加一(yī);結束(shù)条(tiáo)件(jiàn)为(wèi)數 10 个(gè),一(yī)个(gè)起始位加上(shàng)八(bā)个(gè)數據(jù)位,再加上(shàng)一(yī)个(gè)結束(shù)位,共(gòng) 10 位,數完就(jiù)清(qīng)零(líng)。
1.4.3 參考代(dài)碼
使用(yòng)明(míng)德揚的(de)計(jì)數器等模板,可(kě)以(yǐ)很快(kuài)速很熟練地(dì)写出(chū)此(cǐ)模块(kuài)代(dài)碼。
1. always @(posedge clk or negedge rst_n)begin
2. if(rst_n==1'b0)begin
3. tx_flag <= 1'b0;
4. end
5. else if(tx_flag==1'b0 && din_vld) begin
6. tx_flag <= 1'b1;
7. end
8. else if(tx_flag && data_num==9 && cnt==BPS-1)begin
9. tx_flag <= 1'b0;
10. end
11. end
12.
13.
14. always @ (posedge clk or negedge rst_n)begin
15. if(!rst_n)begin
16. cnt <=0;
17. end
18. else if(tx_flag)begin
19. if(cnt==BPS-1)begin
20. cnt<=14'd0;
21. end
22. else begin
23. cnt <=cnt+1'b1;
24. end
25. end
26. else begin
27. cnt<=0;
28. end
29. end
30. assign add_cnt = tx_flag;
31. assign end_cnt = add_cnt && cnt==BPS-1;
32.
33.
34. always @ (posedge clk or negedge rst_n) begin
35. if(!rst_n) begin
36. tx_data_tmp <=8'd0;
37. end
38. else if(tx_flag==1'b0 && din_vld) begin
39. tx_data_tmp <= din;
40. end
41. end
42.
43.
44. always @(posedge clk or negedge rst_n) begin
45. if (rst_n==0) begin
46. data_num <= 0;
47. end
48. else if(add_data_num) begin
49. if(end_data_num)
50. data_num <= 0;
51. else
52. data_num <= data_num+1 ;
53. end
54. end
55. assign add_data_num = end_cnt;
56. assign end_data_num = add_data_num && data_num == 9-1 ;
57.
58.
59.
60. always @ (posedge clk or negedge rst_n) begin
61. if(!rst_n) begin
62. dout <= 1'b1;
63. end
64. else if(tx_flag)begin
65. if(data_num==0)begin
66. dout<=1'b0;
67. end
68. else if(data_num==9)begin
69. dout<=1'b1;
70. end
71. else begin
72. dout <= tx_data_tmp[data_num-1];
73. end
74. end
75. else begin
76. dout<=1'b1;
77. end
78. end
79.
80. always @(*)begin
81. if(din_vld || tx_flag)
82. rdy = 1'b0;
83. else
84. rdy = 1'b1;
85. end
1.5 效果(guǒ)和(hé)總(zǒng)結
➢ 下(xià)图(tú)是(shì)該工程的(de)現(xiàn)象(xiàng)
由(yóu)于(yú)該工程在(zài)不(bù)同(tóng)開(kāi)發(fà)板上(shàng)的(de)上(shàng)板效果(guǒ)是(shì)相同(tóng)的(de),所(suǒ)以(yǐ)就(jiù)統一(yī)展(zhǎn)示。下(xià)图(tú)为(wèi)串口(kǒu)調試助手(shǒu)的(de)界面(miàn),
下(xià)方(fāng)一(yī)欄中(zhōng)是(shì)要(yào)發(fà)送的(de)數據(jù):010203040506,共(gòng) 6 个(gè)字(zì)节(jié),點(diǎn)擊手(shǒu)動(dòng)發(fà)送 10 次(cì)之後(hòu),串口(kǒu)調試助手(shǒu)接收(shōu)到(dào)的(de)數據(jù)将在(zài)上(shàng)方(fāng)空白區(qū)域顯示。
由(yóu)于(yú)該項目的(de)上(shàng)板現(xiàn)象(xiàng)是(shì)動(dòng)态的(de),想(xiǎng)观看(kàn)完整現(xiàn)象(xiàng)的(de)朋友可(kě)以(yǐ)看(kàn)一(yī)下(xià)現(xiàn)象(xiàng)演示的(de)視頻。
視頻講解(jiě)教程和(hé)工程源代(dài)碼下(xià)载請移步明(míng)德揚論壇。
感(gǎn)興趣的(de)朋友也(yě)可(kě)以(yǐ)訪問(wèn)明(míng)德揚論壇(www.fpgabbs.cn)進(jìn)行 FPGA 相關(guān)工程設計(jì)学習,
也(yě)可(kě)以(yǐ)看(kàn)一(yī)下(xià)我(wǒ)们(men)往期(qī)的(de)文(wén)章(zhāng):
《基于(yú) FPGA 的(de)密碼鎖設計(jì)》
《波(bō)形相位頻率可(kě)調 DDS 信(xìn)号(hào)發(fà)生(shēng)器》
《基于(yú) FPGA 的(de)曼徹斯特(tè)編碼解(jiě)碼設計(jì)》
《基于(yú) FPGA 的(de)出(chū)租車計(jì)費系(xì)統》
《數電(diàn)基礎與(yǔ) Verilog 設計(jì)》
《基于(yú) FPGA 的(de)頻率、電(diàn)壓测量(liàng)》
《基于(yú) FPGA 的(de)漢明(míng)碼編碼解(jiě)碼設計(jì)》
《關(guān)于(yú)鎖存器問(wèn)題(tí)的(de)讨論》
《阻塞賦值與(yǔ)非(fēi)阻塞賦值》
《參數例化(huà)时(shí)自(zì)動(dòng)計(jì)算位宽(kuān)的(de)解(jiě)決辦(bàn)法》
明(míng)德揚是(shì)一(yī)家(jiā)專注于(yú) FPGA 領域的(de)專業性(xìng)公司,公司主(zhǔ)要(yào)業务包(bāo)括開(kāi)發(fà)板、教育培訓、項目承
接、人(rén)才服(fú)务等多(duō)个(gè)方(fāng)向(xiàng)。
點(diǎn)撥開(kāi)發(fà)板——学習 FPGA 的(de)入(rù)門(mén)之選。
MP801 開(kāi)發(fà)板——千(qiān)兆(zhào)网(wǎng)、ADDA、大容量(liàng) SDRAM 等,学習和(hé)項目需求一(yī)步到(dào)位。
网(wǎng)絡培訓班——不(bù)管(guǎn)时(shí)間(jiān)和(hé)空間(jiān),明(míng)德揚随时(shí)在(zài)你身(shēn)邊(biān),助你快(kuài)速学習 FPGA。
周末(mò)培訓班——明(míng)天(tiān)的(de)你会(huì)感(gǎn)激現(xiàn)在(zài)的(de)努力進(jìn)取(qǔ),升(shēng)職加薪明(míng)德揚来(lái)助你。
就(jiù)業培訓班——七(qī)大企業級項目实訓,獲得豐富的(de)項目經(jīng)验(yàn),高(gāo)薪就(jiù)業。
專題(tí)課程——高(gāo)手(shǒu)修煉課:提(tí)升(shēng)設計(jì)能(néng)力;实用(yòng)調試技巧課:提(tí)升(shēng)定(dìng)位和(hé)解(jiě)決問(wèn)題(tí)能(néng)力;FIFO 架構
設計(jì)課:助你快(kuài)速成(chéng)为(wèi)架構設計(jì)师(shī);时(shí)序約束(shù)、數字(zì)信(xìn)号(hào)处理、PCIE、綜合項目实踐課等你来(lái)選。
項目承接——承接企業 FPGA 研發(fà)項目。
人(rén)才服(fú)务——提(tí)供人(rén)才推薦、人(rén)才代(dài)培、人(rén)才派遣等服(fú)务。








