本模塊的功能是驗證實現和PC機進行基本的串口通信的功能。需要在
PC機上安裝一個串口調試工具來驗證程序的功能。
程序實現了一個收發一幀10個bit(即無奇偶校驗位)的串口控
制器,10個bit是1位起始位,8個數據位,1個結束
位。串口的波特律由程序中定義的div_par參數決定,更改該參數可以實
現相應的波特率。程序當前設定的div_par 的值是0x104,對應的波特率是
9600。用一個8倍波特率的時鐘將發送或接受每一位bit的周期時間
劃分為8個時隙以使通信同步.
程序的工作過程是:串口處于全雙工工作狀態,按動key2,CPLD向PC發送皐elcome"
字符串(串口調試工具設成按ASCII碼接受方式);PC可隨時向CPLD發送0-F的十六進制
數據,CPLD接受后顯示在7段數碼管上。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY UART IS
?? PORT (
????? clk???????????????????? : IN std_logic;??
????? rst???????????????????? : IN std_logic;??
????? rxd???????????????????? : IN std_logic;?? 串行數據接收端
????? txd???????????????????? : OUT std_logic; 串行數據發送端?
????? en????????????????????? : OUT std_logic_vector(7 downto 0); 數碼管使能
????? seg_data??????????????? : OUT std_logic_vector(7 DOWNTO 0); 數碼管數據?
????? key_input?????????????? : IN std_logic? 按鍵輸入
????? );
END UART;
ARCHITECTURE arch OF UART IS
?? //////////////////inner reg////////////////////
?? SIGNAL div_reg????????????????? :? std_logic_vector(15 DOWNTO 0);分頻計數器,分頻值由波特率決定。分頻后得到頻率8倍波特率的時鐘??
?? SIGNAL div8_tras_reg??????????? :? std_logic_vector(2 DOWNTO 0);該寄存器的計數值對應發送時當前位于的時隙數??
?? SIGNAL div8_rec_reg???????????? :? std_logic_vector(2 DOWNTO 0);? 寄存器的計數值對應接收時當前位于的時隙數
?? SIGNAL state_tras?????????????? :? std_logic_vector(3 DOWNTO 0);? 發送狀態寄存器
?? SIGNAL state_rec??????????????? :? std_logic_vector(3 DOWNTO 0); 接受狀態寄存器
?? SIGNAL clkbaud_tras???????????? :? std_logic; 以波特率為頻率的發送使能信號?
?? SIGNAL clkbaud_rec????????????? :? std_logic; 以波特率為頻率的接受使能信號?
?? SIGNAL clkbaud8x??????????????? :? std_logic; 以8倍波特率為頻率的時鐘,它的作用是將發送或接受一個bit的時鐘周期分為8個時隙?
?? SIGNAL recstart???????????????? :? std_logic; 開始發送標志
?? SIGNAL recstart_tmp???????????? :? std_logic; 開始接受標志?
?? SIGNAL trasstart??????????????? :? std_logic;??
?? SIGNAL rxd_reg1???????????????? :? std_logic; 接收寄存器1?
?? SIGNAL rxd_reg2???????????????? :? std_logic; 接收寄存器2,因為接收數據為異步信號,故用兩級緩存?
?? SIGNAL txd_reg????????????????? :? std_logic; 發送寄存器?
?? SIGNAL rxd_buf????????????????? :? std_logic_vector(7 DOWNTO 0);接受數據緩存??
?? SIGNAL txd_buf????????????????? :? std_logic_vector(7 DOWNTO 0);發送數據緩存??
?? SIGNAL send_state?????????????? :? std_logic_vector(2 DOWNTO 0);每次按鍵給PC發送"Welcome"字符串,這是發送狀態寄存器??
?? SIGNAL cnt_delay??????????????? :? std_logic_vector(19 DOWNTO 0);延時去抖計數器??
?? SIGNAL start_delaycnt?????????? :? std_logic;? 開始延時計數標志
?? SIGNAL key_entry1?????????????? :? std_logic;? 確定有鍵按下曛?
?? SIGNAL key_entry2?????????????? :? std_logic;? 確定有鍵按下標志
?? //////////////////////////////////////////////
?? CONSTANT? div_par?????????????? :? std_logic_vector(15 DOWNTO 0) := "0000000100000100";
?? 分頻參數,其值由對應的波特率計算而得,按此參數分頻的時鐘頻率是波倍特率的8倍,此處值對應9600的波特率,即分頻出的時鐘頻率是9600*8????
?? SIGNAL txd_xhdl3??????????????? :? std_logic;??
BEGIN
?? en <="01010101" ;7段數碼管使能信號賦值
?? txd <= txd_xhdl3;??
?? txd_xhdl3 <= txd_reg ;
?? PROCESS(clk,rst)
?? BEGIN
??????
????? IF (NOT rst = ’1’) THEN
???????? cnt_delay <= "00000000000000000000";???
???????? start_delaycnt <= ’0’;???
????? ELSIF(clk’EVENT AND clk=’1’)THEN
???????? IF (start_delaycnt = ’1’) THEN
??????????? IF (cnt_delay /= "11000011010100000000") THEN
?????????????? cnt_delay <= cnt_delay + "00000000000000000001";???
??????????? ELSE
?????????????? cnt_delay <= "00000000000000000000";???
?????????????? start_delaycnt <= ’0’;???
??????????? END IF;
???????? ELSE
??????????? IF ((NOT key_input=’1’) AND (cnt_delay = "00000000000000000000")) THEN
?????????????? start_delaycnt <= ’1’;???
??????????? END IF;
???????? END IF;
????? END IF;
?? END PROCESS;
?? PROCESS(clk,rst)
?? BEGIN
??????
????? IF (NOT rst = ’1’) THEN
???????? key_entry1 <= ’0’;???
????? ELSIF(clk’EVENT AND clk=’1’)THEN
???????? IF (key_entry2 = ’1’) THEN
??????????? key_entry1 <= ’0’;???
???????? ELSE
??????????? IF (cnt_delay = "11000011010100000000") THEN
?????????????? IF (NOT key_input = ’1’) THEN
????????????????? key_entry1 <= ’1’;???
?????????????? END IF;
??????????? END IF;
???????? END IF;
????? END IF;
?? END PROCESS;
?? PROCESS(clk,rst)
?? BEGIN
??????
????? IF (NOT rst = ’1’) THEN
???????? div_reg <= "0000000000000000";???
????? ELSIF(clk’EVENT AND clk=’1’)THEN
???????? IF (div_reg = div_par - "0000000000000001") THEN
??????????? div_reg <= "0000000000000000";???
???????? ELSE
??????????? div_reg <= div_reg + "0000000000000001";???
???????? END IF;
????? END IF;
?? END PROCESS;
?? PROCESS(clk,rst)? 分頻得到8倍波特率的時鐘
?? BEGIN
??????
????? IF (NOT rst = ’1’) THEN
???????? clkbaud8x <= ’0’;???
????? ELSIF(clk’EVENT AND clk=’1’)THEN
???????? IF (div_reg = div_par - "0000000000000001") THEN
??????????? clkbaud8x <= NOT clkbaud8x;???
???????? END IF;
????? END IF;
?? END PROCESS;
?? PROCESS(clkbaud8x,rst)
?? BEGIN
????? IF (NOT rst = ’1’) THEN
???????? div8_rec_reg <= "000";???
????? ELSE IF(clkbaud8x’EVENT AND clkbaud8x = ’1’) THEN
???????? IF (recstart = ’1’) THEN? 接收開始標志
??????????? div8_rec_reg <= div8_rec_reg + "001";接收開始后,時隙數在8倍波特率的時鐘下加1循環???
???????? END IF;
??? END IF;
????? END IF;
?? END PROCESS;
?? PROCESS(clkbaud8x,rst)
?? BEGIN
????? IF (NOT rst = ’1’) THEN
???????? div8_tras_reg <= "000";???
????? ELSE IF(clkbaud8x’EVENT AND clkbaud8x = ’1’) THEN
???????? IF (trasstart = ’1’) THEN
??????????? div8_tras_reg <= div8_tras_reg + "001";發送開始后,時隙數在8倍波特率的時鐘下加1循環???
???????? END IF;
??? END IF;
????? END IF;
?? END PROCESS;
?? PROCESS(div8_rec_reg)
?? BEGIN
????? IF (div8_rec_reg = "111") THEN
???????? clkbaud_rec <= ’1’; -在第7個時隙,接收??
????? ELSE
???????? clkbaud_rec <= ’0’;???
????? END IF;
?? END PROCESS;
?? PROCESS(div8_tras_reg)
?? BEGIN
????? IF (div8_tras_reg = "111") THEN
???????? clkbaud_tras <= ’1’;? 在第7個時隙,發送使能信號有效,將數據發出?
????? ELSE
???????? clkbaud_tras <= ’0’;???
????? END IF;
?? END PROCESS;
?? PROCESS(clkbaud8x,rst)
?? BEGIN
????? IF (NOT rst = ’1’) THEN
???????? txd_reg <= ’1’;???
???????? trasstart <= ’0’;???
???????? txd_buf <= "00000000";???
???????? state_tras <= "0000";???
???????? send_state <= "000";???
???????? key_entry2 <= ’0’;???
????? ELSE IF(clkbaud8x’EVENT AND clkbaud8x = ’1’) THEN
???????? IF (NOT key_entry2 = ’1’) THEN
??????????? IF (key_entry1 = ’1’) THEN
?????????????? key_entry2 <= ’1’;???
?????????????? txd_buf <= "01110111";?? "w"
??????????? END IF;
???????? ELSE
??????????? CASE state_tras IS
?????????????? WHEN "0000" =>? 發送起始位
??????????????????????? IF ((NOT trasstart=’1’) AND (send_state < "111") ) THEN
?????????????????????????? trasstart <= ’1’;???
??????????????????????? ELSE
?????????????????????????? IF (send_state < "111") THEN
????????????????????????????? IF (clkbaud_tras = ’1’) THEN
???????????????????????????????? txd_reg <= ’0’;???
???????????????????????????????? state_tras <= state_tras + "0001";???
????????????????????????????? END IF;
?????????????????????????? ELSE
????????????????????????????? key_entry2 <= ’0’;???
????????????????????????????? state_tras <= "0000";???
?????????????????????????? END IF;
??????????????????????? END IF;
?????????????? WHEN "0001" => 發送第1位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "0010" =>? 發送第2位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "0011" =>? 發送第3位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "0100" => 發送第4位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "0101" => 發送第5位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "0110" => 發送第6位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "0111" => 發送第7位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "1000" =>? 發送第8位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= txd_buf(0);???
?????????????????????????? txd_buf(6 DOWNTO 0) <= txd_buf(7 DOWNTO 1);???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "1001" =>? 發送停止位
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? txd_reg <= ’1’;???
?????????????????????????? txd_buf <= "01010101";???
?????????????????????????? state_tras <= state_tras + "0001";???
??????????????????????? END IF;
?????????????? WHEN "1111" =>
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? state_tras <= state_tras + "0001";???
?????????????????????????? send_state <= send_state + "001";???
?????????????????????????? trasstart <= ’0’;???
?????????????????????????? CASE send_state IS
????????????????????????????? WHEN "000" =>
?????????????????????????????????????? txd_buf <= "01100101"; "e"??
????????????????????????????? WHEN "001" =>
?????????????????????????????????????? txd_buf <= "01101100"; "l"??
????????????????????????????? WHEN "010" =>
?????????????????????????????????????? txd_buf <= "01100011";? "c"?
????????????????????????????? WHEN "011" =>
?????????????????????????????????????? txd_buf <= "01101111"; "o"?
????????????????????????????? WHEN "100" =>
?????????????????????????????????????? txd_buf <= "01101101";? "m"?
????????????????????????????? WHEN "101" =>
?????????????????????????????????????? txd_buf <= "01100101"; "e"??
????????????????????????????? WHEN OTHERS? =>
?????????????????????????????????????? txd_buf <= "00000000";?
?????????????????????????????
?????????????????????????? END CASE;
??????????????????????? END IF;
?????????????? WHEN OTHERS? =>
??????????????????????? IF (clkbaud_tras = ’1’) THEN
?????????????????????????? state_tras <= state_tras + "0001";???
?????????????????????????? trasstart <= ’1’;???
??????????????????????? END IF;
??????????????
??????????? END CASE;
???????? END IF;
????? END IF;
?END IF;
?? END PROCESS;
?? PROCESS(clkbaud8x,rst)? 接受PC機的數據
?? BEGIN
????? IF (NOT rst = ’1’) THEN
???????? rxd_reg1 <= ’0’;???
???????? rxd_reg2 <= ’0’;???
???????? rxd_buf <= "00000000";???
???????? state_rec <= "0000";???
???????? recstart <= ’0’;???
???????? recstart_tmp <= ’0’;???
????? ELSE IF(clkbaud8x’EVENT AND clkbaud8x = ’1’) THEN
???????? rxd_reg1 <= rxd;???
???????? rxd_reg2 <= rxd_reg1;???
???????? IF (state_rec = "0000") THEN
??????????? IF (recstart_tmp = ’1’) THEN
?????????????? recstart <= ’1’;???
?????????????? recstart_tmp <= ’0’;???
?????????????? state_rec <= state_rec + "0001";???
??????????? ELSE
?????????????? IF ((NOT rxd_reg1 AND rxd_reg2) = ’1’) THEN 檢測到起始位的下降沿,進入接受狀態
????????????????? recstart_tmp <= ’1’;???
?????????????? END IF;
??????????? END IF;
???????? ELSE
??????????? IF (state_rec >= "0001" AND state_rec<="1000") THEN
?????????????? IF (clkbaud_rec = ’1’) THEN
????????????????? rxd_buf(7) <= rxd_reg2;???
????????????????? rxd_buf(6 DOWNTO 0) <= rxd_buf(7 DOWNTO 1);???
????????????????? state_rec <= state_rec + "0001";???
?????????????? END IF;
??????????? ELSE
?????????????? IF (state_rec = "1001") THEN
????????????????? IF (clkbaud_rec = ’1’) THEN
???????????????????? state_rec <= "0000";???
???????????????????? recstart <= ’0’;???
????????????????? END IF;
?????????????? END IF;
??????????? END IF;
???????? END IF;
????? END IF;
?END IF;
?? END PROCESS;
?? PROCESS(rxd_buf)?? 將接受的數據用數碼管顯示出來
?? BEGIN
????? CASE rxd_buf IS
???????? WHEN "00110000" =>
????????????????? seg_data <= "00000011"; 0??
???????? WHEN "00110001" =>
????????????????? seg_data <= "10011111"; 1?
???????? WHEN "00110010" =>
????????????????? seg_data <= "00100101"; 2?
???????? WHEN "00110011" =>
????????????????? seg_data <= "00001101"; 3??????
???????? WHEN "00110100" =>
????????????????? seg_data <= "10011001"; 4??
&nbs p;??????? WHEN "00110101" =>
????????????????? seg_data <= "01001001"; 5?
???????? WHEN "00110110" =>
????????????????? seg_data <= "01000001"; 6??
???????? WHEN "00110111" =>
????????????????? seg_data <= "00011111"; 7??
???????? WHEN "00111000" =>
????????????????? seg_data <= "00000001"; 8???
???????? WHEN "00111001" =>
????????????????? seg_data <= "00001001"; 9??
???????? WHEN "01000001" =>
????????????????? seg_data <= "00010001"; A??
???????? WHEN "01000010" =>
????????????????? seg_data <= "11000001"; B??
???????? WHEN "01000011" =>
????????????????? seg_data <= "01100011"; C??
???????? WHEN "01000100" =>
????????????????? seg_data <= "10000101"; D?
???????? WHEN "01000101" =>
????????????????? seg_data <= "01100001"; E??
???????? WHEN "01000110" =>
????????????????? seg_data <= "01110001"; F???
???????? WHEN OTHERS? =>
????????????????? seg_data <= "11111111";??????????
????? END CASE;
?? END PROCESS;
END arch;
VHDL設計的串口通信程序
- vhdl(127605)
- 串口通信(54799)
相關推薦
基于Linux環境下串口通信的應用設計
本文介紹了Linux環境下串口通信的設計方法和步驟,并介紹了ARM9微處理器s3c2440在Linux下和C8051Fxxx系列單片機進行串行通信的設計方法,給出了硬件連接和通信程序流程圖。該方法
2014-05-24 10:50:47
2623

VHDL串口程序怎么寫啊?具體要求就是這樣~!
VHDL串口程序怎么寫啊?具體要求就是這樣~!http://zhidao.baidu.com/question/547288797?quesup2&oldq=1
2013-05-24 21:16:33
基于EPM240T100的串口通信
CPLD串口通信模塊硬件設計 二、VHDL程序模塊設計及描述使用VHDL 對CPLD 進行編程,設計3 個模塊,波特率發生模塊,接收器,發送器。1. 波特率發生模塊波特率發生器實際是一個分頻器,如前所述
2013-11-13 11:01:30
多線程在VC++串口通信程序中的應用
本文通過一機房監控系統程序中串口通信對多線程的應用來介紹Windows 9X/NT操作系統中多線程的應用和VC++對多線程的支持。關健詞: 多線程,串口通信在現代的各種實時監控系
2009-09-03 11:45:29
27

VHDL 語言程序的元素
VHDL 語言程序的元素:本章主要內容:VHDL語言的對象VHDL語言的數據類型VHDL語言的運算符VHDL語言的標識符VHDL語言的詞法單元
2009-09-28 14:32:21
41

評論