SOC

ART 비동기 통신 UART_TX (Transmitter) UART_RX (RECEIVER)

전자자연인 2021. 6. 10. 21:54
반응형

1. UART 비동기 통신 이란

 

 UART(Universal Asynchronous Receiver and Transmitter)란 비동기 전이중 1:1통신 방식이다.

 동기통신 PS/2와는 다른 점은 비동기 통신은 최대 입력 전압이 ±15V, 최대 출력 전압이 ±25V로 비교적 높은 전압이다. 그래서 동기통신보다 통신거리가 길고, 최대 통신거리는 15m이다.

 통신속도는 Baud-rate(bau-rate)라 하고, 가변적인 특성을 갖는다.

 UART default 1의 값을 갖으며, START bit(1 bit),Data(8 bit), PARITY(1 bit), STOP(1 bit)  11비트로 전송되고, DATA는 최대 8비트가 기본 단위이다.

 RS-232(가장 많이 쓰임) Tranceiver을 사용하여 TTL(5V)  UART(12V) level로 변환해준다.

 9600bps ~ 921600bps의 속도에서 일반적으로 9600bps,15200bps를 많이 사용하고, 이번 실습에서는 115200bps를 사용한다

 115200bps 한 펄스의 주기는 868055us

 

 

2. UART_TX (Transmitter) VHDL 코드 & 분석 (library 생략)

 

 

entity UART_TX is

port(

nRst : in std_logic;

clk : in std_logic;

start_sig : in std_logic;

data : in std_logic_vector(7 downto 0);

tx : out std_logic;

busy : out std_logic

);

end UART_TX;

 

architecture beh of UART_TX is 

type state_type is (IDLE, START, SEND, PARITY, STOP);

signal state : state_type;

signal cnt : std_logic_vector(8 downto 0);

signal pclk : std_logic;

signal start_d : std_logic;

signal flag : std_logic;

signal temp_data : std_logic_vector(7 downto 0);

signal tx_data : std_logic_vector(7 downto 0);

signal bit_cnt : std_logic_vector(3 downto 0);

 

begin

process(nRst,clk)

begin

if(nRst = '0') then

start_d <= '0';

flag <= '0';

temp_data <= (others => '0');

elsif rising_edge(clk) then

start_d <= start_sig;

if (start_d = '0') and (start_sig = '1') then

flag <= '1';

temp_data <= data;

 elsif (state = START) then

flag <= '0';

end if;

end if;

end process;

 

 process(nRst,clk)

begin

if(nRst = '0') then

cnt <= (others => '0');

pclk <= '0';

 

elsif rising_edge(clk) then

if(cnt = 433) then

cnt <= (others => '0');

pclk <= not pclk;

else

cnt <= cnt + 1;

end if;

end if;

end process;

 

process(nRst,pclk)

begin

if(nRst = '0') then

state <= IDLE;

bit_cnt <= (others =>'0');

tx_data <= (others =>'0') ;

busy <= '1';

elsif rising_edge(pclk) then

case state is

when IDLE =>

if(flag = '1') then

state <= START;

else

state <= IDLE;

end if;

bit_cnt <= (others =>'0');

tx_data <= (others =>'0');

busy <= '1';

when START =>

state <= SEND;

tx_data <= temp_data;

busy <= '0';

when SEND =>

if(bit_cnt = 7) then

bit_cnt <= (others =>'0');

state <= PARITY;

 

else

bit_cnt <= bit_cnt + 1;

tx_data <= '0' & tx_data(7 downto 1);

end if;

when PARITY =>

state <= STOP;

when STOP =>

state <= IDLE;

busy <= '1';

when others =>

end case;

end if;

end process;

 

tx <= tx_data(0) when state = SEND else

'0' when state = START or state = PARITY else

'1';

end beh;

 

3.UART_TX 결과 및 시뮬레이션

 



 

 

 

 

(1) data값에 A7이 입력되면서 start_sig값과 이값으로부터 전달 받은 start_d에 의해 시작신호가 형성되면서 flag값에 1의 값이 나오면서 START상태로 넘어간다.

START상태에선 tx_data값에 data값이 전달되어 임시저장된 temp_data의 값을 전달해주고 SEND상태로 넘어가면서 busy값에 0을 전달해준다

(2) SNEND상태에서 입력받은 A7(1010 0111) 0비트 값 1 tx로 전달되고 다음에 bit_cnt(비트카운트)의 수는 1이된다.

tx_data값에 0비트가 tx로 전달되어 비어있으므로 8비트에 0을 채워놓고 기존 tx_data 7~1비트의 수를 6~0비트로 우측 씩 shfit하여 이 값을 tx_data로 전달 해준다.

 

(3) ~ (8) bit_cnt, 즉 비트수가 7이 될 때 까지, (2)번의 과정을 전달하여 우측부터 A7(1010 0111)의 우측부터 좌측으로 차례차례 tx로 전달하여 준다.

 

