色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 手機(jī)與無線通信 > 牛人業(yè)話 > 小梅哥和你一起深入學(xué)習(xí)FPGA之串口調(diào)試(一)(上)

          小梅哥和你一起深入學(xué)習(xí)FPGA之串口調(diào)試(一)(上)

          作者: 時(shí)間:2015-11-19 來源:網(wǎng)絡(luò) 收藏

            大家好,這幾天在各個(gè)論壇上,經(jīng)常就有人在向我咨詢基于的串口通信代碼,大部分都是在網(wǎng)上下載一個(gè)現(xiàn)成的代碼,但是在使用中就遇到了各種問題,于是就發(fā)到了論壇上來求助。在閱讀了他們的代碼之后,我發(fā)現(xiàn)幾乎出自同一個(gè)版本(目前確定為特權(quán)同學(xué)的基于EPM240入門實(shí)驗(yàn)的代碼)。他們?cè)谡{(diào)試這個(gè)代碼的時(shí)候,經(jīng)常存在這樣幾個(gè)問題:1、部分人對(duì)該串口通訊模塊完全不理解,對(duì)每句話,甚至每個(gè)模塊的功能都不理解;2、部分人采用最原始的畫波形的方式來對(duì)該模塊進(jìn)行仿真,結(jié)果無法得到仿真結(jié)果;3、部分人不會(huì)使用modelsim對(duì)該設(shè)計(jì)進(jìn)行仿真;4、絕大部分人不會(huì)編寫testbench;5、下板測(cè)試無法進(jìn)行正確的字符串收發(fā)。在公司內(nèi)部,我將這種現(xiàn)象和幾位老師交流之后,夏宇聞老師建議我專門針對(duì)該代碼寫一個(gè)由原理到代碼,由仿真到板級(jí)的調(diào)試筆記。爭(zhēng)取用最通俗,也是最笨的辦法,手把手的教會(huì)大家來調(diào)試這個(gè)代碼。

          本文引用地址:http://cafeforensic.com/article/283059.htm

            本調(diào)試筆記主要由五個(gè)部分組成:原始代碼分析;原始代碼驗(yàn)證;對(duì)原始代碼進(jìn)行修改;對(duì)修改后的代碼進(jìn)行驗(yàn)證;對(duì)修改后的設(shè)計(jì)進(jìn)行板級(jí)驗(yàn)證。每個(gè)部分,小梅哥都會(huì)用圖文結(jié)合的方式,教大家一步一步的來進(jìn)行。

            原始代碼分析

            該代碼來自小梅哥最崇拜的大神,特權(quán)同學(xué)。當(dāng)時(shí)小梅哥也是看著特權(quán)同學(xué)的書和視頻教程一步一步走過來的。特權(quán)同學(xué)的代碼實(shí)現(xiàn)了單字節(jié)的收發(fā)測(cè)試,沒有對(duì)連續(xù)字節(jié)的收發(fā)進(jìn)行測(cè)試。特權(quán)同學(xué)當(dāng)時(shí)也說過,這個(gè)只是一個(gè)簡(jiǎn)單的實(shí)驗(yàn),離實(shí)際工業(yè)應(yīng)用還有一定的距離??紤]到論壇上很多小伙伴都希望能夠?qū)崿F(xiàn)連續(xù)字節(jié)的收發(fā)功能,因此小梅哥就在特權(quán)同學(xué)的代碼上進(jìn)行了修改。修改后的代碼,輸入時(shí)鐘可以在一定范圍內(nèi)選擇任意頻率,目前已經(jīng)支持5種波特率選擇(9600、19200、38400、57600、115200),實(shí)際小梅哥還做過更高波特率的測(cè)試,目前實(shí)測(cè)在115200波特率的速率下可以實(shí)現(xiàn)超過9999999次連續(xù)無間斷的收發(fā)。這里,小梅哥首先將特權(quán)同學(xué)設(shè)計(jì)架構(gòu)在這里列出來,以給讀者一個(gè)直觀的印象。

              

           

            由上圖可知,特權(quán)同學(xué)的UART串口設(shè)計(jì)主要包含了四個(gè)模塊:串口發(fā)送模塊(my_uart_tx)、串口接收模塊(my_uart_rx)、串口接收波特率發(fā)生器(speed_rx)和串口發(fā)送波特率發(fā)生器(speed_tx),其中,串口發(fā)送波特率發(fā)生器主要用來產(chǎn)生串口發(fā)送模塊發(fā)送數(shù)據(jù)時(shí)所需的波特率時(shí)鐘,串口接收波特率發(fā)生器主要用來產(chǎn)生串口接收模塊接收數(shù)據(jù)時(shí)的波特率時(shí)鐘,串口發(fā)送模塊主要負(fù)責(zé)在指定波特率的速率下將待發(fā)送字節(jié)發(fā)送出去,串口接收模塊則主要負(fù)責(zé)接收來自其他設(shè)備發(fā)送過來的串口數(shù)據(jù)。my_uart_top模塊即串口收發(fā)頂層模塊實(shí)現(xiàn)了各個(gè)模塊間的信號(hào)連接功能,通過該頂層模塊的連接,實(shí)現(xiàn)了將串口接收到的數(shù)據(jù)再發(fā)送出去的功能,即我們測(cè)試串口通信最常用的一種方式——回環(huán)測(cè)試。特權(quán)同學(xué)該實(shí)驗(yàn)的各個(gè)端口和內(nèi)部信號(hào)的意義如表1所示:

            該實(shí)驗(yàn)的內(nèi)容為,串口接收模塊在檢測(cè)到發(fā)送設(shè)備發(fā)送過來的數(shù)據(jù)起始位時(shí),接收中斷信號(hào)置1,該信號(hào)則作為啟動(dòng)串口接收波特率發(fā)送器的控制信號(hào),然后在每個(gè)波特率時(shí)鐘上升沿到來時(shí)讀取串口接收端口(rs232_rx)上的數(shù)據(jù)。一幀(字節(jié))數(shù)據(jù)接收完成后,接收中斷信號(hào)拉低,停止波特率發(fā)生器工作,接收完成,系統(tǒng)進(jìn)入等待狀態(tài),等待下一次的數(shù)據(jù)到來。

            同時(shí),接收中斷信號(hào)的下降沿也作為串口發(fā)送模塊的發(fā)送使能信號(hào),因?yàn)橐坏┙邮罩袛嘈盘?hào)的下降沿出現(xiàn),就表明接收模塊完成了一次數(shù)據(jù)的接收,此時(shí),就開始使能串口發(fā)送波特率發(fā)生器,串口發(fā)送模塊則在波特率時(shí)鐘的上升沿到來時(shí)依次將接收模塊接收到的數(shù)據(jù)的每一位(發(fā)送模塊自動(dòng)添加起始位和停止位)依次發(fā)送出去,當(dāng)數(shù)據(jù)發(fā)送完成之后,停止串口發(fā)送波特率發(fā)生器的使能,模塊進(jìn)入等待狀態(tài),等待下一次接收中斷信號(hào)下降沿的到來。

            這里,我們首先對(duì)該設(shè)計(jì)的波特率發(fā)生器模塊進(jìn)行分析。該模塊相對(duì)簡(jiǎn)單,代碼如下所示:

            以下是代碼片段:

            1 module speed_select (

            2 clk, rst_n ,

            3 bps_start , clk_bps

            4 );

            5

            6 input clk; // 50MHz

            7 input rst_n ; //

            8 input bps_start ; //

            9 output clk_bps ; // clk_bps

            10

            11 /*

            12 parameter bps9600 = 5207, // 9600bps

            13 bps19200 = 2603, // 19200bps

            14 bps38400 = 1301, // 38400bps

            15 bps57600 = 867, // 57600bps

            16 bps115200 = 433; // 115200bps

            17

            18 parameter bps9600_2 = 2603,

            19 bps19200_2 = 1301,

            20 bps38400_2 = 650,

            21 bps57600_2 = 433,

            22 bps115200_2 = 216;

            23 */

            24

            25 //

            26 `define BPS_PARA 5207 // 9600

            27 `define BPS_PARA_2 2603 // 9600

            28

            29 reg[ 12 : 0] cnt ; //

            30 reg clk_bps_r ; //

            31

            32 //---------------------------------------------------------

            33 reg[ 2 : 0] uart_ctrl ; // uart

            34 //---------------------------------------------------------

            35

            36 always @ ( posedge clk or negedge rst_n )

            37 if(! rst_n ) cnt <= 13'd0 ;

            38 else if(( cnt == `BPS_PARA ) || ! bps_start ) cnt <= 13'd0 ;

            39 else cnt <= cnt+1'b1 ; //

            40

            41 always @ ( posedge clk or negedge rst_n )

            42 if(! rst_n ) clk_bps_r <= 1'b0 ;

            43 else if( cnt == `BPS_PARA_2 ) clk_bps_r <= 1'b1 ;

            //clk_bps_r ,

            44 else clk_bps_r <= 1'b0 ;

            45

            46 assign clk_bps = clk_bps_r ;

            47

            48 endmodule

            該代碼的12-22行用注釋的方式告訴了我們,獲得不同波特率時(shí)波特率分頻計(jì)數(shù)器的值應(yīng)該為多少,以及波特率計(jì)數(shù)器計(jì)數(shù)到一半時(shí)的值為多少(該值作為對(duì)信號(hào)的采樣點(diǎn),因?yàn)橐话闱闆r下,一位數(shù)據(jù),在該位數(shù)據(jù)保持時(shí)間的中間時(shí)刻是最穩(wěn)定的)。26行和27行定義的兩個(gè)參數(shù)BPS_PARA和BPS_PARA_2分別就是波特率分頻計(jì)數(shù)器的最大值和中間值。實(shí)際使用時(shí),只需要根據(jù)你所需要的波特率,更改這兩個(gè)參數(shù)的值即可 。例如,選擇波特率為9600bps時(shí),設(shè)定BPS_PARA=5207,BPS_PARA_2=2603。關(guān)于這個(gè)值的計(jì)算,這里暫時(shí)不提,后文會(huì)有交代。

            36行至39行為波特率分頻計(jì)數(shù)器的計(jì)數(shù)進(jìn)程,即波特率發(fā)生模塊沒有被使能(! bps_start)或者計(jì)數(shù)器計(jì)數(shù)到BPS_PARA后則將計(jì)數(shù)器清零,其它情況下則每來一個(gè)時(shí)鐘上升沿計(jì)數(shù)器自加1。通過此進(jìn)程,則可得到相對(duì)精準(zhǔn)的波特率定時(shí)。

            41行至44行為數(shù)據(jù)采樣時(shí)刻的生成,上面提到過“一般情況下,一位數(shù)據(jù),在該位數(shù)據(jù)保持時(shí)間的中間時(shí)刻是最穩(wěn)定的”,因此這里我們?cè)谟?jì)數(shù)器計(jì)數(shù)到一半時(shí),產(chǎn)生一個(gè)時(shí)鐘周期的高脈沖,此脈沖作為采樣數(shù)據(jù)的使能信號(hào)。

           


          上一頁 1 2 3 下一頁

          關(guān)鍵詞: FPGA 串口調(diào)試

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