Tải bản đầy đủ (.doc) (26 trang)

Thiết kế bộ truyền nhận UART

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (433.2 KB, 26 trang )

BÁO CÁO
BÀI TẬP CHUYÊN ĐỀ (KTĐT)
Đề tài: Thiết kế bộ truyền nhận UART
GVHD: Huỳnh Việt Thắng
Nhóm: 7

24


1. Kiến thức cơ bản về UART:
- UART (Universal Asynchronous Receiver Transmitter) gọi là bộ thu phát dữ
liệu không đồng bộ nối tiếp. UART được sử dụng phổ biến để giao tiếp giữa các thiết
bị khác nhau.
- UART có nhiệm vụ chuyển đổi 1 byte (8 bit) dữ liệu từ song song sang nối tiếp
và thêm vào các bit start, stop để tạo thành khung truyền truyền đi.
- Bộ phát UART được điều khiển việc truyền tải dữ liệu bằng một xung clock gọi
là tốc độ baud.

Hình 1: Khung truyền UART
-

Dữ liệu được gởi đi không đồng bộ xung clock nên giữa bộ truyền và bộ nhận
cần có một sự thống nhất với nhau. Vì vậy, khi bộ truyền truyền một khung dữ liệu
(frame), bộ nhận sẽ lấy mẫu các tín hiệu đó và sau đó tập hợp và khôi phục lại tín hiệu
gốc.
- Cơ chế này được minh họa ở hình 2, một bit thông tin được chia thành 16 điểm
lấy mẫu. Vì xác suất lỗi ở vị trí mẫu đầu và mẫu cuối là cao nhất còn xác suất lỗi ở vị
trí giữa là thấp nhất nên ta chọn điểm lấy mẫu ở giữa.

Hình 2: Cơ chế lấy mẫu nhận dữ liệu


24


 Từ những kiến thức ở trên và yêu cầu của đề bài, ta thiết kế một bộ vừa truyền
vừa nhận UART, hiển thị ngay ra giá trị vừa truyền đi.
2. Thiết kế:
2.1. Sơ đồ khối của thiết kế:

Hình 3: Sơ đồ khối của thiết kế
-

Trong đó:


Khối điều khiển CONTROL: tiếp nhận tín hiệu điều khiển tx_in để tạo
tín hiệu cho phép khối truyền UART hoạt động. Đồng thời nhận các giá trị dữ liệu từ
rev_data để hiển thị ra led đơn.

Khối tạo tốc độ truyền BAUD_RATE: dựa vào tần số clock của hệ
thống, khối này sẽ tính toán và tạo xung nhịp truyền dữ liệu khi truyền và lấy mẫu dữ
liệu khi nhận.

Khối truyền nối tiếp UART_TRANSMITTER: nhận dữ liệu từ ngõ vào
data_in và phát đi dựa trên tốc độ baud đã được tính toán trong khối BAUD_RATE.

Khối nhận nối tiếp UART_RECEIVER: phát hiện, lấy mẫu và lưu trữ dữ
liệu nhận nối tiếp từ chân uart_rx với tốc độ baud đã được tính toán ở khối
BAUD_RATE.

24



2.2. Máy trạng thái hữu hạn:
-

Máy trạng thái hữu hạn của bộ truyền:
reset=’0’ or uart_en=0’

Idle
Idle
tx_enable=’1’

tx_count=”1001”
and tx_clken

Load_tx
s

Shift_data

Hình 4: Máy trạng thái hữu hạn của bộ truyền
-

Trong đó:
• reset: tín hiệu reset hệ thống.
• uart_en: tín hiệu cho phép hệ thống làm việc.
• tx_enable: tín hiệu cho phép bộ truyền làm việc.
• tx_count: tín hiệu đếm số bit được truyền đi.
• tx_clken: xung cho phép dịch từng bit dữ liệu khi bộ truyền hoạt động.


Trạng thái hiện tại Mô tả

Điều kiện

Trạng thái kế tiếp

Idle

Trạng thái ban đầu khi bộ tx_enable
truyền không hoạt động

Load_txs

Load_txs

Trạng thái nạp dữ liệu
vào thanh ghi dịch truyền

Shift_data

Shift_data

Trạng thái truyền từng bit tx_count=”1001” Idle
và tx_clken
dữ liệu
24


-


Máy trạng thái hữu hạn của bộ nhận:
reset=’0’ or uart_en=’0’
Idle
uart_rx_sync=’0’

rx_count=”1010”
uart_rx_sync=’1’
and samp_count=”0111”

Check_start_
Receive_dat
bit
a
uart_rx_sync=’0’ and samp_count=”0111”
Hình 5: Máy trạng thái hữu hạn của bộ nhận
-

