VHDL语言UART代码

VHDL语言UART代码,第1张

UART通信

library IEEE

use IEEE.STD_LOGIC_1164.ALL

use IEEE.STD_LOGIC_ARITH.ALL

use IEEE.STD_LOGIC_UNSIGNED.ALL

entity UART is--通用异步串行收发器实体

Port ( UART_clk : in STD_LOGIC --收发器时钟输入,50MHz

UART_rst : in std_logic

UART_TX_buf : in STD_LOGIC_VECTOR(7 downto 0)

UART_TX_TI : out std_logic

UART_TX_EN : in std_logic

UART_TXD : out std_logic

UART_baudrate : out STD_LOGIC) --收发器波特率输出19200的14倍频(测试完成后可以取消)

end UART

architecture Behavioral of UART is

signal baudrate_counter :std_logic_vector(6 downto 0):="0000000" --波特率发生器分频计数器

signal baudrate_out :std_logic:='0' --波特率发生器波特率信号

signal TX_clk : std_logic:='0'

signal tx_clk_counter : std_logic_vector(3 downto 0) :="0000"

type TX_STATE is (TX_idle,TX_transfer)

signal TX_current_state,TX_next_state : Tx_state

signal TX_buf_shift : std_logic_vector(9 downto 0):= "0111111111"

signal TX_counter :std_logic_vector(3 downto 0):="0000"

signal TX_start : std_logic:='0'

signal TXD_buf: std_logic:='0'

signal TX_TI : std_logic:='1'

begin

baudrate: process (UART_clk) --波特率发生器进程

begin

if rising_edge(UART_clk) then --对输入时钟进行分频获得所需波特率的14倍频

if (baudrate_counter >= "1011100") then

baudrate_counter <= "0000000"

baudrate_out <= not baudrate_out

else

baudrate_counter <= baudrate_counter + '1'

baudrate_out <= baudrate_out

end if

end if

end process

UART_baudrate <= baudrate_out --将波特率信号传给输出接口

sync_proc_tx: process(baudrate_out,UART_rst)--同步进程,状态机转换

begin

if (UART_rst = '1') then

tx_current_state <= tx_idle

elsif (falling_edge(baudrate_out)) then

tx_current_state <= TX_next_state

end if

end process

comb_proc_tx: process(baudrate_out,UART_rst)--组合逻辑,状态机转换、输出

begin

if (UART_rst = '1') then

TX_next_state <= TX_idle

TX_counter <= "0000"

TXD_buf <= '1'

TX_start <= '0'

TX_TI <= '1'

TX_clk_counter <= "0000"

TX_buf_shift <= "1111111111"

elsif (rising_edge(baudrate_out)) then

case TX_current_state is

when TX_idle =>

if (UART_TX_EN = '1' and TX_TI = '1') then --如果满足发送起始条件

TX_next_state <= TX_transfer --转换下一状态到发送

TX_counter <= "1010"--发送bit计数器置数,发送10个bit,8bit数据加上开始结束位

TXD_buf <= '1' --发送寄存器发送‘1’

TX_start <= '1'--发送过程标志

TX_TI <= '0' --发送进行中标志,表示发送器不可用

TX_clk_counter <= "1101" --分频计数器置数

TX_buf_shift <= '1' &UART_TX_buf &'0'--寄存器保存数据与开始结束位

else

TX_next_state <= TX_idle

TX_counter <= "0000"

TXD_buf <= '1'

TX_start <= '0'

TX_TI <= '1'

TX_clk_counter <= "0000"

TX_buf_shift <= "1111111111"

end if

when TX_transfer =>

if (TX_start = '1' and TX_TI = '0' and TX_counter /= "0000") then --进入正常发送状态

if (TX_clk_counter >= "1101") then--如果分频完成

TX_next_state <= TX_transfer --没有发送完成,继续进入发送状态

TX_counter <= TX_counter - '1' --发送bit计数器自减

TXD_buf <= TX_buf_shift(0) --发送数据

