在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于FPGA的UART串口接收模塊設(shè)計(jì)

FPGA研究院 ? 來(lái)源:數(shù)字站 ? 2024-10-24 14:24 ? 次閱讀

01UART(異步串行接口

串行通信:指利用一條數(shù)據(jù)線(xiàn)將資料一位位的順序傳輸。

異步通信:以一個(gè)字符為傳輸單位,通信中兩個(gè)字符間的時(shí)間間隔是不固定的,然而在同一個(gè)字符的兩個(gè)相鄰位代碼間的時(shí)間間隔是固定的。

通信協(xié)議:指通信雙方約定的一些規(guī)則。在使用串口通信的時(shí)候,規(guī)定有:空閑位、起始位、數(shù)據(jù)位、奇偶校驗(yàn)位、停止位。

02串口通信時(shí)序

這個(gè)協(xié)議在 FPGA 內(nèi)部是除 SPI 之外最簡(jiǎn)單的接口吧,其實(shí)就是發(fā)送方與接收方相互認(rèn)定的協(xié)議(暗號(hào)),這種接口數(shù)據(jù)一般是單向傳輸,所以發(fā)送方和接收方通信一般需要兩根數(shù)據(jù)線(xiàn)。

wKgZoWcZ6E-AMgphAAFZtYDBo60836.jpg

圖1 URAT時(shí)序圖

數(shù)據(jù)線(xiàn)在沒(méi)有數(shù)據(jù)傳輸時(shí)保持高電平,當(dāng)需要傳輸數(shù)據(jù)時(shí),發(fā)送方把數(shù)據(jù)線(xiàn)拉低一段時(shí)間,告訴接收方開(kāi)始傳輸數(shù)據(jù)了。之后把數(shù)據(jù)從低位到高位或者高位到低位(這個(gè)根據(jù)通信雙方的要求確定)依次發(fā)送給對(duì)方(數(shù)據(jù)的位數(shù)雙方應(yīng)該事先確認(rèn)好,通常5~8位數(shù)據(jù))。數(shù)據(jù)發(fā)送完,可能會(huì)發(fā)送一位奇偶校驗(yàn)(這部分在下一節(jié)構(gòu)建完整UART協(xié)議時(shí)細(xì)說(shuō))。最后就是將數(shù)據(jù)線(xiàn)拉高一段時(shí)間表示數(shù)據(jù)傳輸結(jié)束。

在這之間就會(huì)有疑問(wèn),每位數(shù)據(jù)電平持續(xù)時(shí)間到底是多久?

這就引出波特率,通常就是說(shuō)每秒能傳輸多少位數(shù)據(jù),比如波特率為9600bit/s,就是指1秒傳輸9600位數(shù)據(jù)(當(dāng)然這是包含起始位,校驗(yàn)位,停止位在內(nèi)的,所以有效數(shù)據(jù)其實(shí)并沒(méi)有這么多)。當(dāng)使用該波特率時(shí),那每個(gè)電平持續(xù)時(shí)間不就是1/9600秒么。

03串口接收模塊設(shè)計(jì)

首先確定模塊接口信號(hào),肯定有個(gè)串口的輸入信號(hào)uart_rx吧,然后時(shí)鐘信號(hào)clk和復(fù)位信號(hào)rst_n也是不可能少的。接收到數(shù)據(jù)后肯定要輸出吧,所以在加一個(gè)uart_rx,注意該信號(hào)位寬應(yīng)該是可以改變的(因?yàn)榇趨f(xié)議的數(shù)據(jù)位可以改變)。一般還要有一個(gè)信號(hào)用于指示接收到的數(shù)據(jù)什么時(shí)候是有效的,便于后續(xù)模塊使用uart_rx,即uart_tx_vld(為高電平時(shí),表示uart_rx有效)。

信號(hào) I/O 位寬 含義
clk I 1 系統(tǒng)時(shí)鐘,50MHZ
rst_n I 1 系統(tǒng)復(fù)位,低電平有效
uart_rx I 1 UART接口輸入信號(hào)
rx_data O 8 數(shù)據(jù)輸出信號(hào)
rx_vld O 1 數(shù)據(jù)有效指示信號(hào),高電平有效

模塊總體思路:有了輸入輸出信號(hào)后,模塊內(nèi)部就是根據(jù)輸入信號(hào)生成輸出信號(hào)而已。通過(guò)觀察圖1時(shí)序知道,每位數(shù)據(jù)傳輸需要使用 1/波特率 的時(shí)間,每次需要傳輸?shù)?“數(shù)據(jù)” 包括起始位,數(shù)據(jù)位,校驗(yàn)位,結(jié)束位。那么以上是不是就對(duì)應(yīng)兩個(gè)計(jì)數(shù)器?所以使用計(jì)數(shù)器data_num來(lái)計(jì)數(shù)一位數(shù)據(jù)傳輸需要的時(shí)間(需要將1/波特率轉(zhuǎn)換為系統(tǒng)時(shí)鐘個(gè)數(shù)作為data_num的結(jié)束條件),使用計(jì)數(shù)器cnt來(lái)計(jì)數(shù)目前傳輸?shù)牡趲孜粩?shù)據(jù)了。整體思路就是如此,大致如下圖,接下來(lái)就是細(xì)節(jié):

wKgZoWcZ6H-AIe08AAAV6slb9Xk462.jpg

圖2 計(jì)數(shù)器架構(gòu)