Trong đó:
• Reset: tín hiệu reset hệ thống.
• Uart_en: tín hiệu cho phép hệ thống làm việc.
• Uart_rx_sync: tín hiệu lấy mẫu đọc được.
• Samp_count: tín hiệu đếm số lần lấy mẫu trong từng xung vào.
• Rx_count: tín hiệu đếm xung vào.

Trạng thái hiện tại Mô tả

Điều kiện

Trạng thái kế tiếp


Idle

uart_rx_sync=’0’

Check_start_bit

Check_start_bit

Trạng thái ban đầu khi
bộ nhận không hoạt
động
Trạng thái lấy mẫu và

samp_count=”0111”

Idle
24


kiểm tra bit start

và uart_rx_sync=’1’
samp_count=”0111”

Receive_data

và uart_rx_sync=’0’
Receive_data

Trạng thái lấy mẫu các

bit dữ liệu trên đường
nhận

rx_count=”1010”

Idle

3. Chương trình chính:
3.1. Code VHDL:
-

Khối BAUD_RATE

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

24



entity baud_rate is
port (
clk : in std_logic;

-- clock dong bo he thong

reset : in std_logic; -- reset he thong. Tich cuc muc thap
uart_en : in std_logic;
Tich cuc muc cao

-- cho phep he thong lam viec.

tx_clken : out std_logic;
du lieu khi bo truyen hoat dong

-- xung cho phep dich tung bit

rx_clken : out std_logic
tri lay mau du lieu o bo nhan

-- xung cho phep xac dinh vi

);
end baud_rate;

architecture Behavioral of baud_rate is
signal tx_count: std_logic_vector(13 downto 0);
signal rx_count: std_logic_vector(9 downto 0);
signal tx_clken_temp: std_logic;
signal rx_clken_temp: std_logic;

constant temp: integer:=324;
MHz

-- 9600=fo/((324+1)*16 - 1), fo=50

begin
process(clk)
-- tao xung dich du lieu o bo phat
begin
if rising_edge(clk) then
if ((reset='0') or (tx_clken_temp='1') or (uart_en='0'))
then
tx_count <= (others => '0');
else

24


tx_count <= (tx_count + 1);
end if;
end if;
end process;

process (tx_count, tx_clken_temp)
begin
if (tx_count = (((temp + 1)*16) - 1)) then
tx_clken_temp <= '1';
else
tx_clken_temp <= '0';
end if;

tx_clken <= tx_clken_temp;
end process;

process(clk)
-- tao xung lay mau du lieu o bo nhan
begin
if rising_edge(clk) then
if ((reset='0') or (rx_clken_temp='1') or (uart_en='0'))
then
rx_count <= (others => '0');
else
rx_count <= (rx_count + 1);
end if;
end if;
end process;

24


process (rx_count, rx_clken_temp)
begin
if (rx_count = temp) then
rx_clken_temp <= '1';
else
rx_clken_temp <= '0';
end if;
rx_clken <= rx_clken_temp;
end process;
end Behavioral;


-

Khối CONTROL

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

24


entity control is
port(
clk : in std_logic;

-- clock dong bo he thong

reset : in std_logic; -- reset he thong. Tich cuc muc thap
uart_en : in std_logic;
Tich cuc muc cao


-- cho phep he thong lam viec.

tx_in : in std_logic; -- cho phep ghi du lieu tu data_in
vao bo truyen. Tich cuc muc cao
nhan duoc

rev_data : in std_logic_vector(7 downto 0); -- du lieu

led_0 : out std_logic_vector(3 downto 0);
nhan duoc xuat ra led don

-- gia tri

led_1 : out std_logic_vector(3 downto 0);
nhan duoc xuat ra led don

-- gia tri

dong

tx_en : out std_logic -- tin hieu cho phep bo truyen hoat
);

end control;

architecture Behavioral of control is
-- khai bao cac tin hieu
signal data_led_0: std_logic_vector(3 downto 0);
signal data_led_1: std_logic_vector(3 downto 0);

signal tx_in_sync: std_logic;
begin
process (rev_data)
-- gan gia tri cho led don
begin
data_led_0 <= rev_data(3 downto 0);
data_led_1 <= rev_data(7 downto 4);

24


end process;
led_0 <= data_led_0;
led_1 <= data_led_1;
process (clk, reset, uart_en, tx_in, tx_in_sync)
-- tao tin hieu cho phep truyen
begin
if rising_edge(clk) then
if (reset='0') then
tx_in_sync <= '0';
else
tx_in_sync <= tx_in;
end if;
end if;

tx_en <= (not tx_in_sync) and tx_in and uart_en;
end process;
end Behavioral;

-


Khối UART_TRANSMITTER

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values

24


--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity uart_transmitter is
port (
clk : in std_logic;

-- clock dong bo he thong

reset : in std_logic; -- reset he thong. Tich cuc muc thap
uart_en : in std_logic;

Tich cuc muc cao

-- cho phep he thong lam viec.

data_in : in std_logic_vector(7 downto 0); -- 8 bit du
lieu ngo vao
tx_enable : in std_logic;

-- tin hieu cho phep bo truyen

hoat dong
tx_clken : in std_logic;
du lieu khi bo truyen hoat dong
uart_tx : out std_logic

-- xung cho phep dich tung bit
-- duong truyen du lieu dong

bo
);
end uart_transmitter;

architecture Behavioral of uart_transmitter is
signal state: std_logic_vector(1 downto 0);
constant idle: std_logic_vector(1 downto 0):= "00";
constant load_txs: std_logic_vector(1 downto 0):= "01";
constant shift_data: std_logic_vector(1 downto 0):= "10";

24



signal tsr: std_logic_vector(9 downto 0);
signal tx_count: std_logic_vector(3 downto 0);
begin
-- may trang thai huu han
process(clk)
begin
if rising_edge(clk) then
if ((reset='0') or (uart_en='0')) then
state <= idle;
else
case state is
when idle =>
if (tx_enable='1') then state <=

load_txs;

end if;
when load_txs =>
state <= shift_data;
when shift_data =>
if ((tx_count="1001") and (tx_clken='1'))
then -- dem den 10 vi khung truyen co 10 bit du lieu
state <= idle;
end if;
when others =>
state <= idle;
end case;
end if;
end if;

end process;
24


-- dau ra may trang thai huu han
process(clk)
begin
if rising_edge(clk) then
if ((reset='0') or (uart_en='0')) then
tsr <= "0000000000";
uart_tx <= '1';
tx_count <= "0000";
else
case state is
when idle =>
tsr <= "0000000000";
uart_tx <= '1';
tx_count <= "0000";
when load_txs =>
tsr <= ('1' & data_in & '0');
bit 0 la bit start, bit 1 la bit stop vao khung truyen

-- gan

when shift_data =>
if (tx_clken = '1') then
uart_tx <= tsr(0);

-- gan du lieu


vao duong truyen
tsr <= ('1' & tsr(9 downto 1));

--

dich du lieu
tx_count <= tx_count + 1;

-- bo

dem truyen
end if;
when others =>
tsr <= "0000000000";
uart_tx <= '1';

24


tx_count <= "0000";
end case;
end if;
end if;
end process;
end Behavioral;

-

Khối UART_RECEIVER


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity uart_receiver is
port (
clk : in std_logic;

-- clock dong bo he thong

reset : in std_logic; -- reset he thong. Tich cuc muc thap
uart_en : in std_logic;
Tich cuc muc cao

-- cho phep he thong lam viec.

24


rx_clken : in std_logic;

tri lay mau du lieu o bo nhan
uart_rx : in std_logic;

-- xung cho phep xac dinh vi
-- duong nhan du lieu dong bo

rev_data : out std_logic_vector(7 downto 0) -- du lieu
nhan duoc
);
end uart_receiver;

architecture Behavioral of uart_receiver is
signal rx_count: std_logic_vector(3 downto 0); -- tin hieu dem
xung vao
signal samp_count: std_logic_vector(3 downto 0);
dem so lan de lay mau trong tung xung vao
signal uart_rx_sync: std_logic;

-- tin hieu

-- tin hieu lay mau doc duoc

signal rsr: std_logic_vector(7 downto 0);
signal state: std_logic_vector(1 downto 0);
constant idle: std_logic_vector(1 downto 0):= "00";
constant check_start_bit: std_logic_vector(1 downto 0):= "01";
constant receive_data: std_logic_vector(1 downto 0):= "10";
begin
process(clk)
begin

if rising_edge(clk) then
if ((reset='0') or (uart_en='0')) then
uart_rx_sync <= '1';
else
uart_rx_sync <= uart_rx;
end if;
end if;

24


end process;
-- may trang thai huu han
process(clk)
begin
if rising_edge(clk) then
if ((reset='0') or (uart_en='0')) then
state <= idle;
else
case state is
when idle =>
if (uart_rx_sync = '0') then
state <= check_start_bit;
end if;
when check_start_bit =>
mau o gia tri thu 8

if (samp_count = "0111") then

-- lay


