VHDL實(shí)驗(yàn)三:設(shè)計(jì)UART串行傳輸模塊 [CPLD/FPGA]發(fā)布時(shí)間:2010-12-13 23:51:24 一,、 實(shí)驗(yàn)原理: 1,、 概述 UART的全稱是通用異步收發(fā)器(Universal Asynchronous Receiver/Transmitter),是實(shí)現(xiàn)設(shè)備之間低速數(shù)據(jù)通信的標(biāo)準(zhǔn)協(xié)議,?!爱惒健敝覆恍枰~外的時(shí)鐘線進(jìn)行數(shù)據(jù)的同步傳輸,是一種串行總線接口,,只需占用兩根線就可以完成數(shù)據(jù)的收發(fā)(一根接收數(shù)據(jù),一根發(fā)送數(shù)據(jù)),,常用的標(biāo)準(zhǔn)通信波特率有9600bps,、115200bps等。 2,、 通信協(xié)議與幀格式 UART一幀由起始位,、數(shù)據(jù)位、校驗(yàn)位和停止位組成,。數(shù)據(jù)逐位傳輸,,示意圖如圖 1.1所示,。 a) 起始位 UART空閑時(shí)(沒有數(shù)據(jù)傳輸),總線為高電平(邏輯1),,當(dāng)需要數(shù)據(jù)傳輸時(shí),,首先發(fā)送一個(gè)“起始位”,起始位為一個(gè)低電平“邏輯0”,。 為什么需要起始位,? 因?yàn)閁ART沒有控制線,要讓接收方知道什么時(shí)候開始接收數(shù)據(jù),,需要一些手段,,在UART,數(shù)據(jù)的傳輸只有一根線,,所以在發(fā)送數(shù)據(jù)之前,,先發(fā)一位邏輯“0”作為數(shù)據(jù)發(fā)送的起始標(biāo)志,接收方在空閑時(shí),當(dāng)檢測到有一個(gè)低電平,,則開始接逐位接收數(shù)據(jù),。 b) 數(shù)據(jù)位 如圖 1.1的“2.”所示,緊挨著“起始位”的是數(shù)據(jù)位,,它可以是5,、6、7或8位,,收/發(fā)雙方在數(shù)據(jù)開始傳輸前,,需要對雙方數(shù)據(jù)位位數(shù)作一致的定義,否則會導(dǎo)致數(shù)據(jù)的傳輸錯(cuò)誤,;數(shù)據(jù)位的發(fā)送采用低位(LSB)先發(fā)送,。 為什么數(shù)據(jù)位可變? 因?yàn)閁ART是一種低速總線,,每多發(fā)一位都占用不少的時(shí)間(由傳輸波特波決定),,所以可以傳輸數(shù)據(jù)的特點(diǎn),采用不同位數(shù)據(jù)的波特率以節(jié)約時(shí)間,。如在Modbus協(xié)議中,,Modbus-ASCII是以ASCII碼傳輸?shù)模驗(yàn)锳SCII是不會大于0x7F,,所以使用7位的數(shù)據(jù)位,,而Modbus-RTU則采用8位的數(shù)據(jù)位。 c) 校驗(yàn)位 UART的校驗(yàn)位緊挨著數(shù)據(jù)位,,采用奇/偶位校驗(yàn)方式,,可有可無,是為了為了驗(yàn)證數(shù)據(jù)傳輸?shù)陌踩远O(shè)置的,,在收/發(fā)雙方進(jìn)行數(shù)據(jù)傳輸前要預(yù)設(shè)好是否需要校驗(yàn)位,如果需要?jiǎng)t是奇校驗(yàn)還是偶校驗(yàn),。如圖 1.1的“3.”所示,。 為什么需要校驗(yàn)? UART長距離數(shù)據(jù)傳輸時(shí),使用RS-232,、RS-485傳輸,,一般使用較長的導(dǎo)線連接收/發(fā)設(shè)備,其工作現(xiàn)場因存在不同程序的干擾,,可能會導(dǎo)致數(shù)據(jù)的傳輸錯(cuò)誤,,加個(gè)校驗(yàn)位可作初步的校驗(yàn),如果校驗(yàn)出錯(cuò),,說明數(shù)據(jù)是不可靠的,,直接丟棄;如果校驗(yàn)通過,則數(shù)據(jù)有一定的可靠性,,可進(jìn)入下一級的校驗(yàn),,通常加入通信協(xié)議,如Modbus-RTU引入了CRC校驗(yàn),。 d) 停止位 UART的幀以停止位作為停止標(biāo)志,,是在數(shù)據(jù)位(沒有校驗(yàn)位)和校驗(yàn)位(有校驗(yàn)位)之后發(fā)送1~2位的邏輯“1”。停止為可以為1位,、1.5位和2位,。當(dāng)發(fā)送完停止位之后,UART總線進(jìn)入空閑,。 e) 空閑 空閑指UART總線上沒有數(shù)據(jù)進(jìn)行傳輸,,表現(xiàn)為發(fā)送方輸出邏輯“1”,在空閑時(shí),,接收方時(shí)刻監(jiān)視UART總線上電平變化,,當(dāng)發(fā)現(xiàn)起始化,則進(jìn)入數(shù)據(jù)接收狀態(tài),,直至接收完一幀數(shù)據(jù),,如果最后沒有檢測到停止位,則標(biāo)志幀錯(cuò)誤,。 f) 波特率(Baudrate) 由于UART沒有同步時(shí)鐘線,,收/發(fā)雙方如果需要進(jìn)行正確的數(shù)據(jù)傳輸,則要在收/發(fā)雙方定義一致的位時(shí)鐘,,位時(shí)鐘可以理解為UART總線一個(gè)位所占用的時(shí)間,,即“波特率”。在定義上,,收/發(fā)雙方的波特率可以是隨意的,,只需要保持一致,如雙方都是1000bps,,但是,,這不能兼容現(xiàn)有常用的設(shè)備,兼容性差,。所以在工程應(yīng)用中,,常用一些特定的波特率真,如4800bps,、9600bps或115200bps等,。 如果波特率是9600bps,則傳輸速度最大是多少? 波特率的單位是bps(位每秒),,是指發(fā)送一位所占用的時(shí)間,。如果UART定義8位數(shù)數(shù)位,、無校驗(yàn)、1位停止位,。則一幀數(shù)據(jù)的位數(shù)N如公式(3)所示: N = 1位起始位+8位數(shù)據(jù)位+0位校驗(yàn)位+1位停止位=10bits 公式(3) 所以最大數(shù)據(jù)傳輸率為:9600bps / N = 960BPS(字節(jié)每秒),。 即當(dāng)波特率為9600rps,UART幀格式為8位數(shù)據(jù)位,、無校驗(yàn),、1位停止位時(shí),最大的數(shù)據(jù)傳輸率為0.96KBPS,。 g) 常用幀格式 如圖 1.3所示為8位數(shù)據(jù)位,、無校驗(yàn)位、1位停止位的幀格式示意圖,,一幀共有10位,。發(fā)送的數(shù)據(jù)為0xA5。
3,、 硬件接口 a)RS-232連接器 RS-232的連接器常用的是DB-9,,其連接器示意圖如圖 1.6所示,為九針連接器,。對于常用的簡單應(yīng)用,,使用到的有三根線:RxD、TxD和GND,。串口接口頭分公母接頭,,下面所示為母的接頭。
實(shí)物圖如圖 1.7所示,。 b) 電平轉(zhuǎn)換電路(與計(jì)算機(jī)連接)
二,、實(shí)驗(yàn)過程 有了上面的理論基礎(chǔ)我們就可以開始設(shè)計(jì)一個(gè)UART的串行傳輸模塊了。 1,、 系統(tǒng)框圖的設(shè)計(jì): 系統(tǒng)的傳輸取決于波特率的大小,,所以要設(shè)計(jì)一個(gè)專門產(chǎn)生波特率計(jì)數(shù),實(shí)質(zhì)上是對系統(tǒng)時(shí)鐘頻率進(jìn)行分頻,。由于是單線發(fā)送和接收,,實(shí)現(xiàn)了全雙工傳輸,實(shí)質(zhì)上是相當(dāng)于串行序列接收與發(fā)生,,只不過這個(gè)序列是有一定的通信格式而已,。下面是兩個(gè)系統(tǒng)的框圖設(shè)計(jì): 圖2.1接收模塊系統(tǒng)框圖 圖2.2發(fā)送模塊的系統(tǒng)框圖 2,、 波特率計(jì)數(shù)器設(shè)計(jì): 我們以9600的波特率,,50MHZ的時(shí)鐘晶振舉例說明:由上面的理論知識我們可以知道,9600bps,,則表示傳輸一位的時(shí)間需要1/9600s,。時(shí)鐘晶振為50MHZ,則一個(gè)時(shí)鐘脈沖周期為:1/50M s。則串行傳輸一位的時(shí)間長度需要50M/9600=5208個(gè)時(shí)鐘脈沖周期,,半周期為2604個(gè)時(shí)鐘脈沖周期,。這個(gè)波特率時(shí)鐘脈沖就可以由系統(tǒng)時(shí)鐘脈沖分頻所得。 程序設(shè)計(jì): --工程名:時(shí)鐘分頻器 --功能:實(shí)現(xiàn)對時(shí)鐘脈沖的分頻,,產(chǎn)生9600波特率時(shí)鐘脈沖 --時(shí)間:2010-12-10 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all;
entity speed_select is port(clk:in std_logic;--時(shí)鐘信號 rst:in std_logic;--復(fù)位信號,,低電平有效 bps_start:in std_logic;--信號開始傳輸信號 clk_bps:out std_logic);--波特率信號 end entity;
architecture behav of speed_select is constant bps_para: integer :=5207; constant bps_para_2: integer :=2603; signal cnt:integer range 0 to bps_para:=0;
begin process(clk) --計(jì)數(shù)進(jìn)程 begin if(rst='0') then cnt<=0; elsif rising_edge(clk) then clk_bps<='1'; --后半周期置1 if (cnt<bps_para_2) then --前半周期置0 clk_bps<='0'; cnt<=cnt+1; --不斷自加計(jì)數(shù) elsif cnt<bps_para then cnt<=cnt+1; else cnt<=0; --計(jì)數(shù)完成對cnt進(jìn)行清零 end if; if(bps_start='0') then ---數(shù)據(jù)開始傳輸對cnt進(jìn)行清零 cnt<=0; end if; end if; end process; end behav;
仿真結(jié)果如下: 3、 串行數(shù)據(jù)接收器設(shè)計(jì): 串行數(shù)據(jù)是在波特率時(shí)鐘脈沖下傳輸?shù)?。根?jù)UART的常用串行傳輸協(xié)議(1位低電平起始位,,8位數(shù)據(jù)位,無檢驗(yàn)位,,1位停止位),,我們可以設(shè)計(jì)出如下的狀態(tài)機(jī): 程序設(shè)計(jì)如下:
--工程名:UART串行接收器 --功能:實(shí)現(xiàn)對RXD串行數(shù)據(jù)接收,轉(zhuǎn)換成8位數(shù)據(jù)并行輸出 --時(shí)間:2010-12-10 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all;
entity uart_rx is port( rst:in std_logic; --復(fù)位信號,,低電平有效 rx:in std_logic;--RXD串行數(shù)據(jù)輸入 clk_bps:in std_logic;--波特率信號 rx_data:out std_logic_vector(7 downto 0); --8位并行數(shù)據(jù)輸出 rx_int:out std_logic;--中斷傳輸信號 bps_start:out std_logic--信號開始傳輸信號 ); end entity;
architecture asm of uart_rx is signal shifter:std_logic_vector(7 downto 0); signal bitstate:integer range 0 to 10:=0; begin process(clk_bps,rst,rx) --接收進(jìn)程 begin if(rst='0') then --復(fù)位信號 bitstate<=0; shifter<="ZZZZZZZZ"; elsif(rising_edge(clk_bps)) then if(bitstate=0) then --狀態(tài)0 判斷有沒有數(shù)據(jù)輸入 if(rx='0') then bitstate<=bitstate+1; bps_start<='1'; end if; elsif(bitstate=9) then --狀態(tài)9 數(shù)據(jù)接收完成 bitstate<=0; bps_start<='0'; else --其他狀態(tài)接收1-8為數(shù)據(jù),,停止位不檢查 shifter(0)<=rx; shifter(7 downto 1)<=shifter(6 downto 0); bps_start<='0'; bitstate<=bitstate+1; end if; end if; end process;
process(clk_bps,rst) --輸出進(jìn)程 begin if(rst='0') then rx_data<="00000000"; rx_int<='0'; elsif(bitstate=9) then rx_data<=shifter; --數(shù)據(jù)輸出 rx_int<='1'; else rx_int<='0'; rx_data<="ZZZZZZZZ"; end if; end process; end asm;
仿真結(jié)果如下:
4、 串行數(shù)據(jù)發(fā)送器設(shè)計(jì): --工程名:UART串行發(fā)送器 --功能:實(shí)現(xiàn)對8位并行輸入數(shù)據(jù),,轉(zhuǎn)換成TXD串行數(shù)據(jù)發(fā)送 --時(shí)間:2010-12-10 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all;
entity uart_tx is port( rst:in std_logic; --復(fù)位信號,,低電平有效 rx_data:in std_logic_vector(7 downto 0); --8位并行數(shù)據(jù)輸入 rx_int:in std_logic;--中斷傳輸信號 clk_bps:in std_logic;--波特率信號 tx:out std_logic;--TXD串行數(shù)據(jù)輸出 bps_start:out std_logic--信號開始傳輸信號 ); end entity;
architecture asm of uart_tx is signal shifter:std_logic_vector(7 downto 0); type state is(s0,s1,s2,s3); begin process(clk_bps,rst) variable cnt:integer range 0 to 8; variable present_state:state; begin if(rst='0') then tx<='1'; bps_start<='0'; elsif(rising_edge(clk_bps)) then case present_state is when s0=> --判定有沒有并行數(shù)據(jù)輸入 if(rx_int='1') then shifter<=rx_data; bps_start<='1'; tx<='1'; present_state:=s1; else tx<='1'; present_state:=s0; end if; when s1=> --狀態(tài)1,低電平起始位輸出 tx<='0'; bps_start<='0'; present_state:=s2; when s2=> --狀態(tài)2,8位數(shù)據(jù)移位輸出 if(cnt<8) then tx<=shifter(cnt); bps_start<='0'; cnt:=cnt+1; present_state:=s2; else cnt:=0; bps_start<='0'; present_state:=s3; end if; when s3=> --狀態(tài)3,,高電平停止位輸出 tx<='1'; bps_start<='0'; present_state:=s0; end case; end if; end process; end asm;
仿真結(jié)果如下: 圖形化設(shè)計(jì):
利用Quartus集成的仿真軟件,,比較難檢驗(yàn)生成的總體圖形文件,這里就不做仿真了,。 每個(gè)模塊都是經(jīng)過仿真測試的,。估計(jì)沒有什么問題了。
實(shí)驗(yàn)總結(jié):通過本次實(shí)驗(yàn)進(jìn)一步熟悉了對FPGA的開發(fā)流程,。之前一直用這個(gè)UART通信,,但是由于單片機(jī)將這個(gè)模塊集成化了,也只是在用,,沒有深入去了解,,通過本次實(shí)驗(yàn)對這個(gè)串口通信協(xié)議有了刨根式的了解。通過本次實(shí)驗(yàn),,我也深刻的體會到一個(gè)項(xiàng)目的開展過程,,首先要對項(xiàng)目的理論知識深入理解,才能很好的開展項(xiàng)目,,同時(shí)在遇到從來沒有遇到過的問題時(shí),,要將這個(gè)問題化解成自己熟悉的模塊,一步一步的實(shí)現(xiàn),,不能操之過急,。在這個(gè)工程中,,我們將可以將這個(gè)系統(tǒng)化解成三個(gè)模塊進(jìn)行開展:波特率發(fā)生器(分頻器),串行數(shù)據(jù)接收器(序列接收器),,串行數(shù)據(jù)發(fā)送器(序列發(fā)生器),。這樣的話,不但目標(biāo)明確,,而且將項(xiàng)目分工,,加快了項(xiàng)目的進(jìn)度。這是最后一次實(shí)驗(yàn)了,,期待著課程設(shè)計(jì)了,,希望這個(gè)課程在以后能派上大用場。
主要遇到的問題: 1,, 對UART通信協(xié)議的理論知識理解:雖然一直在用這個(gè)模塊,,但是卻對其如何實(shí)現(xiàn)沒有真正的了解過,通過本次實(shí)驗(yàn)惡補(bǔ)這方面的知識了 2,, 項(xiàng)目的構(gòu)架,,對這個(gè)工程如何構(gòu)架,如何將分割成自己熟悉的模塊,。這個(gè)開展這個(gè)工程所首要解決的,,同時(shí)也要花中功夫下去,因?yàn)檫@一步直接關(guān)系到下一步開展的,。 3,, 已經(jīng)開始熟練VHDL編程了,在語法上面,,沒有什么好糾結(jié)的了,,經(jīng)過上兩次的實(shí)驗(yàn)后,這次實(shí)驗(yàn)還是挺順利的,,慢慢在成長著,。 |
|