⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 urat.vhd

📁 VHDL语言编写的全功能串口模块(包含DTR
💻 VHD
📖 第 1 页 / 共 2 页
字号:

--程序_UART串行通信  
 --这个程序可以完成简单的串行收发任务,时钟频率采用40MHz 

-- 本模块的功能是验证实现和PC机进行基本的串口通信的功能。需要在 
--PC机上安装一个串口调试工具来验证程序的功能。 
-- 程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控 
--制器,10个bit是1位起始位,8个数据位,1个结束 
--位。串口的波特律由程序中定义的div_par参数决定,更改该参数可以实 
--现相应的波特率。程序当前设定的div_par 的值是0x104,对应的波特率是 
--9600。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间 
--划分为8个时隙以使通信同步. 
--程序的工作过程是:串口处于全双工工作状态,按动SW0,CPLD向PC发送“welcome" 
--字符串(串口调试工具设成按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; -- 数码管使能  

      clkout                  : OUT std_logic;

      out_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(7 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 seg_data                  :  std_logic_vector(7 DOWNTO 0);
 
--------------------------------------------------------------------------------
 
    SIGNAL key_entry1               :  std_logic;  --确定有键按下标志  
 
   --////////////////////////////////////////////// 
   --CONSTANT  div_par               :  std_logic_vector(15 DOWNTO 0) := "0000000100000100";  
CONSTANT  div_par               :  std_logic_vector(7 DOWNTO 0) := "00011010";  
   --分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8      
   SIGNAL txd_xhdl3                :  std_logic;    

BEGIN 
   en <='0' ;--7段数码管使能信号赋值 
   txd <= not txd_xhdl3;    
   txd_xhdl3 <= txd_reg ; 

clkout<=clkbaud8x;
out_data<=txd_buf;
key_entry1<=key_input;

   PROCESS(clk,rst) 
   BEGIN 
       
      IF (NOT rst = '1') THEN 
         div_reg <= "00000000";     
      ELSIF(clk'EVENT AND clk='1')THEN 
         IF (div_reg = div_par - "00000001") THEN 
            div_reg <= "00000000";     
         ELSE 
            div_reg <= div_reg + "00000001";     
         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 - "00000001") 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";          
      ELSE IF(clkbaud8x'EVENT AND clkbaud8x = '1') THEN 
         IF (NOT key_entry1= '1') THEN 
               txd_buf <= "01110111";   --"w"  
          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 
                              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";     

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -