270 likes | 649 Views
UART Controller 구현. Lecture #11. UART - 학습목표. UART 의 기본 동작 특성과 타이밍 특성을 이해한다 UART controller 를 설계한다. UART - 강의순서. UART Data sheet 분석 UART Controller 분석 및 설계. UART Data Sheet 분석 (1).
E N D
UART Controller 구현 Lecture #11
UART - 학습목표 • UART의 기본 동작 특성과 타이밍 특성을 이해한다 • UART controller를 설계한다
UART - 강의순서 • UART Data sheet 분석 • UART Controller 분석 및 설계
UART Data Sheet 분석 (1) • RS-232C 인터페이스는 일반적인 PC와 I/O device와의 직렬 통신을 위한 기본적인 UART (Universal Asynchronous Receiver/Transmitter) 기능을 가진다
UART Data Sheet 분석 (2) • UART의 직렬 전송 모드 • 데이터 비트 수 (7/8 bits) • 정지 비트 수(1/2 bits) • 패리티 종류 및 사용 여부(No/Even/Odd bit) • Baud Rate(1200, 4800, 9600, … bps) • 송수신이 각각 독립적으로 행해지는 Full-duplex 전송 방식을 지원한다
UART Data Sheet 분석 (3) • UART Controller - main features : • 8 bytes RX FIFO & 8 bytes TX FIFO • 12 bits Baud-rate generator • System clock
UART Controller 블록도
UART Data Sheet 분석 (4) • Data Transmission • Start bit • Data bit ( 7/8 bit) • Parity bit ( No/Even/ Odd bit ) • Stop bit ( 1/2 bit ) • TX Register -> FIFO -> Shift Register -> Serial Output
UART Data Sheet 분석 (5) • Data Reception • Start bit • Data bit ( 7/8 bit) • Parity bit ( No/Even/ Odd bit ) • Stop bit ( 1/2 bit ) • Serial Input -> Shift Register -> FIFO -> RX Register
UART Data Sheet 분석 (6) • Baud Rate Generation • TX Block : Use Baud Rate Clock • RX Block : Use 16/32 Baud Rate Clock • Baud Rate Clock : BR = Clock/ ( 16 * ( N+1) )
UART Data Sheet 분석 (7) • UART Control Register
UART Data Sheet 분석 (8) • UART Status Register(1)
UART Data Sheet 분석 (9) • UART Status Register(2)
UART Data Sheet 분석 (10) • UART Transmit Buffer Register • UART Receive Buffer Register
UART Data Sheet 분석 (11) • UART Baud Rate Divisor Register • UART Baud Rate Table
UART Controller 분석 및 설계 (UART Top) library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity uart is port( clock : in std_logic; rx_sdata : in std_logic; tx_sdata : out std_logic; rx_pdata : out std_logic_vector(7 downto 0); tx_pdata : in std_logic_vector(7 downto 0); rx_full, tx_empty : out std_logic; load : in std_logic; read : in std_logic; baud : in std_logic_vector(2 downto 0)); end uart; architecture behavioral of uart is signal rxclk : std_logic := '0'; signal txclk : std_logic := '0'; begin clock_gen : entity work.baudgen port map( clk_in => clock, baudsel => baud, rxclk_out => rxclk, txclk_out => txclk); rx_block : entity work.rs232_rx port map( clk => rxclk, din => rx_sdata, dataready => rx_full, read => read, dout => rx_pdata); tx_block : entity work.rs232_tx port map( clk => txclk, load => load, din => tx_pdata, dout => tx_sdata, empty => tx_empty); end behavioral;
UART Controller 분석 및 설계 (Baud Rate Generator -1) library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity baudgen is port( clk_in : in std_logic; --input clock baudsel : in std_logic_vector(2 downto 0); --baud clock select rxclk_out : out std_logic; --divided clock output, 4*baudrate txclk_out : out std_logic); --baud clock output end baudgen ; architecture behavioral of baudgen is constant FCLK : integer := 50000000; constant CLKSCALE : integer := 16; constant max_rx : integer := ((FCLK/9600)/2)/CLKSCALE; constant max_tx : integer := (FCLK/9600)/2; signal rx_count : integer range 0 to max_rx; signal tx_count : integer range 0 to max_tx; signal rxclk : std_logic := '0'; signal txclk : std_logic := '0';
UART Controller 분석 및 설계 (Baud Rate Generator -2) begin process (baudsel) begin case baudsel is when "000" => rx_count <= ((FCLK/9600)/2)/CLKSCALE; tx_count <= (FCLK/9600)/2; when "001" => rx_count <= ((FCLK/19200)/2)/CLKSCALE; tx_count <= (FCLK/19200)/2; when "010" => rx_count <= ((FCLK/38400)/2)/CLKSCALE; tx_count <= (FCLK/38400)/2; when "011" => rx_count <= ((FCLK/57600)/2)/CLKSCALE; tx_count <= (FCLK/57600)/2; when "111" => rx_count <= 2; tx_count <= 2 * CLKSCALE; when others => rx_count <= ((FCLK/115200)/2)/CLKSCALE; tx_count <= (FCLK/115200)/2; end case; end process;
UART Controller 분석 및 설계 (Baud Rate Generator -3) process (clk_in) variable count1 : integer range 0 to max_rx := 0; variable count2 : integer range 0 to max_tx := 0; begin if rising_edge(clk_in) then count1 := count1 + 1; count2 := count2 + 1; if count1 >= rx_count then rxclk <= not rxclk; count1 := 0; end if; if count2 >= tx_count then txclk <= not txclk; count2 := 0; end if; end if; end process; rxclk_out <= rxclk; txclk_out <= txclk; end behavioral;
UART Controller 분석 및 설계 (Transmit Component -1) library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity rs232_tx is port( clk : in std_logic; -- clock, should be at the baud rate load : in std_logic; -- tells us we have data to serialize din : in std_logic_vector(7 downto 0); --parallel input dout : out std_logic; -- serial output empty : out std_logic); -- indicate we are ready more data end rs232_tx; architecture behavioral of rs232_tx is constant MAXCNT : integer := 10; constant startbit : std_logic := '0'; constant stopbit : std_logic := '1'; signal data : std_logic_vector(MAXCNT - 1 downto 0) := (others => stopbit); signal cnt : integer range 0 to MAXCNT := MAXCNT; signal latched : std_logic := '0'; signal latch : std_logic_vector(7 downto 0);
UART Controller 분석 및 설계 (Transmit Component -2) begin dout <= data(0); empty <= '1' when latched = '0' and cnt = MAXCNT else '0'; process (load, cnt) variable flag : std_logic := '0'; begin -- load new data on edge if rising_edge(load) then flag := '1'; latch <= din; end if; if cnt = 0 then flag := '0'; end if; latched <= flag; end process;
UART Controller 분석 및 설계 (Transmit Component -3) process (clk) begin if rising_edge(clk) then if (cnt >= MAXCNT) then if latched = '1' then data <= stopbit & latch & startbit; cnt <= 0; end if; else cnt <= cnt + 1; data (MAXCNT - 2 downto 0) <= data (MAXCNT - 1 downto 1); end if; end if; end process; end behavioral;
UART Controller 분석 및 설계 (Receive Component -1) library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity rs232_rx is port( clk : in std_logic; -- clock, should be CLK_SCALE times faster than baud rate din : in std_logic; -- serial input dataready : out std_logic; -- indicates when dout is valid read : in std_logic; -- pulsed when data has been read dout : out std_logic_vector(7 downto 0)); -- parallel output data end rs232_rx; architecture behavioral of rs232_rx is constant MAXCOUNT : integer := 8; constant CLK_SCALE : integer := 16; constant SYNC_VAL : integer := CLK_SCALE/2; type rx_states is (idle, synchronize, receive,stopping); signal rx_state : rx_states; signal data : std_logic_vector(7 downto 0);
UART Controller 분석 및 설계 (Receive Component -2) begin process (clk, read) variable bit_cnt : integer range 0 to MAXCOUNT; variable sync_cnt : integer range 0 to CLK_SCALE; begin if rising_edge(clk) then case rx_state is when idle => if din = '0' then -- we are receiving a start bit bit_cnt := 0; sync_cnt := 0; rx_state <= synchronize; end if; when synchronize => sync_cnt := sync_cnt + 1; if sync_cnt = SYNC_VAL then -- halfway into the start bit, now synchronized sync_cnt := 0; if din = '0' then rx_state <= receive; -- good start bit else rx_state <= idle; -- bad start bit end if; end if;
UART Controller 분석 및 설계 (Receive Component -3) when receive => sync_cnt := sync_cnt + 1; -- don't want to sample until we are in the middle of the next bit if sync_cnt = CLK_SCALE then sync_cnt := 0; bit_cnt := bit_cnt + 1; data <= din & data(7 downto 1); if bit_cnt = MAXCOUNT then rx_state <= stopping; end if; end if; when stopping => sync_cnt := sync_cnt + 1; -- don't want to finish until we are in the middle of the stop bit if sync_cnt = CLK_SCALE then dataready <= din; rx_state <= idle; end if; end case; end if;
UART Controller 분석 및 설계 (Receive Component -4) if read = '1' then dataready <= '0'; end if; end process; dout <= data; end behavioral;