• 方案介绍
  • 附件下载
  • 相关推荐
申请入驻 产业图谱

通用UART串口收发RS232接口VHDL代码Quartus仿真

06/13 10:38
757
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

2-2312291101544K.doc

共1个文件

名称:通用UART串口收发RS232接口VHDL代码Quartus仿真

软件:Quartus

语言:VHDL

代码功能:

通用UART串口收发RS232接口

1、具有串口发送和接收功能。

2、波特率、数据位长度、停止位长度、校验位长度、校验位奇偶可设置。

默认为:115200波特率,数据位长度8bit,停止位长度1bit,校验位1bit,奇校验。

波特率、数据位长度、停止位长度、校验位长度、校验位奇偶可通过以下代码设置:

uart_baudrate<="11100001000000000";--115200

uart_data_len   <= "1000";--8bit--输入数据位长度

uart_stop_len   <= "01"  ;--输入停止位长度

uart_check_len  <= '1'   ;--输入校验位长度

uart_check_mode <= '0'   ;--输入校验位奇偶

FPGA代码Verilog/VHDL代码资源下载:www.hdlcode.com

演示视频:

设计文档:

1. 工程文件

2. 程序文件

3. 程序编译

4. RTL图

5. 管脚分配

6. Testbench

7. 仿真图

整体仿真

波特率产生模块

发送模块

接收模块

部分代码展示:

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 (
      clk                  : IN STD_LOGIC;
      rst_n                : IN STD_LOGIC;
      
      data_len             : IN STD_LOGIC_VECTOR(3 DOWNTO 0);--数据长度-- 5~8
      stop_len             : IN STD_LOGIC_VECTOR(1 DOWNTO 0);--停止位长度-- 1~2
      check_len            : IN STD_LOGIC;--校验位长度-- 0~1
      check_mode           : IN STD_LOGIC;--奇偶-- 0~1
      
      baud16_tick          : IN STD_LOGIC;
      
      uart_rx_buf_wr_en    : OUT STD_LOGIC;--接收使能
      uart_rx_buf_wr_data  : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--接收数据
      
      uart_rx_err          : OUT STD_LOGIC;
      
      uart_rxd             : IN STD_LOGIC
   );
END uart_rx;
ARCHITECTURE trans OF uart_rx IS
   
--   SIGNAL uart_rxd_sync_r           : STD_LOGIC_VECTOR(2 DOWNTO 0);
   
   SIGNAL uart_rxd_bit_inv          : STD_LOGIC;
   
   SIGNAL Bau16_Tick_shift_r        : STD_LOGIC_VECTOR(1 DOWNTO 0);
   SIGNAL Bau16_Tick_rising         : STD_LOGIC;
   
   SIGNAL state                     : STD_LOGIC_VECTOR(3 DOWNTO 0);
   SIGNAL next_state                : STD_LOGIC_VECTOR(3 DOWNTO 0);
   SIGNAL cnt_baud16_tick           : STD_LOGIC_VECTOR(3 DOWNTO 0);
   SIGNAL cnt_rx_bit                : STD_LOGIC_VECTOR(3 DOWNTO 0);
   
   SIGNAL rx_shift_reg              : STD_LOGIC_VECTOR(8 DOWNTO 0);
   
   SIGNAL rx_check_sum              : STD_LOGIC;
   SIGNAL local_check_sum           : STD_LOGIC;
   SIGNAL uart_rx_buf_wr_data_buf : STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
   -- Drive referenced outputs
   uart_rx_buf_wr_data <= uart_rx_buf_wr_data_buf;--输出接收数据