if (uart_rx_sync = '0') then
state <= receive_data;
else
state <= idle;
end if;
end if;
when receive_data =>
if (rx_count="1010") then
xung thu 10 vi khung truyen co 10 bit

-- dem den

state <= idle;
end if;
when others =>
24


state <= idle;
end case;
end if;
end if;
end process;
-- dau ra may trang thai huu han
process(clk)
begin
if rising_edge(clk) then
if ((reset='0') or (uart_en='0')) then
rsr <=


"11111111";

rx_count <= "0000";
samp_count <= "0000";
else
case state is
when idle =>
rx_count <= "0000";
samp_count <= "0000";
when check_start_bit =>
if (rx_clken='1') then
bo dem lay mau

samp_count <= samp_count + 1;

--

end if;
when receive_data =>
if (rx_clken='1') then
samp_count <= samp_count + 1;
if (samp_count="0111") then

24


rx_count <= rx_count + 1;
if(rx_count<"1001") then
-chi dem den xung thu 9, loai bo bit start va stop ra du lieu nhan

duoc
rsr(7 downto 1));

rsr <= (uart_rx_sync &

-- dich du lieu

end if;
end if;
end if;
when others =>
rx_count <= "0000";
samp_count <= "0000";
end case;
end if;
end if;
end process;
rev_data <= rsr;
end Behavioral;

3.2. Code testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_arith.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;


24


ENTITY test_uart IS
END test_uart;

ARCHITECTURE behavior OF test_uart IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT full_uart
PORT(
clk : IN

std_logic;

reset : IN

std_logic;

-- clock dong bo he thong
-- reset he thong. Tich cuc muc thap

uart_en : IN
Tich cuc muc cao

std_logic;

data_in : IN
lieu ngo vao


std_logic_vector(7 downto 0);

tx_in : IN std_logic;
vao bo truyen. Tich cuc muc cao
uart_rx : IN

-- cho phep he thong lam viec.
-- 8 bit du

-- cho phep ghi du lieu tu data_in

std_logic;

-- duong nhan du lieu dong bo

led_0 : OUT std_logic_vector(3 downto 0);
nhan duoc xuat ra led don

-- gia tri

led_1 : OUT std_logic_vector(3 downto 0);
nhan duoc xuat ra led don

-- gia tri

bo

uart_tx : OUT


std_logic

-- duong truyen du lieu dong

);
END COMPONENT;

--Inputs
signal clk : std_logic := '0';

24


signal reset : std_logic := '0';
signal uart_en : std_logic := '0';
signal data_in : std_logic_vector(7 downto 0) := (others => '0');
signal tx_in : std_logic := '0';
signal uart_rx : std_logic := '0';

--Outputs
signal led_0 : std_logic_vector(3 downto 0);
signal led_1 : std_logic_vector(3 downto 0);
signal uart_tx : std_logic;

-- Clock period definitions
-- chu ky = 20 ns, f = 50 MHz
-- baud_rate = 9600 => t_data = 104200 ns
constant clk_period : time := 20 ns;
constant t_data: time := 104200 ns;
BEGIN


-- Instantiate the Unit Under Test (UUT)
uut: full_uart PORT MAP (
clk => clk,
reset => reset,
uart_en => uart_en,
data_in => data_in,
tx_in => tx_in,
uart_rx => uart_rx,

24


led_0 => led_0,
led_1 => led_1,
uart_tx => uart_tx
);

data_in <= "00010010";

clock: process
-- tao xung tan so 50 MHz
begin
clk <= '1';
wait for 10 ns;
clk <= '0';
wait for 10 ns;
end process;

-- Stimulus process

stim_proc1: process
begin
reset <= '0';
wait for 20 ps;
-- tao du lieu vao
tx_in <= '1';

-- cho phep bo truyen hoat dong

wait for 20 ps;
reset <= '1';
uart_en <= '1';

24


wait for t_data;
-- dich du lieu
for i in 0 to 7 loop
uart_rx <= data_in(i);
wait for t_data;
end loop;
-- phat hien bit stop
uart_rx <= '1';
wait for t_data;
wait;
end process;
END;

3.3. Kết quả mô phỏng:


24


Hình 6: thời điểm uart_tx nhận giá trị bit start và ghi vào trong bit MSB của led_1

Hình 7: thời điểm uart_tx nhận giá trị bit LSB của data_in và tiếp tục ghi vào led_1

24


Hình 8: thời điểm uart_tx nhận giá trị bit thứ 2 của data_in và ghi vào led_1

Hình 9: quá trình truyền nhận kết thúc, 4 bit cao của data_in được ghi vào
led_1 và 4 bit thấp của data_in được ghi vào led_0

24


×