(9) bit_cnt의 값이 7 (8비트전달) 이 되었을 때, bit_cnt의 값을 0으로 초기화 해주고 다음 상태인 PARITY상태로 넘어가고 STOP으로 넘어가 초기상태인 IDLE상태로 만들어준다.

 

 

2. UART_RX (RECEIVER) VHDL 코드 & 분석 (library 생략)

 

 

entity UART_RX is

port(

nRst : in std_logic;

clk : in std_logic;

serialin : in std_logic;

rx_data : out std_logic_vector(7 downto 0);

valid : out std_logic

);

end UART_RX;

 

architecture beh of UART_RX is

 

type state_type is ( IDLE, START, RECEIVE, PARITY, STOP);

signal state : state_type;

signal cnt : std_logic_vector(5 downto 0);

signal pclk : std_logic;

signal pcnt : std_logic_vector(2 downto 0);

signal bit_cnt : std_logic_vector (2 downto 0);

signal serialin_d : std_logic;

signal flag : std_logic;

signal xmtdata : std_logic_vector(7 downto 0);

 

begin

 

process(nRst,clk)

begin

if(nRst = '0') then

cnt <= (others =>'0');

pclk<='0';

elsif rising_edge(clk) then

if(cnt=53) then

cnt<=(others => '0');

pclk<=not pclk;

else

cnt<=cnt+1;

end if;

end if;

end process;

 

process(nRst,clk)

begin

if(nRst='0') then

serialin_d<='0';

flag<='0';

elsif rising_edge(clk) then

serialin_d <= serialin;

if state = IDLE then

if(serialin_d = '1') and (serialin='0') then

flag <= '1';

end if;

 

elsif state = START then

flag <= '0' ;

end if;

end if;

end process;

 

process(nRst,pclk)

begin

if(nRst = '0') then

state <= IDLE;

pcnt<= (others => '0');

bit_cnt<= (others => '0');

xmtdata<= (others => '0');

rx_data<= (others => '0');

 elsif rising_edge(pclk) then

case state is

when IDLE=>

if(flag='1') then

state <= START;

else

state <= IDLE;

end if;

pcnt<= (others => '0');

bit_cnt<= (others => '0');

xmtdata<= (others => '0');

rx_data <= (others => '0');

when START =>

if(pcnt = 3 ) then

pcnt <= (others => '0');

state <= RECEIVE;

else

pcnt <= pcnt + 1;

state <= START ;

end if;

when RECEIVE =>

if(pcnt = 7) then

pcnt <=(others =>'0');

xmtdata <= serialin&xmtdata(7 downto 1);

if(bit_cnt = 7 ) then

bit_cnt <= (others => '0');

state <=PARITY;

else

bit_cnt <= bit_cnt + 1;

state <= RECEIVE;

end if;

else

pcnt <= pcnt + 1;

end if;

 

when PARITY =>

if(pcnt=7) then

pcnt<=(others =>'0');

state <= STOP;

else

pcnt<=pcnt+1;

state<=PARITY;

end if;

 

 

when STOP =>

if(pcnt=7) then

pcnt <= (others => '0');

state <= IDLE;

else

pcnt <= pcnt + 1;

state <= STOP;

end if;

rx_data<=xmtdata;

 

when others =>

state<=IDLE;

end case;

end if;

end process;

 

valid <= '1' when (state = STOP and pcnt=7)else '0';

end beh;

 

3.UART_RX 결과 및 시뮬레이션

 



 

(1) serialin serialin_d에 의해 flag값이 1로 결정되고 상태가 START로 넘어간다.

 

(2) START상태에서 flag값을 다시 0으로 만들어주고 RECEIVE로 넘어간다

 

(3) RECEIVE상태에서 serialin에서 1이 들어 왔는데 바로 xmtdata에 전달이 안되고, pcnt 7의값(들어온 data의 중간시기)를 읽으므로 (2)번에서 serialin 1의 값이 (3)번 시점 에서 읽힌다, 처음1이 들어와 1 & xmtdata(7 downto 0)가 되고, xmtdata 0000 0000이므로 1000 0000 (16진수로 80) xmtdata로 전달됨, 1개를 전달받았으니 bit_cnt의 수는 0이다.

 

(4) bit_cnt의 수는7이 아니므로 RECEIVE상태에서 데이터 8비트를 다 안받은상태이다. serialin에서 1이 또 들어왔기 때문에 xmtdata 1 & xmtdata(7 downto 1) => 1 & 100 0000 이 되므로 1100 0000(16진수로 C0) xmtdata에 전달된다. 그리고 bit_cnt의 수는 1이 된다 (비트수2)

 

(5) ~ (9) 3,4번의 과정을 bit_cnt의 수가 7,즉 비트수가 8개가 될 때 까지 반복한다.

 

(10) PARITY상태에서 STOP상태로 넘어가고,

STOP상태에서 최종 xmtdata값은 A7(16진수)가 되고 이값은 rx_data값으로 전달된다. 이 후 다시 모든 값을 0으로 초기화하고 기본상태인 IDLE상태로 된다.

 

 

 

 

반응형