名称:通用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
757