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