--   PROCESS (clk)
--   BEGIN
--      IF (clk'EVENT AND clk = '1') THEN
--         uart_rxd_sync_r <= (uart_rxd_sync_r(1 DOWNTO 0) & uart_rxd);--移位
--      END IF;
--   END PROCESS;
   
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         uart_rxd_bit_inv <= uart_rxd;--同步到时钟下
      END IF;
   END PROCESS;
   
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         Bau16_Tick_shift_r <= (Bau16_Tick_shift_r(0) & baud16_tick);
      END IF;
   END PROCESS;
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         if(Bau16_Tick_shift_r = "01")then--检测Bau16_Tick_shift_r上升沿
Bau16_Tick_rising<='1';--上升沿
else
Bau16_Tick_rising<='0';
end if;
      END IF;
   END PROCESS;
   
--状态机
   PROCESS (clk, rst_n)
   BEGIN
      IF ((NOT(rst_n)) = '1') THEN
         state <= "0000";
      ELSIF (clk'EVENT AND clk = '1') THEN
         state <= next_state;
      END IF;
   END PROCESS;
   
   PROCESS (state, uart_rxd_bit_inv, Bau16_Tick_rising, cnt_baud16_tick, data_len, check_len)
   BEGIN
      CASE state IS
         WHEN "0000" =>-- IDLE
            IF ((NOT(uart_rxd_bit_inv)) = '1') THEN
               next_state <= "0001";
            ELSE
               next_state <= state;
            END IF;
         WHEN "0001" =>-- Start
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "1000";
            ELSE
               next_state <= state;
            END IF;
         WHEN "1000" => -- Bit 0
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "1001";
            ELSE
               next_state <= state;
            END IF;
         WHEN "1001" =>-- Bit 1
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "1010";
            ELSE
               next_state <= state;
            END IF;
         WHEN "1010" =>-- Bit 2
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "1011";
            ELSE
               next_state <= state;
            END IF;
         WHEN "1011" =>-- Bit 3
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               IF (data_len > "0101") THEN
                  next_state <= "1100";
               ELSE
                  next_state <= "1111";
               END IF;
            ELSE
               next_state <= state;
            END IF;
         WHEN "1100" =>-- Bit 4
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               IF (data_len > "0110") THEN
                  next_state <= "1101";
               ELSE
                  next_state <= "1111";
               END IF;
            ELSE
               next_state <= state;
            END IF;
         WHEN "1101" =>-- Bit 5
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               IF (data_len > "0111") THEN
                  next_state <= "1110";
               ELSE
                  next_state <= "1111";
               END IF;
            ELSE
               next_state <= state;
            END IF;
         WHEN "1110" =>-- Bit 6
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "1111";
            ELSE
               next_state <= state;
            END IF;
         WHEN "1111" =>-- Bit Last
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               IF (check_len > '0') THEN
                  next_state <= "0111";
               ELSE
                  next_state <= "0110";
               END IF;
            ELSE
               next_state <= state;
            END IF;
         WHEN "0111" =>-- Check
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "0110";
            ELSE
               next_state <= state;
            END IF;
         WHEN "0110" =>-- Stop 1
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               next_state <= "0000";
            ELSE
               next_state <= state;
            END IF;
         WHEN OTHERS =>
            next_state <= "0000";
      END CASE;
   END PROCESS;
   
-- count baud16_tick to check the center of uart_rxd
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (state = "0000") THEN
            cnt_baud16_tick <= "0000";
         ELSIF (state > "0000" AND Bau16_Tick_rising = '1') THEN
            cnt_baud16_tick <= cnt_baud16_tick + "0001";
         ELSE
            cnt_baud16_tick <= cnt_baud16_tick;
         END IF;
      END IF;
   END PROCESS;
   
-- count rx bit
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (state > "0110") THEN
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1110") THEN
               cnt_rx_bit <= cnt_rx_bit + "0001";
            ELSE
               cnt_rx_bit <= cnt_rx_bit;
            END IF;
         ELSIF (state <= "0110" AND state > "0000") THEN
            cnt_rx_bit <= cnt_rx_bit;
         ELSE
            cnt_rx_bit <= "0000";
         END IF;
      END IF;
   END PROCESS;
   
--rx shift register
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (state > "0110") THEN
            IF (Bau16_Tick_rising = '1' AND cnt_baud16_tick = "0111") THEN
               IF (cnt_rx_bit < data_len) THEN
                  rx_shift_reg(Conv_Integer(cnt_rx_bit)) <= uart_rxd_bit_inv;
               ELSE
                  rx_shift_reg(8) <= uart_rxd_bit_inv;
               END IF;
            ELSE
               rx_shift_reg <= rx_shift_reg;
            END IF;
         ELSIF (state <= "0110" AND state > "0000") THEN
            rx_shift_reg <= rx_shift_reg;
         ELSE
            rx_shift_reg <= "000000000";
         END IF;
      END IF;
   END PROCESS;
   
   --rx data checksum
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (check_len > '0') THEN
            rx_check_sum <= rx_shift_reg(8);
            local_check_sum <= rx_shift_reg(7) xor rx_shift_reg(6) xor rx_shift_reg(5) xor rx_shift_reg(4) xor rx_shift_reg(3) xor rx_shift_reg(2) xor rx_shift_reg(1) xor rx_shift_reg(0) xor check_mode;
         ELSE
            rx_check_sum <= '0';
            local_check_sum <= '0';
         END IF;
      END IF;
   END PROCESS;
   
   --output uart rx data
   PROCESS (clk, rst_n)
   BEGIN
      IF ((NOT(rst_n)) = '1') THEN
         uart_rx_buf_wr_data_buf <= "00000000";
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (state = "0110" AND cnt_baud16_tick = "1010") THEN
            uart_rx_buf_wr_data_buf <= rx_shift_reg(7 DOWNTO 0);
         ELSE
            uart_rx_buf_wr_data_buf <= uart_rx_buf_wr_data_buf;
         END IF;
      END IF;
   END PROCESS;
   
   --数据有效指示
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (state = "0110" AND Bau16_Tick_rising = '1' AND cnt_baud16_tick = "1011") THEN
            uart_rx_buf_wr_en <= '1';
         ELSE
            uart_rx_buf_wr_en <= '0';
         END IF;
      END IF;
   END PROCESS;
   
   --校验错误
   PROCESS (clk, rst_n)
   BEGIN
      IF ((NOT(rst_n)) = '1') THEN
         uart_rx_err <= '0';
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (state = "0110" AND cnt_baud16_tick = "1010") THEN
            IF (local_check_sum = rx_check_sum) THEN
               uart_rx_err <= '0';
            ELSE
               uart_rx_err <= '1';
            END IF;
         END IF;
      END IF;
   END PROCESS;
   
   
END trans;

点击链接获取代码文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=447

  • 2-2312291101544K.doc
    下载

相关推荐