計(jì)數(shù)器data_num該從什么時(shí)候計(jì)數(shù)?

當(dāng)發(fā)送方發(fā)送起始位時(shí)會(huì)把數(shù)據(jù)線(xiàn)拉低,并且在之后一段時(shí)間內(nèi)發(fā)送起始位,數(shù)據(jù)位等數(shù)據(jù),那么data_num在此期間都要計(jì)數(shù),直到停止位接收完成為止。由此引入一個(gè)標(biāo)志信號(hào)flag,該信號(hào)為高電平時(shí),計(jì)數(shù)器data_num就計(jì)數(shù),當(dāng)計(jì)數(shù)到時(shí)鐘頻率/波特率(1/波特率對(duì)應(yīng)的時(shí)鐘個(gè)數(shù))時(shí)清零。

故計(jì)數(shù)器data_num初始值為0,計(jì)數(shù)條件add_data_num = flag,結(jié)束條件為end_data_num = add_data_num && data_num == BSP_NUM - 1。

flag當(dāng)然就是檢測(cè)到數(shù)據(jù)線(xiàn)下降沿時(shí)拉高,當(dāng)計(jì)數(shù)器cnt計(jì)數(shù)結(jié)束時(shí)拉低,其余時(shí)間保持不變了。

故flag拉高條件:檢測(cè)到uart_rx下降沿,拉低條件為end_cnt。

接下來(lái)就是計(jì)數(shù)器cnt了,cnt表示數(shù)據(jù)線(xiàn)此時(shí)傳輸?shù)氖堑趲孜粩?shù)據(jù)了。當(dāng)計(jì)數(shù)器data_num計(jì)數(shù)結(jié)束時(shí),表示一位數(shù)據(jù)傳輸完成了,此時(shí)cnt就應(yīng)該加一了。當(dāng)計(jì)數(shù)器計(jì)數(shù)到 起始位數(shù)+數(shù)據(jù)位數(shù)+校驗(yàn)位數(shù)+停止位數(shù) 時(shí)表示數(shù)據(jù)傳輸完成了,此時(shí)cnt計(jì)數(shù)結(jié)束并清零,其余時(shí)間保持不變。

故計(jì)數(shù)器cnt初始值為0,計(jì)數(shù)條件add_cnt = end_data_num,計(jì)數(shù)器清零條件end_data_num = add_cnt && cnt == CNT_W - 1。CNT_W = 起始位數(shù)+數(shù)據(jù)位數(shù)+校驗(yàn)位數(shù)+停止位數(shù) 。

接下來(lái)就是接收數(shù)據(jù)并產(chǎn)生輸出信號(hào)了,一般會(huì)在計(jì)數(shù)器data_num計(jì)數(shù)的中部將數(shù)據(jù)線(xiàn)上的數(shù)據(jù)取下來(lái)進(jìn)行保存,此時(shí)的數(shù)據(jù)是比較穩(wěn)定的。由于最終需要輸出的只是數(shù)據(jù)位,本文不考慮校驗(yàn)位,傳輸?shù)?位是起始位,不需要保存。cnt==1時(shí)表示傳輸?shù)?位數(shù)據(jù),需要保存到輸出信號(hào)上的最低位(這是由于串口調(diào)試助手是先發(fā)的最低位,實(shí)際情況要看發(fā)送方先發(fā)高位還是低位)。

flag拉高后,計(jì)數(shù)器data_num進(jìn)行計(jì)數(shù),當(dāng)計(jì)數(shù)完一位數(shù)據(jù)后清零,并且cnt計(jì)數(shù)器進(jìn)行計(jì)數(shù),當(dāng)cnt大于等于1,小于等于8時(shí),表示此時(shí)接收的是數(shù)據(jù)位,將接收到的數(shù)據(jù)保存到rx_data對(duì)應(yīng)位(最好是在data_num為容量的一半時(shí)進(jìn)行保存),當(dāng)cnt計(jì)數(shù)器計(jì)數(shù)完成,表示一組數(shù)據(jù)接收完成,此時(shí)有效指示信號(hào)拉高,并且flag信號(hào)拉低,結(jié)束一組數(shù)據(jù)的接收;所以當(dāng)cnt=1 && data_num == BSP_CNT/2-1時(shí)(BSP_CNT表示波特率對(duì)應(yīng)的時(shí)鐘個(gè)數(shù)),有rx_data[0] <= uart_rx。

經(jīng)過(guò)對(duì)其它位的詳細(xì)分析,最終會(huì)得到這樣的結(jié)果:當(dāng)cnt >=1 && cnt <= DATA_W && data_num == BSP_CNT/2-1 && add_data_num 時(shí)(DATA_W表示每次發(fā)送的數(shù)據(jù)位位數(shù)),rx_data[cnt - 1] <= uart_rx;這樣就產(chǎn)生了輸出數(shù)據(jù)信號(hào)。

之后就是產(chǎn)生輸出有效指示信號(hào),該信號(hào)當(dāng)然是接收完數(shù)據(jù)時(shí)產(chǎn)生的,其實(shí)可以在計(jì)數(shù)器cnt計(jì)數(shù)結(jié)束時(shí)產(chǎn)生。但數(shù)據(jù)在接收完數(shù)據(jù)位后,其實(shí)數(shù)據(jù)就已經(jīng)接收完成了,此時(shí)就可以把輸出有效指示信號(hào)拉高了,這樣后續(xù)模塊就可以提前使用接收到的數(shù)據(jù)。所以當(dāng)cnt == DATA_W && add_data_num && data_num == BSP_NUM/2-1時(shí)將rx_data_vld拉高,其余時(shí)間拉低。

