免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
【接口時(shí)序】3、UART串口收發(fā)的原理與Verilog實(shí)現(xiàn)

一、軟件平臺(tái)與硬件平臺(tái)

  軟件平臺(tái):

    1、操作系統(tǒng):Windows-8.1

    2、開發(fā)套件:ISE14.7

    3、仿真工具:ModelSim-10.4-SE

  硬件平臺(tái):

    1、FPGA型號(hào):XC6SLX45-2CSG324

    2、USB轉(zhuǎn)UART芯片:Silicon Labs CP2102GM

二、原理介紹

  串口是串行接口(serial port)的簡(jiǎn)稱,也稱為串行通信接口或COM接口。串口通信是指采用串行通信協(xié)議(serial communication)在一條信號(hào)線上將數(shù)據(jù)一個(gè)比特一個(gè)比特地逐位進(jìn)行傳輸?shù)耐ㄐ拍J健?串口按電氣標(biāo)準(zhǔn)及協(xié)議來劃分,包括RS-232、RS-422、RS485等。其中最常用的就是RS-232接口。

  RS-232接口有以下三個(gè)特性:

    1、用了一個(gè)9針的連接器"DB-9"(早期的電腦有用25針的連接器"DB-25")

    2、允許全雙工通信(即通過串口發(fā)送數(shù)據(jù)和接收數(shù)據(jù)可以同時(shí)進(jìn)行)

    3、通信的最大速率大約在10KBytes/s左右

  DB-9接口的實(shí)物圖如下圖所示(早期電腦主機(jī)后面可以看到這個(gè)接口,現(xiàn)在一般都用USB轉(zhuǎn)串口線進(jìn)行串口通信):

雖然DB-9接頭一共有9根線,但是實(shí)現(xiàn)串口通信只需要其中的3根線就可以了,分別是:

    1、pin-2:RXD(receive data),接收串行數(shù)據(jù)

    2、pin-3:RXD(transmit data),發(fā)送串行數(shù)據(jù)

    3、pin-5:GND(ground),地線

  在串口通信中,數(shù)據(jù)在1位寬的單條線路上進(jìn)行傳輸,一個(gè)字節(jié)的數(shù)據(jù)要分為8次,由低位到高位按順序一位一位的進(jìn)行傳送,這個(gè)過程稱為數(shù)據(jù)的"串行化(serialized)"過程。由于串口通信是一種異步通信協(xié)議,并沒有時(shí)鐘信號(hào)隨著數(shù)據(jù)一起傳輸,而且空閑狀態(tài)(沒有數(shù)據(jù)傳輸?shù)臓顟B(tài))的時(shí)候,串行傳輸線為高電平1,所以發(fā)送方發(fā)送一個(gè)字節(jié)數(shù)據(jù)之前會(huì)先發(fā)送一個(gè)低電平0,接收方收到這個(gè)低電平0以后就知道有數(shù)據(jù)要來了,準(zhǔn)備開始接收數(shù)據(jù)從而實(shí)現(xiàn)一次通信。串口通信的時(shí)序如下圖所示:

  串口通信的規(guī)范如下:

    1、空閑狀態(tài)(沒有數(shù)據(jù)傳輸?shù)臓顟B(tài))下,串行傳輸線上為高電平1

    2、發(fā)送方發(fā)送低電平0表示數(shù)據(jù)傳輸開始,這個(gè)低電平表示傳輸?shù)钠鹗嘉?/p>

    3、8-bit的數(shù)據(jù)位(1 Byte)是從最低位開始發(fā)送,最高位最后發(fā)送

    4、數(shù)據(jù)位的最高位發(fā)送完畢以后的下一位是奇偶校驗(yàn)位,這一位可以省略不要,同時(shí),當(dāng)不發(fā)送奇偶校驗(yàn)位的時(shí)候接收方也相應(yīng)的不接收校驗(yàn)位

    5、最后一位是停止位,用高電平1表示停止位

  下面以發(fā)送字節(jié)0x55為例來說明整個(gè)的發(fā)送過程:

    先把0x55轉(zhuǎn)化成二進(jìn)制為:01010101。顯然0x55的最低位bit 0是1,次低位bit 1是0,……..,最高位bit 7是0,由于串口是從最低位開始發(fā)送一個(gè)字節(jié),所以0x55各個(gè)位的發(fā)送順序是1-0-1-0-1-0-1-0,波形如下圖所示

下面在給出一個(gè)波形,根據(jù)上面的規(guī)則也可以很容易判斷這是發(fā)送字節(jié)0x13的波形

接下來的最后一個(gè)問題是:串口傳輸?shù)乃俣仁嵌嗌伲?/p>

  實(shí)際上,串口傳輸?shù)乃俣扔貌ㄌ芈?baudrate)來指定。波特率表示的是每秒發(fā)送的比特?cái)?shù),單位是bps(bits-per-seconds),例如,1000 bauds表示1秒鐘發(fā)送了1000個(gè)比特,或者說每個(gè)比特持續(xù)的時(shí)間是1ms。關(guān)于串口發(fā)送的波特率是有一組標(biāo)準(zhǔn)的規(guī)定的,并不是隨便一個(gè)數(shù)字。常用的波特率標(biāo)準(zhǔn)有:

    1、1200 bps

    2、9600 bps (常用)

    3、38400 bps

    4、115200 bps (常用,而且通常情況下是我們能用的最快的波特率)

  波特率為115200 bps時(shí),每個(gè)比特持續(xù)的時(shí)間為(1/115200)=8.7us,所以發(fā)送8個(gè)bit(1 Byte)需要的時(shí)間是8*8.7us=69us。在不考慮奇偶校驗(yàn)位的情況下,發(fā)送一個(gè)字節(jié)還需要發(fā)送額外的1個(gè)起始位和1個(gè)停止位,所以發(fā)送1個(gè)字節(jié)實(shí)際所需要的最少時(shí)間是10*8.7us=87us,這意味著1s(1000000us)中能發(fā)送的字節(jié)數(shù)為(1000000/87) = 11494,所以在波特率為115200bps的情況下,串口傳輸數(shù)據(jù)的速率約為11.5KB/s。而有些電腦的串口有時(shí)候需要一個(gè)更長(zhǎng)的停止位,比如1.5位或2位的停止位,那么發(fā)送一個(gè)字節(jié)所需要的時(shí)間比只有一個(gè)比特停止位的情況所耗費(fèi)的時(shí)間更長(zhǎng),在這種情況下,串口的傳輸速率會(huì)低于10.5KB/s。

  通過上面一系列的總結(jié)以后,可以得出FPGA與PC之間的串口通信主要包括三個(gè)模塊:波特率產(chǎn)生模塊、發(fā)射模塊和接收模塊。