TX_start <= '1'--发送过程标志继续允许

TX_TI <= '0'--发送器不允许使用

TX_clk_counter <= "0000" --分频计数器清灵,继续下一次

TX_buf_shift <= '1' &TX_buf_shift(9 downto 1) --数据移位

else

TX_next_state <= TX_transfer

TX_counter <= TX_counter

TXD_buf <= TXD_buf

TX_start <= '1'

TX_TI <= '0'

TX_clk_counter <= TX_clk_counter + '1'

TX_buf_shift <= TX_buf_shift

end if

else

TX_next_state <= TX_idle

TX_counter <= "0000"

TXD_buf <= '1'

TX_start <= '0'

TX_TI <= '1'

TX_clk_counter <= "0000"

TX_buf_shift <= "1111111111"

end if

when others =>

TX_next_state <= TX_idle

TX_counter <= "0000"

TXD_buf <= '1'

TX_start <= '0'

TX_TI <= '1'

TX_clk_counter <= "0000"

TX_buf_shift <= "1111111111"

end case

end if

end process

UART_TXD <= TXD_buf

UART_TX_TI <= TX_TI

end Behavioral

library ieee

use ieee.std_logic_1164.all

use ieee.std_logic_arith.all

use ieee.std_logic_unsigned.all

entity transmitter is

port(cs,clk,rx:in std_logic

indata:in std_logic_vector(7 downto 0)

txd,ti:out std_logic)

end transmitter

architecture tr1 of transmitter is

signal sig_count:std_logic_vector(3 downto 0)

signal sig_ti,sig_ti1,sig_txd,sig_buffer:std_logic

signal sig_data:std_logic_vector(7 downto 0)

signal sig_txddata:std_logic_vector(9 downto 0)

begin

process(cs,clk,rx)

begin

if(clk'event and clk='1')then

if(cs='0')then

if(sig_buffer='0')then

if(rx='0')then

for i in 8 downto 1 loop

sig_txddata(i)<=indata(i-1)

end loop

sig_txddata(9)<='0'--加起始位

sig_data<=indata

sig_buffer<='1'

end if

else

for i in 9 downto 1 loop

sig_txddata(i)<=sig_txddata(i-1)

end loop

sig_txd<=sig_txddata(9)

sig_txddata(0)<='1'--加停止位

if(sig_count="1000")then

sig_count<="0000"

elsif(sig_count="0000"and sig_ti='1')then

sig_buffer<='0'

sig_ti<='0'

else

sig_count<=sig_count+'1'

sig_ti<='1'

end if

end if

end if

end if

end process

process

begin

if(sig_ti='0')then

txd<='1'

else txd<=sig_txd

end if

end process

ti<=not sig_ti

end tr1

RXD作高电平就可以了,如果你不想接收数据,可以不用去管它。

因为RS232通信是半双工,即 RXD,TXD,CLK 三线控制,其中时钟频率由传输的波特率决定,接收和发送的波特率需要设置,FPGA是自己编程时加个时钟发生器来控制TXD的频率,接收的 如PC,可由串口软件设置。只要频率匹配,从机(FPFA)TXD的信号就可以按照协议发送过去,而在主机(PC)上RXD上就接收到了数据。

理论上误码率很低,所以用RXD接收PC机发回的反馈信号,比如奇偶校验,比如一个低电平,但也可以在PC机上接收多次或者自己写协议,对接收到的数据处理,毕竟没有反馈就不知道错误与否。

程序你对着RS232的时序自己写下就可以了,你看懂了就很简单,因为关键的时序在FPGA里很容易实现。

程序方面的传输方面,你可以设置一个数据寄存器 比如 8位,用来放要发送的内容,然后 低位(或者高位,忘记了)一位一位传,传完一个移一位就可以了

一般数据传输的开始信号为低电平,结束为高电平,空闲为高电平。

因为鄙人编程是C的,在ARM上,VHDL也忘差不多了,只能告诉你大概原理。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12102307.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存