如果想要保證輸出數(shù)據(jù)線(xiàn)上數(shù)據(jù)比較干凈,不出現(xiàn)接收過(guò)程中的無(wú)效數(shù)據(jù),那么可以將rx_data和rx_data_vld在rx_data_vld有效時(shí)才進(jìn)行輸出,其余時(shí)間保持不變。

最后還要注意,數(shù)據(jù)線(xiàn)是其他芯片或者設(shè)備輸入的信號(hào),為了減小亞穩(wěn)態(tài)出現(xiàn)的機(jī)率,一般需要將數(shù)據(jù)線(xiàn)上的信號(hào)通過(guò)寄存器寄存兩個(gè)時(shí)鐘。由于還需要檢測(cè)數(shù)據(jù)線(xiàn)的下降沿,所以還要把該信號(hào)延遲一個(gè)時(shí)鐘,最終將接收到的信號(hào)uart_rx打三拍(前兩拍用于同步處理,最后一拍用于檢測(cè)輸入信號(hào)的下降沿),然后通過(guò)uart_rx_ff1和uart_rx_ff2檢測(cè)出下降沿,把標(biāo)志信號(hào)flag拉高。

整體時(shí)序圖如下:

wKgaoWcZ6H-ASdBnAAK3kb-VzDE307.jpg

圖3 整體時(shí)序

時(shí)序圖可能在手機(jī)上沒(méi)法看,所以將上圖各個(gè)部分截圖放在下面:

wKgaoWcZ6H-AJ-G8AADzajyaeCM470.jpg

圖4 準(zhǔn)備傳輸數(shù)據(jù)

當(dāng)計(jì)數(shù)器data_num=BSP_NUM/2-1的時(shí)候,將uart_rx_ff2的數(shù)據(jù)保存到rx_data的第cnt-1位,下圖為最低位,至于為什么是uart_rx_ff2,而不是uart_rx_ff1,通過(guò)下圖可知uart_rx_ff2與計(jì)數(shù)器data_num是對(duì)齊的,所以該信號(hào)會(huì)更準(zhǔn)。由于串口傳輸數(shù)據(jù)還是比較慢的,使用這兩個(gè)信號(hào)對(duì)結(jié)果基本沒(méi)有影響。

wKgZoWcZ6H-ALab3AAESgJq9Fgw625.jpg

圖5 接收最低位數(shù)據(jù)

接收完8位數(shù)據(jù),將輸出使能信號(hào)拉高,rx_data的x表示不確定,因?yàn)閳D4~圖6只能確定接收的最高位和最低位數(shù)據(jù),其余時(shí)序沒(méi)有畫(huà),中間的時(shí)序類(lèi)似,所以省略雙波浪線(xiàn)表示中間的數(shù)據(jù)傳輸省略。

最后接收完停止位后,end_cnt拉高表示接收一次數(shù)據(jù)傳輸完成,將兩個(gè)計(jì)數(shù)器清零,并且將標(biāo)志信號(hào)flag拉低。

wKgZoWcZ6H-AXV83AAFWswk34Tg217.jpg

圖6 接收完8位數(shù)據(jù)

上述將模塊內(nèi)部信號(hào)講完了,如果要實(shí)現(xiàn)功能完全夠了,但是在調(diào)用模塊時(shí),我們往往不習(xí)慣去改模塊內(nèi)部的參數(shù),這就需要通過(guò)parameter和localparam添加一些參數(shù),來(lái)自動(dòng)設(shè)置計(jì)數(shù)器位寬,計(jì)數(shù)器結(jié)束條件等等。其實(shí)人為需要設(shè)置的就是波特率、數(shù)據(jù)位位數(shù)、校驗(yàn)位數(shù)、停止位數(shù)(起始位是必須的,故不考慮設(shè)置參數(shù)),由于計(jì)算波特率對(duì)應(yīng)是時(shí)鐘個(gè)數(shù)時(shí)還需要知道系統(tǒng)時(shí)鐘頻率,所以增加一個(gè)系統(tǒng)時(shí)鐘頻率參數(shù)。

所以parameter就定義波特率BPS、時(shí)鐘頻率FCLK、數(shù)據(jù)位數(shù)DATA_W、校驗(yàn)位數(shù)CHECK_W 、停止位數(shù)STOP_W 。而localparam需要通過(guò)parameter定義的參數(shù)得到波特率對(duì)應(yīng)的 時(shí)鐘數(shù)BPS_CNT=時(shí)鐘頻率FCLK/波特率BPS ,計(jì)數(shù)器data_num需要計(jì)數(shù)到BPS_CNT,所以需要通過(guò)BPS_CNT計(jì)算出計(jì)數(shù)器data_num的位寬BPS_CNT_W,可以通過(guò)以下函數(shù)實(shí)現(xiàn)。

function integer clogb2(input integer depth);begin
    if(depth==0)
        clogb2 = 1;
    else if(depth!=0)
        for(clogb2=0;depth>0;clogb2=clogb2+1)
            depth=depth>>1;
    end
endfunction

接下來(lái)就是cnt計(jì)數(shù)器的結(jié)束條件了,可以由localparam定義CNT_NUM=DATA_W + CHECK_W + STOP_W。在利用上面函數(shù)計(jì)算出該計(jì)數(shù)器的位寬CNT_NUM_W就行了,內(nèi)部信號(hào)根據(jù)這些常量變化即可。