三、目標(biāo)功能

  1、編寫發(fā)送模塊的verilog代碼,并往PC上連續(xù)不斷發(fā)送0x00~0xff這些數(shù)據(jù),PC上用串口調(diào)試助手進(jìn)行接收并以16進(jìn)制顯示出來

  2、在第一個(gè)功能的基礎(chǔ)上編寫接收模塊的verilog代碼,接收模塊接收到第一個(gè)功能中發(fā)送模塊發(fā)送的數(shù)據(jù)以后,用接收到的并行數(shù)據(jù)的低四位驅(qū)動(dòng)板上的四個(gè)LED燈

  3、編寫一個(gè)頂層模塊把發(fā)送模塊和接收模塊均例化進(jìn)去,然后從PC的串口調(diào)試助手上發(fā)送數(shù)據(jù)到FPGA,F(xiàn)PGA接收到數(shù)據(jù)以后把接收的數(shù)據(jù)返回給串口調(diào)試助手顯示

四、設(shè)計(jì)思路與Verilog代碼編寫

4.1、發(fā)送模塊波特率時(shí)鐘的設(shè)計(jì)與實(shí)現(xiàn)

  本節(jié)以波特率為115200bps為例來說明波特率模塊設(shè)計(jì)方法,其余波特率可以以此類推。由于我的開發(fā)板上的時(shí)鐘為50MHz,周期T=20ns,而波特率為115200bps,所以1個(gè)bit持續(xù)的時(shí)間是8.7us,那么每個(gè)bit占用的周期數(shù)N=(8.7us / 20ns) = 434,所以可以定義一個(gè)計(jì)數(shù)器,每當(dāng)計(jì)數(shù)器從0計(jì)數(shù)到433的時(shí)候就把計(jì)數(shù)器清零,然后在計(jì)數(shù)值為1(這個(gè)計(jì)數(shù)值最好比433的一半要小,這篇博客的最后一部分分析了原因)的情況下產(chǎn)生一個(gè)高脈沖。發(fā)射模塊只要檢測(cè)到這個(gè)高脈沖的到來就發(fā)送一個(gè)bit,這樣就實(shí)現(xiàn)了波特率為115200bps的串口數(shù)據(jù)發(fā)送。

  而接收模塊的波特率時(shí)鐘產(chǎn)生邏輯與發(fā)送的波特率時(shí)鐘相比稍有不同。不同之處在于當(dāng)接收模塊檢測(cè)到I_rs232_rxd的下降沿以后,表示有數(shù)據(jù)過來,準(zhǔn)備開始接收數(shù)據(jù)了,由于一個(gè)bit持續(xù)的時(shí)間為434個(gè)時(shí)鐘周期,所以為了保證接收模塊接收數(shù)據(jù)的準(zhǔn)確性,我們需要在434/2=217個(gè)周期,也就是數(shù)據(jù)的正中間位置的時(shí)候把輸入的數(shù)據(jù)接收并存起來。也就是說接收模塊的波特率時(shí)鐘要比發(fā)射模塊的波特率時(shí)鐘滯后數(shù)個(gè)周期

  波特率產(chǎn)生模塊的框圖如下圖所示

  其中:

  I_clk是系統(tǒng)時(shí)鐘;

  I_rst_n是系統(tǒng)復(fù)位;

  I_tx_bps_en是發(fā)射模塊波特率使能信號(hào),當(dāng)I_tx_bps_en為1時(shí)O_bps_tx_clk才有時(shí)鐘信號(hào)輸出;

  I_rx_bps_en是接收模塊波特率使能信號(hào),當(dāng)I_rx_bps_en為1時(shí)O_bps_rx_clk才有時(shí)鐘信號(hào)輸出。

  波特率模塊的完整代碼如下:

