欢迎来到EDA中国!
当前位置:网站首页 >技术专栏 > FPGA

VHDL串口通信程序设计

发布时间: 2013-07-06 17:52:22     来源: EDA中国

VHDL串口通信程序设计
本模块的功能是验证实现和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

获取帮助