由此設(shè)計(jì)的模塊在例化時(shí),只需要修改parameter的幾個(gè)常量即可,不要對(duì)模塊內(nèi)部代碼做任何處理,這部分操作不會(huì)占用額外資源,在綜合工具對(duì)齊進(jìn)行綜合時(shí)就會(huì)處理,不會(huì)消耗FPGA的除法器之類(lèi)的資源。

根據(jù)以上分析,直接得到以下代碼,基本上不需要仿真調(diào)試。

04 參考代碼

//--###############################################################################################
//--# Designer : 發(fā)送一位數(shù)據(jù)所需系統(tǒng)時(shí)鐘數(shù)計(jì)算方式BPS_CNT = 1000_000_000/(Tclk*比特率),
//Tclk是系統(tǒng)時(shí)鐘周期,單位ns。
//--###############################################################################################
module uart_rx #(
    parameter       FCLK    =       50_000_000  ,//系統(tǒng)時(shí)鐘頻率,默認(rèn)50MHZ;
    parameter       BPS     =       9600        ,//串口波特率;
    parameter       DATA_W  =       8           ,//接收數(shù)據(jù)位數(shù)以及輸出數(shù)據(jù)位寬;
    parameter       CHECK_W =       0           ,//校驗(yàn)位,0代表無(wú)校驗(yàn)位;
    parameter       STOP_W  =       1            //1位停止位;
)(
    input                           clk         ,//系統(tǒng)工作時(shí)鐘50MHZ
    input                           rst_n       ,//系統(tǒng)復(fù)位信號(hào),低電平有效


    input                           uart_rx     ,//UART接口輸入信號(hào)
    output reg  [DATA_W-1:0]        rx_out      ,//數(shù)據(jù)輸出信號(hào)
    output reg                      rx_out_vld   //數(shù)據(jù)有效指示信號(hào)
    );
    
    localparam      BPS_CNT   =     FCLK/BPS;//波特率為9600bit/s,當(dāng)波特率為115200bit/s時(shí),DATA_115200==434;
    localparam      BPS_CNT_W =     clogb2(BPS_CNT-1);//根據(jù)BPS_CNT調(diào)用函數(shù)自動(dòng)計(jì)算計(jì)數(shù)器data_num位寬;
    localparam      CNT_NUM   =     DATA_W + CHECK_W + STOP_W;//計(jì)數(shù)器計(jì)數(shù)值;
    localparam      CNT_NUM_W =     clogb2(CNT_NUM);//根據(jù)計(jì)數(shù)器cnt的值,利用函數(shù)自動(dòng)計(jì)算此計(jì)數(shù)器的位寬;


    reg                             rx_vld          ;//表示接收完一組串口發(fā)來(lái)的數(shù)據(jù)了;
    reg                             uart_rx_ff0     ;
    reg                             uart_rx_ff1     ;
    reg                             uart_rx_ff2     ;
    reg                             flag            ;
    reg     [BPS_CNT_W-1:0]         data_num        ;
    reg     [CNT_NUM_W-1:0]         cnt             ;
    reg     [DATA_W-1:0]            rx_data         ;


    wire                            add_data_num    ;
    wire                            end_data_num    ;
    wire                            add_cnt         ;
    wire                            end_cnt         ;


    /******************注釋開(kāi)始******************
    自動(dòng)計(jì)算信號(hào)位寬;
     ******************注釋結(jié)束******************/
    function integer   clogb2(input integer depth);begin
        if(depth==0)
            clogb2 = 1;
        else if(depth!=0)
            for(clogb2=0;depth>0;clogb2=clogb2+1)
                depth=depth>>1;
        end
    endfunction


    /******************注釋開(kāi)始******************
    接收一位數(shù)據(jù)所用時(shí)間計(jì)數(shù)器data_num,初始值為0,當(dāng)接收到數(shù)據(jù)時(shí)進(jìn)行計(jì)數(shù),
    當(dāng)一位數(shù)據(jù)接收完成時(shí)清零;
    ******************注釋結(jié)束******************/
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            data_num <= {{BPS_CNT_W}{1'b0}};
        end
        else if(add_data_num)begin
            if(end_data_num)
                data_num <= {{BPS_CNT_W}{1'b0}};
            else
                data_num <= data_num + {{{BPS_CNT_W-1}{1'b0}},1'b1};
        end
    end


    assign add_data_num = flag;       
    assign end_data_num = add_data_num && data_num==BPS_CNT-1;


    //接受一組數(shù)據(jù)所用時(shí)間;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= {{CNT_NUM_W}{1'b0}};
        end
        else if(add_cnt)begin
            if(end_cnt)
                cnt <= {{CNT_NUM_W}{1'b0}};
            else
                cnt <= cnt + {{{CNT_NUM_W-1}{1'b0}},1'b1};
        end
    end


    assign add_cnt = end_data_num;       
    assign end_cnt = add_cnt && cnt== CNT_NUM-1;


    /******************注釋開(kāi)始******************
    PC端相對(duì)應(yīng)于FPGA為異步接口,為預(yù)防亞穩(wěn)態(tài)產(chǎn)生,對(duì)接收數(shù)據(jù)進(jìn)行打兩拍處理,由于需要采集信號(hào)下降沿,故打三拍處理;
    ******************注釋結(jié)束******************/
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin//三個(gè)寄存器組成移位寄存器,初始化為0;
            {uart_rx_ff2,uart_rx_ff1,uart_rx_ff0} <= 3'd0;
        end
        else begin//時(shí)鐘上升沿時(shí),將uart_rx信號(hào)移入移位寄存器,其余位左移一位;
            {uart_rx_ff2,uart_rx_ff1,uart_rx_ff0} <= {uart_rx_ff1,uart_rx_ff0,uart_rx};
        end
    end


    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            flag <= 1'b0;
        end
        else if(uart_rx_ff2==1 && uart_rx_ff1==0)begin//取UART_RX信號(hào)下降沿
            flag <= 1'b1;
        end
        else if(end_cnt)begin//一組數(shù)據(jù)接收完畢;
            flag <= 1'b0;
        end
    end


    //在中間時(shí)刻對(duì)輸入數(shù)據(jù)進(jìn)行采集,并且將數(shù)據(jù)存入rx_data;
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rx_data <= {{DATA_W}{1'b0}};
        end
        else if(cnt>=1 && cnt<=DATA_W && add_data_num && data_num==BPS_CNT/2-1)begin
            rx_data[cnt-1] <= uart_rx_ff2;
        end
    end


    //在接收完數(shù)據(jù)后,指示產(chǎn)生rx_data信號(hào)有效;
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rx_vld <= 1'b0;
        end
        else begin
            rx_vld <= (cnt==CNT_NUM-1 && add_data_num && data_num==BPS_CNT/2-1);
        end
    end


    //當(dāng)接收完一組數(shù)據(jù)后,將接收到的數(shù)據(jù)經(jīng)過(guò)一組觸發(fā)器暫存后輸出;
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin//
            rx_out <= 0;
        end
        else if(rx_vld)begin
            rx_out <= rx_data;
        end
    end


    //在接收完數(shù)據(jù)后,拉高一個(gè)時(shí)鐘,指示產(chǎn)生rx_out信號(hào)有效;
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rx_out_vld <= 1'b0;
        end
        else begin
            rx_out_vld <= rx_vld;
        end
    end


    endmodule
05 modelism仿真

仿真部分的代碼,通過(guò)一個(gè)任務(wù)task實(shí)現(xiàn)串口數(shù)據(jù)的發(fā)送,由于上述設(shè)計(jì)不支持校驗(yàn)位,所以這個(gè)模塊設(shè)置校驗(yàn)位也是沒(méi)有用的。

發(fā)送數(shù)據(jù)只需要調(diào)用tx();任務(wù)即可,內(nèi)部直接輸入待發(fā)送數(shù)據(jù),數(shù)據(jù)位寬依舊通過(guò)DATA_W設(shè)置,波特率BPS設(shè)置。

參考代碼:

`timescale 1 ns/1 ns
module uart_rx_test();
    parameter  CYCLE    = 20;//The unit is ns. The default value is 10ns;
    parameter  RST_TIME  = 10;//Reset time: Reset 3 clock widths by default;
    parameter  STOP_TIME  = 1000;//Time for simulation running after reset (unit: clock cycle). Simulation stops after 1000 clocks are run by default;


    // uart_rx Parameters
    parameter   FCLK        = 50_000_000;//系統(tǒng)時(shí)鐘頻率;
    parameter   BPS         = 9600      ;//串口波特率;
    parameter   BPS_CNT     = FCLK/BPS  ;//波特率對(duì)應(yīng)時(shí)鐘數(shù),不用手動(dòng)修改該參數(shù);
    parameter   DATA_W      = 8         ;//接收數(shù)據(jù)位數(shù)以及輸出數(shù)據(jù)位寬;
    parameter   CHECK_W     = 2'b01     ;//校驗(yàn)位,2'b00代表無(wú)校驗(yàn)位,2'b01表示奇校驗(yàn),2'b10表示偶校驗(yàn),2'b11無(wú)效。
    parameter   STOP_W      = 2'b11     ;//停止位,2'b01表示1位停止位,2'b10表示2位停止位,2'b11表示1.5位停止位;


    // uart_rx Inputs
    reg                     clk         ;
    reg                     rst_n       ;
    reg                     uart_tx     ;


    // uart_rx Outputs
    wire  [DATA_W-1:0]      rx_out      ;
    wire                    rx_out_vld  ;


    //例化串口接收模塊;
    uart_rx #(
        .FCLK       (FCLK       ),
        .BPS        (BPS        ),
        .DATA_W     (DATA_W     ),
        .CHECK_W    (CHECK_W    ),
        .STOP_W     (STOP_W     ))
    u_uart_rx (
        .clk        ( clk           ),
        .rst_n      ( rst_n         ),
        .uart_rx    ( uart_tx       ),
        .rx_out     ( rx_out        ),
        .rx_out_vld ( rx_out_vld    )
    );


    //The local clock is generated at 100 MB;
    initial begin
        clk = 0; 
        forever #(CYCLE/2) clk=~clk;
    end


    //Generate reset signal;
    initial begin
        rst_n = 1;
        #2; rst_n = 0;
        #(RST_TIME*CYCLE);//復(fù)位完成;
        rst_n = 1;
    end


    //Input signal din assignment method;
    initial begin
        #1;uart_tx = 1; //初始化時(shí)輸入高電平;
        #(100*CYCLE);   //Start assigning values;
        tx(8'ha5);      //以串口形式發(fā)送8'h5a;
        #(500*CYCLE);   //發(fā)送完成后延遲500個(gè)時(shí)鐘;
        tx(8'h5a);      //之后發(fā)送數(shù)據(jù)8'h59;
        #(500*CYCLE);   //發(fā)送完成后延遲500個(gè)時(shí)鐘;
        $stop;          //Stop simulation;
    end


    //模擬串口發(fā)送函數(shù),1位起始位,1位停止位,無(wú)校驗(yàn)位,8位數(shù)據(jù),先發(fā)低位;
    integer i;//用于控制循環(huán)次數(shù);
    task tx(
        input   [DATA_W-1:0]   data //串口待發(fā)送數(shù)據(jù);
    );
        begin
            @(posedge clk);//延遲一個(gè)時(shí)鐘后發(fā)送起始位;
            #1; uart_tx = 1'b0;
            repeat(BPS_CNT) @(posedge clk);//延遲BPS_CNT個(gè)時(shí)鐘;
            for(i=0 ; i<8 ; i=i+1)begin
                #1; uart_tx = data[i];
                repeat(BPS_CNT) @(posedge clk);//延遲BPS_CNT個(gè)時(shí)鐘;
            end
            if(CHECK_W == 2'b01)begin
                #1;uart_tx = ~(^data);//奇校驗(yàn)時(shí),發(fā)送數(shù)據(jù);
                repeat(BPS_CNT) @(posedge clk);//延遲BPS_CNT個(gè)時(shí)鐘;
            end
            else if(CHECK_W == 2'b10)begin
                #1;uart_tx = (^data);//偶校驗(yàn)時(shí),發(fā)送數(shù)據(jù);
                repeat(BPS_CNT) @(posedge clk);//延遲BPS_CNT個(gè)時(shí)鐘;
            end
            @(posedge clk);//延遲一個(gè)時(shí)鐘后發(fā)送停止位;
            #1; uart_tx = 1'b1;
            if(STOP_W == 2'b01)//1位停止位;
                repeat(BPS_CNT) @(posedge clk);//延遲BPS_CNT個(gè)時(shí)鐘;
            else if(STOP_W == 2'b10)//2位停止位;
                repeat(2*BPS_CNT) @(posedge clk);//延遲2*BPS_CNT個(gè)時(shí)鐘;
            else if(STOP_W == 2'b11)//1.5位停止位;
                repeat(BPS_CNT*3/2) @(posedge clk);//延遲1.5*BPS_CNT個(gè)時(shí)鐘;
        end
    endtask


endmodule

仿真運(yùn)行結(jié)果(rx_out先接收到8’ha5,后接收到8’h5a):

808ab682-904e-11ef-a511-92fbcf53809c.png

圖7仿真結(jié)果

查看細(xì)節(jié):開(kāi)始接收數(shù)據(jù)(起始位)片段:

80a10194-904e-11ef-a511-92fbcf53809c.png

圖8起始位仿真

接收最低位數(shù)據(jù)仿真如下:

80bd0362-904e-11ef-a511-92fbcf53809c.png

圖9接收第一位數(shù)據(jù)

接收最后一位數(shù)據(jù),并且產(chǎn)生輸出有效指示信號(hào),下一個(gè)時(shí)鐘將數(shù)據(jù)輸出,此時(shí)串口傳輸實(shí)際上并沒(méi)有完成,最后一位數(shù)據(jù)才傳輸一半(data_num計(jì)數(shù)器才2603==5208/2-1),但已經(jīng)接收到完整數(shù)據(jù),所以直接輸出,節(jié)省時(shí)間,但flag信號(hào)依舊位高電平,表示該模塊還處于工作狀態(tài)。

80e2ffb8-904e-11ef-a511-92fbcf53809c.png

圖10接收完最后一位數(shù)據(jù)

計(jì)數(shù)器data_num計(jì)數(shù)到5208-1并且計(jì)數(shù)器cnt計(jì)數(shù)器到8,表示一次傳輸完成,flag信號(hào)拉低,并且兩個(gè)計(jì)數(shù)器清零,表示完成傳輸,仿真如下:

81050b8a-904e-11ef-a511-92fbcf53809c.png

圖11接收完停止位

06 綜合測(cè)試

這個(gè)工程很久了,之前學(xué)的時(shí)候使用quartus綜合的,綜合效果如下所示:

811d8ab6-904e-11ef-a511-92fbcf53809c.png

圖12quartus綜合工程

對(duì)應(yīng)的RTL模塊視圖(由于時(shí)鐘頻率FCLK和波特率BPS參數(shù)設(shè)置會(huì)影響計(jì)數(shù)器cnt和data_num的位寬,所以不同數(shù)據(jù)匯總和出不同的電路,下圖為時(shí)鐘頻率50MHZ,波特率9600的RTL視圖):

8150f93c-904e-11ef-a511-92fbcf53809c.png

圖13RTL視圖

對(duì)系統(tǒng)時(shí)鐘頻率進(jìn)行約束后,最大時(shí)鐘頻率為120.86MHZ,遠(yuǎn)大于實(shí)際的50MHZ,滿(mǎn)足時(shí)序要求;

81672748-904e-11ef-a511-92fbcf53809c.png

圖14系統(tǒng)最大工作時(shí)鐘頻率

signal tap II 測(cè)試

將程序下載到FPGA,打開(kāi)串口調(diào)試助手,設(shè)置波特率9600,發(fā)送數(shù)據(jù)0XA5,使用signal tap II抓取數(shù)據(jù)8'hA5。

81845b9c-904e-11ef-a511-92fbcf53809c.png

圖15串口助手發(fā)送數(shù)據(jù)

串口調(diào)試助手發(fā)送數(shù)據(jù)0XB3,使用signal tap II抓取數(shù)據(jù)8'hB3。

81aa0f90-904e-11ef-a511-92fbcf53809c.png

圖16signal tap接收串口助手發(fā)送數(shù)據(jù)

串口調(diào)試助手發(fā)送數(shù)據(jù)0X5a,使用signal tap II抓取數(shù)據(jù)8'h5A。 81c6b03c-904e-11ef-a511-92fbcf53809c.png

圖17 調(diào)試

07總結(jié)

其實(shí)最主要的就是能夠根據(jù)協(xié)議找到合適的主架構(gòu),然后根據(jù)該架構(gòu)去產(chǎn)生輸出信號(hào)。

本文就利用兩個(gè)計(jì)數(shù)器作為主架構(gòu),根據(jù)計(jì)數(shù)器的狀態(tài)生成輸出信號(hào),切記我們需要的并不是計(jì)數(shù)器,而是計(jì)數(shù)器生成的輸出信號(hào),如果使用parameter要考慮模塊內(nèi)部各種會(huì)改變的數(shù)據(jù)與這些參數(shù)的關(guān)系。

最好不要留需要手動(dòng)修改的數(shù)據(jù),這種數(shù)據(jù)如果忘記修改,會(huì)對(duì)后續(xù)設(shè)計(jì)造成很大影響,浪費(fèi)調(diào)試時(shí)間。

來(lái)源:本文轉(zhuǎn)載自數(shù)字站公眾號(hào)

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1629

    文章

    21736

    瀏覽量

    603319
  • 接收模塊
    +關(guān)注

    關(guān)注

    1

    文章

    20

    瀏覽量

    10459
  • 串口
    +關(guān)注

    關(guān)注

    14

    文章

    1554

    瀏覽量

    76512
  • uart
    +關(guān)注

    關(guān)注

    22

    文章

    1235

    瀏覽量

    101387
  • 串行通信
    +關(guān)注

    關(guān)注

    4

    文章

    572

    瀏覽量

    35398

原文標(biāo)題:基于FPGA的UART串口接收模塊

文章出處:【微信號(hào):FPGA研究院,微信公眾號(hào):FPGA研究院】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    ZYNQ進(jìn)階:PL端實(shí)現(xiàn)串口UART接收設(shè)計(jì)

    uart接收模塊設(shè)計(jì)主要分為波特率控制計(jì)數(shù)邏輯和按位接收邏輯。
    的頭像 發(fā)表于 11-25 14:30 ?9174次閱讀
    ZYNQ進(jìn)階:PL端實(shí)現(xiàn)<b class='flag-5'>串口</b><b class='flag-5'>UART</b>的<b class='flag-5'>接收</b>設(shè)計(jì)

    什么是串口(UART)?串口的組成和FPGA實(shí)現(xiàn)

    串口作為常用的三大低速總線(xiàn)(UART、SPI、IIC)之一,在設(shè)計(jì)眾多通信接口和調(diào)試時(shí)占有重要地位。
    的頭像 發(fā)表于 01-03 11:43 ?1.5w次閱讀
    什么是<b class='flag-5'>串口</b>(<b class='flag-5'>UART</b>)?<b class='flag-5'>串口</b>的組成和<b class='flag-5'>FPGA</b>實(shí)現(xiàn)

    求助:fpga接收串口命令并解析 ,如何才能實(shí)現(xiàn)?

    我的FPGA需要實(shí)現(xiàn)如下功能:接收一個(gè)兩字節(jié)的命令,如:16'h8003,8位字節(jié)接收,然后解析,我的實(shí)現(xiàn)如下,1)一共三個(gè)模塊,頂層模塊
    發(fā)表于 11-21 16:17

    基于FPGA的串行接收模塊的設(shè)計(jì)

    為了使計(jì)算機(jī)能夠通過(guò)串口控制FPGA 的輸出信號(hào),筆者根據(jù)異步串行通信的原理,設(shè)計(jì)了簡(jiǎn)便易行的FPGA 串行通信接口系統(tǒng),并應(yīng)用VHDL 語(yǔ)言在FPGA 內(nèi)部集成了串行
    發(fā)表于 09-24 15:52 ?18次下載

    FPGA/CPLD設(shè)計(jì)UART

    UART 是廣泛使用的串行數(shù)據(jù)通訊電路。本設(shè)計(jì)包含UART 發(fā)送器、接收器和波特率發(fā)生器。設(shè)計(jì)應(yīng)用EDA 技術(shù),基于FPGA/CPLD 器件設(shè)計(jì)與實(shí)現(xiàn)
    發(fā)表于 09-29 08:01 ?24次下載

    基于EasyFPGA030的串口接收顯示設(shè)計(jì)

    本實(shí)驗(yàn)是基于EasyFPGA030 的串口接收設(shè)計(jì)。FPGA 除了需要控制外圍器件完成特定的功能外,在很多的應(yīng)用中還需要完成FPGA
    發(fā)表于 03-11 15:39 ?30次下載

    FPGA與CPLD實(shí)現(xiàn)UART

    UART 是廣泛使用的串行數(shù)據(jù)通訊電路。本設(shè)計(jì)包含UART 發(fā)送器、接收器和波特率發(fā)生器。設(shè)計(jì)應(yīng)用EDA 技術(shù),基于FPGA/CPLD 器件設(shè)計(jì)與實(shí)現(xiàn)
    發(fā)表于 12-17 00:15 ?59次下載
    <b class='flag-5'>FPGA</b>與CPLD實(shí)現(xiàn)<b class='flag-5'>UART</b>

    基于FPGA串口通信設(shè)計(jì)_王鵬

    介紹FPGA串口通信有發(fā)送模塊接收模塊的程序
    發(fā)表于 03-03 16:31 ?22次下載

    uart是什么意思?認(rèn)識(shí)uart串口

    都要通過(guò)串口來(lái)進(jìn)行配置。UART串口還是許多硬件數(shù)據(jù)輸出的主要接口,如GPS接收器就是通過(guò)UART串口
    發(fā)表于 12-06 14:51 ?11w次閱讀
    <b class='flag-5'>uart</b>是什么意思?認(rèn)識(shí)<b class='flag-5'>uart</b><b class='flag-5'>串口</b>

    UART串口WiFi模塊的工作原理及應(yīng)用

    隨著物聯(lián)網(wǎng)智能家居應(yīng)用的日漸豐富,越來(lái)越多的WiFi工程師開(kāi)始更多的關(guān)注UART串口WiFi模塊,為讓新手工程師更快的將UART串口WiFi
    的頭像 發(fā)表于 01-14 09:27 ?1.1w次閱讀
    <b class='flag-5'>UART</b><b class='flag-5'>串口</b>WiFi<b class='flag-5'>模塊</b>的工作原理及應(yīng)用

    UART串口WiFi模塊的工作原理及應(yīng)用

    隨著物聯(lián)網(wǎng)智能家居應(yīng)用的日漸豐富,越來(lái)越多的 WiFi 工程師開(kāi)始更多的關(guān)注 UART 串口 WiFi 模塊,為讓新手工程師更快的將 UART 串口
    發(fā)表于 01-08 08:00 ?23次下載
    <b class='flag-5'>UART</b><b class='flag-5'>串口</b>WiFi<b class='flag-5'>模塊</b>的工作原理及應(yīng)用

    FPGA為基礎(chǔ)的UART模塊的詳細(xì)設(shè)計(jì)方案

    UART的實(shí)現(xiàn)方法,具體描述了發(fā)送、接收模塊的設(shè)計(jì),恰當(dāng)使用了有限狀態(tài)機(jī),實(shí)現(xiàn)了FPGA上的UART的設(shè)計(jì),給出仿真結(jié)果。
    發(fā)表于 07-07 15:51 ?12次下載
    以<b class='flag-5'>FPGA</b>為基礎(chǔ)的<b class='flag-5'>UART</b><b class='flag-5'>模塊</b>的詳細(xì)設(shè)計(jì)方案

    使用FPGA模塊化設(shè)計(jì)方法實(shí)現(xiàn)UART的設(shè)計(jì)論文

    的實(shí)現(xiàn)方法,具體描述了發(fā)送、接收模塊的設(shè)計(jì),恰當(dāng)使用了有限狀態(tài)機(jī),實(shí)現(xiàn)了FPGA上的UART的設(shè)計(jì),給出仿真結(jié)果。
    發(fā)表于 07-07 17:28 ?10次下載
    使用<b class='flag-5'>FPGA</b>和<b class='flag-5'>模塊</b>化設(shè)計(jì)方法實(shí)現(xiàn)<b class='flag-5'>UART</b>的設(shè)計(jì)論文

    基于FPGAUART模塊設(shè)計(jì)與實(shí)現(xiàn)簡(jiǎn)介

    基于FPGAUART模塊設(shè)計(jì)與實(shí)現(xiàn)介紹說(shuō)明。
    發(fā)表于 06-01 09:43 ?20次下載

    UART串口通訊

    UART串口通訊總結(jié)前言串口的基本概念串口配置的基本屬性串口(Serial port)和RS-232串口
    發(fā)表于 12-20 19:31 ?24次下載
    <b class='flag-5'>UART</b><b class='flag-5'>串口</b>通訊
    主站蜘蛛池模板: 午夜视频网站在线观看| 波多野结衣一级特黄毛片| 天天草天天干天天| 欧美在线成人午夜影视| 国产自在自线午夜精品视频| 6一10周岁毛片免费| 欧美一级特黄aaaaaa在线看片| 中文字幕精品一区| 一级毛片真人免费播放视频| 欧美午夜寂寞影院安卓列表| 性视频久久| 妹子干综合网| 一级一片一a一片| 丁香六月综合网| 乱人伦的小说| 三级毛片在线免费观看| 久久综合一| 一级网站片| 一区二区三区亚洲| 欧美三页| 亚洲九九香蕉| 性欧美性| 亚洲美国avcom| 精品卡一卡二 卡四卡视频| 婷婷在线观看香蕉五月天| 性夜影院爽黄a爽在线看香蕉| 天堂资源wwww在线看| 精品四虎免费观看国产高清 | 鲁一鲁色一色| 免费看一级黄色录像| 亚洲高清成人| 色综合久久综合| 国产成年美女毛片80s| 狠狠干狠狠插| 一级做a爱过程免费视| 美女18黄| 2022天天干| 欧美激情91| 天天操天天操天天操香蕉| 99久热只有精品视频免费观看17| 年轻的护士3|