module baudrate_gen(    input   I_clk                  , // 系統(tǒng)50MHz時(shí)鐘    input   I_rst_n                , // 系統(tǒng)全局復(fù)位    input   I_bps_tx_clk_en        , // 串口發(fā)送模塊波特率時(shí)鐘使能信號(hào)    input   I_bps_rx_clk_en        , // 串口接收模塊波特率時(shí)鐘使能信號(hào)    output  O_bps_tx_clk           , // 發(fā)送模塊波特率產(chǎn)生時(shí)鐘    output  O_bps_rx_clk             // 接收模塊波特率產(chǎn)生時(shí)鐘);parameter       C_BPS9600         = 5207         ,    //波特率為9600bps                C_BPS19200        = 2603         ,    //波特率為19200bps                C_BPS38400        = 1301         ,    //波特率為38400bps                C_BPS57600        = 867          ,    //波特率為57600bps                C_BPS115200       = 433          ;    //波特率為115200bps                parameter       C_BPS_SELECT      = C_BPS115200  ;    //波特率選擇                reg [12:0]  R_bps_tx_cnt       ;reg [12:0]  R_bps_rx_cnt       ;///////////////////////////////////////////////////////////    // 功能:串口發(fā)送模塊的波特率時(shí)鐘產(chǎn)生邏輯///////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        R_bps_tx_cnt <= 13'd0 ;    else if(I_bps_tx_clk_en == 1'b1)        begin            if(R_bps_tx_cnt == C_BPS_SELECT)                R_bps_tx_cnt <= 13'd0 ;            else                R_bps_tx_cnt <= R_bps_tx_cnt + 1'b1 ;                         end        else        R_bps_tx_cnt <= 13'd0 ;        endassign O_bps_tx_clk = (R_bps_tx_cnt == 13'd1) ? 1'b1 : 1'b0 ;///////////////////////////////////////////////////////////    // 功能:串口接收模塊的波特率時(shí)鐘產(chǎn)生邏輯///////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        R_bps_rx_cnt <= 13'd0 ;    else if(I_bps_rx_clk_en == 1'b1)        begin            if(R_bps_rx_cnt == C_BPS_SELECT)                R_bps_rx_cnt <= 13'd0 ;            else                R_bps_rx_cnt <= R_bps_rx_cnt + 1'b1 ;                         end        else        R_bps_rx_cnt <= 13'd0 ;        endassign O_bps_rx_clk = (R_bps_rx_cnt == C_BPS_SELECT >> 1'b1) ? 1'b1 : 1'b0 ;endmodule

  波特率模塊的ModelSim仿真圖為

4.2、發(fā)送模塊的設(shè)計(jì)與實(shí)現(xiàn)

  有了波特率時(shí)鐘以后,就可以開始編寫發(fā)送模塊的內(nèi)部邏輯了。發(fā)送模塊的結(jié)構(gòu)框圖如下圖所示

       其中:

  I_clk是系統(tǒng)時(shí)鐘;

  I_rst_n是系統(tǒng)復(fù)位;

  I_tx_start是開始發(fā)送信號(hào),當(dāng)檢測(cè)到I_tx_start為高電平時(shí),立馬把輸入I_para_data[7:0]的數(shù)據(jù)串行化成單bit的發(fā)出去;

  I_bps_tx_clk是發(fā)送模塊波特率時(shí)鐘信號(hào),當(dāng)檢測(cè)到I_bps_tx_clk為高的時(shí)候就發(fā)送1個(gè)bit;

  I_para_data[7:0]是并行的8-bit數(shù)據(jù);

  O_rs232_txd是串行的bit數(shù)據(jù)流;

  O_bps_clk_en是發(fā)射波特率時(shí)鐘啟動(dòng)信號(hào),當(dāng)它為1是波特率產(chǎn)生模塊才能產(chǎn)生發(fā)射模塊的波特率時(shí)鐘;

  O_tx_done是發(fā)送1字節(jié)數(shù)據(jù)完成的標(biāo)志位,當(dāng)一個(gè)字節(jié)發(fā)送完畢以后,O_tx_done產(chǎn)生一個(gè)高脈沖。

  以發(fā)送字節(jié)0x55為例,發(fā)送模塊幾個(gè)關(guān)鍵信號(hào)的時(shí)序圖如下圖所示

  發(fā)送模塊的代碼如下:

module uart_txd(    input          I_clk           , // 系統(tǒng)50MHz時(shí)鐘    input          I_rst_n         , // 系統(tǒng)全局復(fù)位    input          I_tx_start      , // 發(fā)送使能信號(hào)    input          I_bps_tx_clk    , // 發(fā)送波特率時(shí)鐘    input   [7:0]  I_para_data     , // 要發(fā)送的并行數(shù)據(jù)    output  reg    O_rs232_txd     , // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連    output  reg    O_bps_tx_clk_en , // 波特率時(shí)鐘使能信號(hào)    output  reg    O_tx_done         // 發(fā)送完成的標(biāo)志);reg  [3:0]  R_state ;reg R_transmiting ; // 數(shù)據(jù)正在發(fā)送標(biāo)志/////////////////////////////////////////////////////////////////////////////// 產(chǎn)生發(fā)送 R_transmiting 標(biāo)志位/////////////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        R_transmiting <= 1'b0 ;    else if(O_tx_done)        R_transmiting <= 1'b0 ;    else if(I_tx_start)        R_transmiting <= 1'b1 ;          end/////////////////////////////////////////////////////////////////////////////// 發(fā)送數(shù)據(jù)狀態(tài)機(jī)/////////////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        begin            R_state      <= 4'd0 ;            O_rs232_txd  <= 1'b1 ;             O_tx_done    <= 1'b0 ;            O_bps_tx_clk_en <= 1'b0 ;  // 關(guān)掉波特率時(shí)鐘使能信號(hào)        end     else if(R_transmiting) // 檢測(cè)發(fā)送標(biāo)志被拉高,準(zhǔn)備發(fā)送數(shù)據(jù)        begin            O_bps_tx_clk_en <= 1'b1 ;  // 發(fā)送數(shù)據(jù)前的第一件事就是打開波特率時(shí)鐘使能信號(hào)            if(I_bps_tx_clk) // 在波特率時(shí)鐘的控制下把數(shù)據(jù)通過一個(gè)狀態(tài)機(jī)發(fā)送出去,并產(chǎn)生發(fā)送完成信號(hào)                begin                    case(R_state)                        4'd0  : // 發(fā)送起始位                            begin                                O_rs232_txd  <= 1'b0            ;                                O_tx_done    <= 1'b0            ;                                 R_state      <= R_state + 1'b1  ;                            end                        4'd1  : // 發(fā)送 I_para_data[0]                            begin                                O_rs232_txd  <= I_para_data[0]  ;                                O_tx_done    <= 1'b0            ;                                 R_state      <= R_state + 1'b1  ;                            end                         4'd2  : // 發(fā)送 I_para_data[1]                            begin                                O_rs232_txd  <= I_para_data[1]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                        4'd3  : // 發(fā)送 I_para_data[2]                            begin                                O_rs232_txd  <= I_para_data[2]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                        4'd4  : // 發(fā)送 I_para_data[3]                            begin                                O_rs232_txd  <= I_para_data[3]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                         4'd5  : // 發(fā)送 I_para_data[4]                            begin                                O_rs232_txd  <= I_para_data[4]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                        4'd6  : // 發(fā)送 I_para_data[5]                            begin                                O_rs232_txd  <= I_para_data[5]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                        4'd7  : // 發(fā)送 I_para_data[6]                            begin                                O_rs232_txd  <= I_para_data[6]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                        4'd8  : // 發(fā)送 I_para_data[7]                            begin                                O_rs232_txd  <= I_para_data[7]   ;                                O_tx_done    <= 1'b0             ;                                 R_state      <= R_state + 1'b1   ;                            end                         4'd9  : // 發(fā)送 停止位                            begin                                O_rs232_txd  <= 1'b1             ;                                O_tx_done    <= 1'b1             ;                                 R_state      <= 4'd0          ;                            end                        default :R_state      <= 4'd0            ;
          endcase 
        end
      end
    else
      begin
        O_bps_tx_clk_en    <= 1'b0 ; // 一幀數(shù)據(jù)發(fā)送完畢以后就關(guān)掉波特率時(shí)鐘使能信號(hào)
        R_state        <= 4'd0 ;
        O_tx_done      <= 1'b0 ;
        O_rs232_txd      <= 1'b1 ;
      end
end

endmodule

  其中當(dāng)檢測(cè)到輸入信號(hào)I_tx_start為高電平以后,發(fā)送模塊立即把R_transmiting信號(hào)拉高,表示開始要發(fā)送數(shù)據(jù)了,在R_transmiting為高電平的期間,打開波特率時(shí)鐘使能信號(hào)并且在波特率時(shí)鐘的控制下通過一個(gè)狀態(tài)機(jī)把并行數(shù)據(jù)發(fā)送出去,并產(chǎn)生發(fā)送完成信號(hào)O_tx_done,等O_tx_done為高以后再把R_transmiting拉低表示一次發(fā)送結(jié)束。

  為了實(shí)現(xiàn)功能1的效果還需要編寫一個(gè)頂層模塊把波特率模塊和發(fā)送模塊例化進(jìn)去并產(chǎn)生發(fā)送的信號(hào),頂層模塊的代碼如下:

module uart_tx_top(    input          I_clk           , // 系統(tǒng)50MHz時(shí)鐘    input          I_rst_n         , // 系統(tǒng)全局復(fù)位    output         O_rs232_txd       // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連);wire            W_bps_tx_clk             ;wire            W_bps_tx_clk_en          ;wire            W_tx_start               ;wire            W_tx_done                ;wire  [7:0]     W_para_data              ;        reg   [7:0]     R_data_reg               ;reg   [31:0]    R_cnt_1s                 ;reg             R_tx_start_reg           ;assign W_tx_start     =    R_tx_start_reg    ;assign W_para_data    =    R_data_reg        ;/////////////////////////////////////////////////////////////////////// 產(chǎn)生要發(fā)送的數(shù)據(jù)/////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin     if(!I_rst_n)        begin             R_cnt_1s         <= 31'd0     ;             R_data_reg       <= 8'd0      ;             R_tx_start_reg  <= 1'b0      ;        end     else if(R_cnt_1s == 31'd24_999_999)        begin             R_cnt_1s         <= 31'd0                 ;             R_data_reg       <= R_data_reg + 1'b1      ;             R_tx_start_reg <= 1'b1                 ;        end     else        begin          R_cnt_1s             <= R_cnt_1s + 1'b1     ;          R_tx_start_reg     <= 1'b0             ;        endenduart_txd U_uart_txd(    .I_clk               (I_clk                 ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n             (I_rst_n               ), // 系統(tǒng)全局復(fù)位    .I_tx_start          (W_tx_start            ), // 發(fā)送使能信號(hào)    .I_bps_tx_clk        (W_bps_tx_clk          ), // 波特率時(shí)鐘    .I_para_data         (W_para_data           ), // 要發(fā)送的并行數(shù)據(jù)    .O_rs232_txd         (O_rs232_txd           ), // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連    .O_bps_tx_clk_en     (W_bps_tx_clk_en       ), // 波特率時(shí)鐘使能信號(hào)    .O_tx_done           (W_tx_done             )  // 發(fā)送完成的標(biāo)志);baudrate_gen U_baudrate_gen(    .I_clk              (I_clk              ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n            (I_rst_n            ), // 系統(tǒng)全局復(fù)位    .I_bps_tx_clk_en    (W_bps_tx_clk_en    ), // 串口發(fā)送模塊波特率時(shí)鐘使能信號(hào)    .I_bps_rx_clk_en    (                   ), // 串口接收模塊波特率時(shí)鐘使能信號(hào)    .O_bps_tx_clk       (W_bps_tx_clk       ), // 發(fā)送模塊波特率產(chǎn)生時(shí)鐘    .O_bps_rx_clk       (                   )  // 接收模塊波特率產(chǎn)生時(shí)鐘);endmodule

  下載到板之前先用Modelsim仿一下看邏輯是否正確,仿之前把R_cnt_1s這個(gè)參數(shù)的上限值設(shè)置小一點(diǎn),比如5000,可以加快仿真速度,下圖是仿真時(shí)序圖,顯然完全滿足設(shè)計(jì)要求。

仿真結(jié)束以后就綁定管腳然后下載到FPGA中,接著打開電腦的串口調(diào)試助手,下圖是我的電腦上的顯示效果:

4.3、接收模塊的設(shè)計(jì)與實(shí)現(xiàn)

  波特率模塊和發(fā)送模塊都沒問題以后,就可以開始編寫接收模塊的代碼了。接收模塊的結(jié)構(gòu)框圖如下圖所示

  其中:

  I_clk是系統(tǒng)時(shí)鐘;

  I_rst_n是系統(tǒng)復(fù)位;

  I_rx_start是開始發(fā)送信號(hào),當(dāng)I_rx_start一直為高電平時(shí),接收模塊檢測(cè)到有數(shù)據(jù)就會(huì)接收;

  I_bps_rx_clk是接收模塊波特率時(shí)鐘信號(hào),當(dāng)檢測(cè)到I_bps_rx_clk為高的時(shí)候就接收1個(gè)bit;

  I_rs232_rx是串行的bit數(shù)據(jù)流;

  O_para_data[7:0]是并行的8-bit數(shù)據(jù);

  O_bps_rx_clk_en是發(fā)射波特率時(shí)鐘啟動(dòng)信號(hào),當(dāng)它為1是波特率產(chǎn)生模塊才能產(chǎn)生接收模塊的波特率時(shí)鐘;

  O_rx_done是接收1字節(jié)數(shù)據(jù)完成的標(biāo)志位,當(dāng)一個(gè)字節(jié)接收完畢以后,O_rx_done產(chǎn)生一個(gè)高脈沖。

  接收模塊與發(fā)射模塊的邏輯結(jié)構(gòu)非常類似,但是由于接收模塊需要判斷串行數(shù)據(jù)流的起始位,所以還要加一段檢測(cè)串行數(shù)據(jù)流下降沿的邏輯,檢測(cè)串行數(shù)據(jù)流下降沿的代碼如下:

////////////////////////////////////////////////////////////////////////////////// 功能:把 I_rs232_rxd 打的前兩拍,是為了消除亞穩(wěn)態(tài)//      把 I_rs232_rxd 打的后兩拍,是為了產(chǎn)生下降沿標(biāo)志位////////////////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        begin            R_rs232_rx_reg0 <= 1'b0 ;            R_rs232_rx_reg1 <= 1'b0 ;            R_rs232_rx_reg2 <= 1'b0 ;            R_rs232_rx_reg3 <= 1'b0 ;        end     else        begin              R_rs232_rx_reg0 <= I_rs232_rxd      ;            R_rs232_rx_reg1 <= R_rs232_rx_reg0  ;             R_rs232_rx_reg2 <= R_rs232_rx_reg1  ;             R_rs232_rx_reg3 <= R_rs232_rx_reg2  ;         end   end// 產(chǎn)生I_rs232_rxd信號(hào)的下降沿標(biāo)志位assign W_rs232_rxd_neg    =    (~R_rs232_rx_reg2) & R_rs232_rx_reg3 ;

  這段邏輯一共把I_rs232_rxd信號(hào)打了四拍,其中前兩排是為了消除I_rs232_rxd的亞穩(wěn)態(tài)(后面有時(shí)間專門討論亞穩(wěn)態(tài)問題),后兩排用來產(chǎn)生I_rs232_rxd信號(hào)下降沿的標(biāo)志位。

  這里以接收0x55這個(gè)字節(jié)為例來演示接收模塊的幾個(gè)重要信號(hào)的時(shí)序圖如下圖所示:

  接收模塊的完整代碼如下:

module uart_rxd(    input                       I_clk               , // 系統(tǒng)50MHz時(shí)鐘    input                       I_rst_n             , // 系統(tǒng)全局復(fù)位    input                       I_rx_start          , // 接收使能信號(hào)    input                       I_bps_rx_clk        , // 接收波特率時(shí)鐘    input                       I_rs232_rxd         , // 接收的串行數(shù)據(jù),在硬件上與串口相連      output    reg               O_bps_rx_clk_en     , // 波特率時(shí)鐘使能信號(hào)    output    reg               O_rx_done           , // 接收完成標(biāo)志    output    reg   [7:0]       O_para_data           // 接收到的8-bit并行數(shù)據(jù));reg         R_rs232_rx_reg0 ;reg         R_rs232_rx_reg1 ;reg         R_rs232_rx_reg2 ;reg         R_rs232_rx_reg3 ;reg         R_receiving     ;reg [3:0]   R_state         ;reg [7:0]   R_para_data_reg ;wire        W_rs232_rxd_neg ;////////////////////////////////////////////////////////////////////////////////// 功能:把 I_rs232_rxd 打的前兩拍,是為了消除亞穩(wěn)態(tài)//          把 I_rs232_rxd 打的后兩拍,是為了產(chǎn)生下降沿標(biāo)志位////////////////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        begin            R_rs232_rx_reg0 <= 1'b0 ;            R_rs232_rx_reg1 <= 1'b0 ;            R_rs232_rx_reg2 <= 1'b0 ;            R_rs232_rx_reg3 <= 1'b0 ;        end     else        begin              R_rs232_rx_reg0 <= I_rs232_rxd      ;            R_rs232_rx_reg1 <= R_rs232_rx_reg0  ;             R_rs232_rx_reg2 <= R_rs232_rx_reg1  ;             R_rs232_rx_reg3 <= R_rs232_rx_reg2  ;         end   end// 產(chǎn)生I_rs232_rxd信號(hào)的下降沿標(biāo)志位assign W_rs232_rxd_neg    =    (~R_rs232_rx_reg2) & R_rs232_rx_reg3 ;////////////////////////////////////////////////////////////////////////////////// 功能:產(chǎn)生發(fā)送信號(hào)R_receiving////////////////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        R_receiving <= 1'b0 ;    else if(O_rx_done)        R_receiving <= 1'b0 ;    else if(I_rx_start && W_rs232_rxd_neg)        R_receiving <= 1'b1 ;          end////////////////////////////////////////////////////////////////////////////////// 功能:用狀態(tài)機(jī)把串行的輸入數(shù)據(jù)接收,并轉(zhuǎn)化為并行數(shù)據(jù)輸出////////////////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        begin            O_rx_done       <= 1'b0 ;             R_state         <= 4'd0 ;            R_para_data_reg <= 8'd0 ;            O_bps_rx_clk_en <= 1'b0 ;        end     else if(R_receiving)        begin            O_bps_rx_clk_en <= 1'b1 ; // 打開波特率時(shí)鐘使能信號(hào)            if(I_bps_rx_clk)                begin                    case(R_state)                        4'd0  : // 接收起始位,但不保存                            begin                                R_para_data_reg     <= 8'd0             ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                        4'd1  : // 接收第0位,保存到R_para_data_reg[0]                            begin                                R_para_data_reg[0]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                        4'd2  : // 接收第1位,保存到R_para_data_reg[1]                            begin                                R_para_data_reg[1]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                        4'd3  : // 接收第2位,保存到R_para_data_reg[2]                            begin                                R_para_data_reg[2]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                         4'd4  : // 接收第3位,保存到R_para_data_reg[3]                            begin                                R_para_data_reg[3]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                         4'd5  : // 接收第4位,保存到R_para_data_reg[4]                            begin                                R_para_data_reg[4]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                        4'd6  : // 接收第5位,保存到R_para_data_reg[5]                            begin                                R_para_data_reg[5]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                        4'd7  :// 接收第6位,保存到R_para_data_reg[6]                            begin                                R_para_data_reg[6]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                        4'd8  : // 接收第7位,保存到R_para_data_reg[7]                            begin                                R_para_data_reg[7]  <= I_rs232_rxd      ;                                O_rx_done           <= 1'b0             ;                                 R_state             <= R_state + 1'b1   ;                            end                         4'd9  : // 接收停止位,但不保存,并把R_para_data_reg給輸出                            begin                                O_para_data         <= R_para_data_reg  ;                                O_rx_done           <= 1'b1             ;                                 R_state             <= 4'd0             ;                            end                                                     default:R_state <= 4'd0                         ;                                                                          endcase                 end        end    else        begin            O_rx_done           <= 1'b0 ;            R_state             <= 4'd0 ;            R_para_data_reg     <= 8'd0 ;            O_bps_rx_clk_en     <= 1'b0 ; // 接收完畢以后關(guān)閉波特率時(shí)鐘使能信號(hào)        end          endendmodule

  在下載到開發(fā)板測(cè)試之前,可以先用ModelSim軟件對(duì)模塊進(jìn)行一個(gè)功能仿真,方法是直接把接收模塊例化到上一小節(jié)測(cè)試發(fā)送模塊的例子中,例化的頂層代碼如下:

module uart_top(    input             I_clk           , // 系統(tǒng)50MHz時(shí)鐘    input             I_rst_n         , // 系統(tǒng)全局復(fù)位    output    [3:0]   O_led_out       ,    output            O_rs232_txd       // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連);wire            W_bps_tx_clk                 ;wire            W_bps_tx_clk_en              ;wire            W_bps_rx_clk                 ;wire            W_bps_rx_clk_en              ;wire            W_tx_start                   ;wire            W_tx_done                    ;wire            W_rx_done                    ;wire  [7:0]     W_para_data                  ;wire  [7:0]     W_rx_para_data               ;            reg   [7:0]     R_data_reg                   ;reg   [31:0]    R_cnt_1s                     ;reg             R_tx_start_reg               ;    assign W_tx_start     =    R_tx_start_reg      ;assign W_para_data    =    R_data_reg          ;assign O_led_out     =    W_rx_para_data[3:0] ;/////////////////////////////////////////////////////////////////////// 產(chǎn)生要發(fā)送的數(shù)據(jù)/////////////////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin     if(!I_rst_n)        begin             R_cnt_1s         <= 31'd0     ;             R_data_reg       <= 8'd0      ;             R_tx_start_reg   <= 1'b0      ;        end     else if(R_cnt_1s == 31'd5000)        begin             R_cnt_1s         <= 31'd0                 ;             R_data_reg       <= R_data_reg + 1'b1     ;             R_tx_start_reg   <= 1'b1                  ;        end     else        begin          R_cnt_1s           <= R_cnt_1s + 1'b1     ;          R_tx_start_reg     <= 1'b0                ;        endenduart_txd U_uart_txd(    .I_clk               (I_clk                 ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n             (I_rst_n               ), // 系統(tǒng)全局復(fù)位    .I_tx_start          (W_tx_start            ), // 發(fā)送使能信號(hào)    .I_bps_tx_clk        (W_bps_tx_clk          ), // 波特率時(shí)鐘    .I_para_data         (W_para_data           ), // 要發(fā)送的并行數(shù)據(jù)    .O_rs232_txd         (O_rs232_txd           ), // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連    .O_bps_tx_clk_en     (W_bps_tx_clk_en       ), // 波特率時(shí)鐘使能信號(hào)    .O_tx_done           (W_tx_done             )  // 發(fā)送完成的標(biāo)志);baudrate_gen U_baudrate_gen(    .I_clk              (I_clk              ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n            (I_rst_n            ), // 系統(tǒng)全局復(fù)位    .I_bps_tx_clk_en    (W_bps_tx_clk_en    ), // 串口發(fā)送模塊波特率時(shí)鐘使能信號(hào)    .I_bps_rx_clk_en    (W_bps_rx_clk_en    ), // 串口接收模塊波特率時(shí)鐘使能信號(hào)    .O_bps_tx_clk       (W_bps_tx_clk       ), // 發(fā)送模塊波特率產(chǎn)生時(shí)鐘    .O_bps_rx_clk       (W_bps_rx_clk       )  // 接收模塊波特率產(chǎn)生時(shí)鐘);uart_rxd U_uart_rxd(    .I_clk              (I_clk              ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n            (I_rst_n            ), // 系統(tǒng)全局復(fù)位    .I_rx_start         (1'b1               ), // 接收使能信號(hào)    .I_bps_rx_clk       (W_bps_rx_clk       ), // 接收波特率時(shí)鐘    .I_rs232_rxd        (O_rs232_txd        ), // 接收的串行數(shù)據(jù),在硬件上與串口相連      .O_bps_rx_clk_en    (W_bps_rx_clk_en    ), // 波特率時(shí)鐘使能信號(hào)    .O_rx_done          (W_rx_done          ), // 接收完成標(biāo)志    .O_para_data        (W_rx_para_data     )  // 接收到的8-bit并行數(shù)據(jù));endmodule

  仿真圖如下圖所示

 

  由圖可以看到接收數(shù)據(jù)與發(fā)送的數(shù)據(jù)完全一致,說明邏輯沒有問題,接下來就綁定管腳然后把代碼下載到FPGA看看效果,正常的效果是,PC的串口調(diào)試助手一直按順序顯示00~FF這些數(shù)據(jù),板上的LED燈的狀態(tài)與數(shù)據(jù)的低四位狀態(tài)相同。至此,功能二也全部實(shí)現(xiàn)完畢。

4.4、串口回顯功能的設(shè)計(jì)與實(shí)現(xiàn)

  有了發(fā)射模塊和接收模塊以后,功能三的要求就很簡(jiǎn)單了,直接寫一個(gè)頂層模塊,把串口的發(fā)送模塊與接收模塊例化進(jìn)去就可以了,唯一要做的就是把接收模塊的接收完成標(biāo)志位O_rx_done連接到發(fā)送模塊的I_tx_start上,把接收模塊的8-bit并行輸出總線O_para_data連接到發(fā)送模塊的8-bit并行輸入總線I_para_data上,下面直接給出頂層的代碼:

module uart_top(    input            I_clk           , // 系統(tǒng)50MHz時(shí)鐘    input            I_rst_n         , // 系統(tǒng)全局復(fù)位    input            I_rs232_rxd     , // 接收的串行數(shù)據(jù),在硬件上與串口相連    output           O_rs232_txd     , // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連    output    [3:0]  O_led_out       );wire            W_bps_tx_clk                 ;wire            W_bps_tx_clk_en              ;wire            W_bps_rx_clk                 ;wire            W_bps_rx_clk_en              ;wire            W_rx_done                    ;wire            W_tx_done                    ;wire  [7:0]     W_para_data                  ;assign    O_led_out = W_para_data[3:0]       ;baudrate_gen U_baudrate_gen(    .I_clk              (I_clk              ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n            (I_rst_n            ), // 系統(tǒng)全局復(fù)位    .I_bps_tx_clk_en    (W_bps_tx_clk_en    ), // 串口發(fā)送模塊波特率時(shí)鐘使能信號(hào)    .I_bps_rx_clk_en    (W_bps_rx_clk_en    ), // 串口接收模塊波特率時(shí)鐘使能信號(hào)    .O_bps_tx_clk       (W_bps_tx_clk       ), // 發(fā)送模塊波特率產(chǎn)生時(shí)鐘    .O_bps_rx_clk       (W_bps_rx_clk       )  // 接收模塊波特率產(chǎn)生時(shí)鐘);uart_txd U_uart_txd(    .I_clk               (I_clk                 ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n             (I_rst_n               ), // 系統(tǒng)全局復(fù)位    .I_tx_start          (W_rx_done             ), // 發(fā)送使能信號(hào)    .I_bps_tx_clk        (W_bps_tx_clk          ), // 波特率時(shí)鐘    .I_para_data         (W_para_data           ), // 要發(fā)送的并行數(shù)據(jù)    .O_rs232_txd         (O_rs232_txd           ), // 發(fā)送的串行數(shù)據(jù),在硬件上與串口相連    .O_bps_tx_clk_en     (W_bps_tx_clk_en       ), // 波特率時(shí)鐘使能信號(hào)    .O_tx_done           (W_tx_done             )  // 發(fā)送完成的標(biāo)志);uart_rxd U_uart_rxd(    .I_clk              (I_clk                ), // 系統(tǒng)50MHz時(shí)鐘    .I_rst_n            (I_rst_n              ), // 系統(tǒng)全局復(fù)位    .I_rx_start         (1'b1                 ), // 接收使能信號(hào)    .I_bps_rx_clk       (W_bps_rx_clk         ), // 接收波特率時(shí)鐘    .I_rs232_rxd        (I_rs232_rxd          ), // 接收的串行數(shù)據(jù),在硬件上與串口相連      .O_bps_rx_clk_en    (W_bps_rx_clk_en      ), // 波特率時(shí)鐘使能信號(hào)    .O_rx_done          (W_rx_done            ), // 接收完成標(biāo)志    .O_para_data        (W_para_data          )  // 接收到的8-bit并行數(shù)據(jù));endmodule

  建立工程并綁定管腳以后下載到開發(fā)板中,利用串口調(diào)試助手的自動(dòng)發(fā)送(自動(dòng)發(fā)送的周期最好在200ms以上)功能我對(duì)波特率為9600bps和115200bps分別進(jìn)行了測(cè)試,在9600bps的情況下我一共發(fā)送了1002512個(gè)字節(jié),全部接受正確,115200bps波特率情況下一共發(fā)送了512325字節(jié),也全部接受正確,邏輯基本穩(wěn)定,歡迎大家繼續(xù)測(cè)。我第一次寫串口代碼的時(shí)候出現(xiàn)過在115200bps的情況下發(fā)送字節(jié)達(dá)到10萬(wàn)以上的時(shí)候出現(xiàn)誤碼的情況,原因下一小節(jié)再說,上面的代碼已經(jīng)把這個(gè)問題修復(fù)了,原因就出在波特率模塊上。至此,功能三已全部完成。

五、進(jìn)一步思考

5.1、波特率模塊產(chǎn)生的O_bps_tx_clk滯后O_bps_rx_clk可能出現(xiàn)的問題

  我最開始寫的波特率模塊如下:

module baudrate_gen(    input   I_clk                  , // 系統(tǒng)50MHz時(shí)鐘    input   I_rst_n                , // 系統(tǒng)全局復(fù)位    input   I_bps_tx_clk_en        , // 串口發(fā)送模塊波特率時(shí)鐘使能信號(hào)    input   I_bps_rx_clk_en        , // 串口接收模塊波特率時(shí)鐘使能信號(hào)    output  O_bps_tx_clk           , // 發(fā)送模塊波特率產(chǎn)生時(shí)鐘    output  O_bps_rx_clk           // 接收模塊波特率產(chǎn)生時(shí)鐘);parameter         C_BPS9600         = 5207         ,    //波特率為9600bps                  C_BPS19200        = 2603         ,    //波特率為19200bps                  C_BPS38400        = 1301         ,    //波特率為38400bps                  C_BPS57600        = 867          ,    //波特率為57600bps                  C_BPS115200       = 433          ;    //波特率為115200bps                parameter         C_BPS_SELECT      = C_BPS115200  ; //波特率選擇                reg [12:0]  R_bps_tx_cnt       ;reg         R_bps_tx_clk_reg   ;reg [12:0]  R_bps_rx_cnt       ;///////////////////////////////////////////////////////////    // 功能:串口發(fā)送模塊的波特率時(shí)鐘產(chǎn)生邏輯///////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        begin            R_bps_tx_cnt       <= 13'd0 ;            R_bps_tx_clk_reg   <= 1'b0  ;        end     else if(I_bps_tx_clk_en == 1'b1)        begin            if(R_bps_tx_cnt == C_BPS_SELECT)                begin                    R_bps_tx_cnt       <= 13'd0 ;                    R_bps_tx_clk_reg   <= 1'b1  ;                end                               else                begin                    R_bps_tx_cnt       <= R_bps_tx_cnt + 1'b1 ;                    R_bps_tx_clk_reg   <= 1'b0                ;                 end            end       else        begin            R_bps_tx_cnt       <= 13'd0 ;            R_bps_tx_clk_reg   <= 1'b0  ;         end             endassign O_bps_tx_clk = R_bps_tx_clk_reg ;///////////////////////////////////////////////////////////    // 功能:串口接收模塊的波特率時(shí)鐘產(chǎn)生邏輯///////////////////////////////////////////////////////////always @(posedge I_clk or negedge I_rst_n)begin    if(!I_rst_n)        R_bps_rx_cnt <= 13'd0 ;    else if(I_bps_rx_clk_en == 1'b1)        begin            if(R_bps_rx_cnt == C_BPS_SELECT)                R_bps_rx_cnt <= 13'd0 ;            else                R_bps_rx_cnt <= R_bps_rx_cnt + 1'b1 ;                         end        else        R_bps_rx_cnt <= 13'd0 ;        endassign O_bps_rx_clk = (R_bps_rx_cnt == C_BPS_SELECT >> 1'b1) ? 1'b1 : 1'b0 ;endmodule

  其仿真如下所示:

  當(dāng)發(fā)送波特率時(shí)鐘使能信號(hào)打開以后,計(jì)數(shù)值計(jì)滿C_BPS_SELECT后才產(chǎn)生一個(gè)發(fā)送時(shí)鐘脈沖,而接收波特率時(shí)鐘只需要計(jì)滿C_BPS_SELECT的一半就產(chǎn)生了一個(gè)時(shí)鐘脈沖,這就導(dǎo)致在回顯實(shí)驗(yàn)中,O_bps_tx_clk滯后于O_bps_rx_clk,而回顯實(shí)驗(yàn)中我們直接把接收完成的標(biāo)志直接接在了發(fā)送開始標(biāo)志上,所以這就有可能導(dǎo)致,上一次的數(shù)據(jù)還沒發(fā)送完的時(shí)候這一次的數(shù)據(jù)已經(jīng)來了,經(jīng)過我的測(cè)試,使用上面的波特率邏輯,如果不做回顯實(shí)驗(yàn),一般沒問題,如果做回顯實(shí)驗(yàn),在波特率較高,比如115200bps和57600bps的情況下,數(shù)據(jù)量少的時(shí)候不會(huì)出錯(cuò),數(shù)據(jù)量大的時(shí)候一般都會(huì)有數(shù)據(jù)丟失,而在波特率較低的情況下,比如9600bps和2400bps,數(shù)據(jù)直接是接收一幀漏一幀,比如發(fā)送字符串a(chǎn)bcdef,接收回來的是ace。我用ChipScope才抓出了這個(gè)原因。今后使用的時(shí)候要注意這個(gè)問題。

5.2發(fā)送數(shù)據(jù)的狀態(tài)機(jī)和接收數(shù)據(jù)的狀態(tài)機(jī)可以用移位的方式來做

  事實(shí)上那個(gè)狀態(tài)機(jī)的發(fā)送8-bit數(shù)據(jù)和接收8-bit數(shù)據(jù)的部分可以用移位的方法來做,這樣寫的代碼會(huì)更短更精煉。今后有空的時(shí)候自己在重新寫一次。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
基于Verilog下的串口通信實(shí)驗(yàn)
FPGA實(shí)現(xiàn)串口UART自收發(fā)
UART串口收發(fā)控制器設(shè)計(jì)詳解
VHDL實(shí)驗(yàn)三:設(shè)計(jì)UART串行傳輸模塊 [CPLD/FPGA]
Testbench仿真串口自收發(fā)通信
一天一個(gè)設(shè)計(jì)實(shí)例-3萬(wàn)字講解UART和實(shí)例
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服