通用可调UART串口通信协议VHDL代码Quartus仿真

名称:通用可调UART串口通信协议VHDL代码Quartus仿真(文末获取)

软件:Quartus

语言:VHDL

代码功能:

通用可调UART串口通信协议

1、可以调整波特率

2、可以调整数据位长度

3、可以调整停止位长度

4、可以调整校验位长度

5、可以设置奇偶校验

6、支持串口发送和接收

7、具有VHDL和Verilog两个独立工程文件

1. 工程文件(以VHDL工程为例)

2. 程序文件

3. 程序编译

4. RTL图

5. Testbench

6. 仿真图

整体仿真

波特率产生模块

发送模块

接收模块

部分代码展示:

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;
源代码

 扫描文章末尾的公众号二维码

  • 20
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 VHDL 代码实现 UART: ``` entity UART is Port ( CLK : in std_logic; RST : in std_logic; TX : out std_logic; RX : in std_logic); end UART; architecture Behavioral of UART is signal TX_shift_reg : std_logic_vector(9 downto 0); signal TX_busy : std_logic := '0'; signal TX_data : std_logic_vector(7 downto 0); signal TX_counter : integer range 0 to 11 := 0; signal RX_shift_reg : std_logic_vector(9 downto 0); signal RX_busy : std_logic := '0'; signal RX_data : std_logic_vector(7 downto 0); signal RX_counter : integer range 0 to 11 := 0; constant BAUD_RATE : integer := 9600; constant CLK_FREQ : integer := 50000000; -- 50 MHz clock begin UART_TX : process(CLK, RST) begin if(RST = '1') then TX_shift_reg <= (others => '1'); TX_busy <= '0'; TX_counter <= 0; elsif(CLK'event and CLK = '1') then if(TX_busy = '1') then TX_counter <= TX_counter + 1; if(TX_counter = 11) then TX_shift_reg <= TX_shift_reg(TX_shift_reg'high - 1 downto 0) & '1'; TX_busy <= '0'; TX_counter <= 0; end if; else if(TX_shift_reg(TX_shift_reg'high) = '0') then TX <= '0'; TX_busy <= '1'; TX_counter <= 0; else TX <= '1'; end if; end if; end if; end process UART_TX; UART_RX : process(CLK, RST) begin if(RST = '1') then RX_shift_reg <= (others => '1'); RX_busy <= '0'; RX_counter <= 0; elsif(CLK'event and CLK = '1') then if(RX_busy = '1') then RX_counter <= RX_counter + 1; if(RX_counter = 11) then RX_data <= RX_shift_reg(RX_shift_reg'high - 2 downto RX_shift_reg'low); RX_shift_reg <= (others => '1'); RX_busy <= '0'; RX_counter <= 0; end if; else RX_shift_reg <= RX_shift_reg(RX_shift_reg'high - 1 downto 0) & RX; if(RX_shift_reg(RX_shift_reg'high - 1 downto RX_shift_reg'high - 10) = "0101010101") then RX_busy <= '1'; RX_counter <= 0; end if; end if; end if; end process UART_RX; -- Baud rate generator UART_BAUD : process(CLK, RST) begin if(RST = '1') then TX_shift_reg(TX_shift_reg'high) <= '1'; elsif(CLK'event and CLK = '1') then TX_shift_reg(TX_shift_reg'high) <= not TX_shift_reg(TX_shift_reg'high); end if; end process UART_BAUD; end Behavioral; ``` 这个实现包括了一个简单的波特率生成器和 TX 和 RX 的状态机。该实现使用9600波特率,50 MHz时钟频率和8个数据位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值