UART
Authors: Anthony Eshpeter & Andrew Dunmore
Description: This program uses the parallel port of a computer in order to communicate between the computer and the system. Four control lines are used between the computer and the UART to control flow of data. Four more control lines are used between the UART and the system to control flow of data between the two. Data is passed using an 8-bit input line and two 4-bit output lines.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library lpm;
use lpm.lpm_components.ALL;
entity UART2 is
generic( data_in_width : positive := 8;
data_out_width : positive := 4;
slow_cnt_width : positive := 5;
mux_sel_width : positive := 0;
mux_in_width :positive := 1;
mux_size : positive := 2);
port( clk: in std_logic;
data_rec: out std_logic; -- control line to main controller
data_ack: in std_logic; -- control line from main controller
data_in : out std_logic_vector(data_in_width-1 downto 0); -- data to main controller
ready_to_send:out std_logic; -- control line to main controller
data_send:in std_logic; -- control line from main controller
data_out: in std_logic_vector(data_in_width-1 downto 0); -- data from main controller
CTS_comp:out std_logic; -- control line to computer
send_req_comp:in std_logic; -- control line from computer
data_in_comp:in std_logic_vector(data_in_width-1 downto 0); -- data from computer
ack_comp:in std_logic; -- control line from computer
trans_req_comp:out std_logic; -- control line to computer
data_out_comp:out std_logic_vector(data_out_width-1 downto 0)); -- data to computer
end UART2;
architecture behavioural of UART2 is
type state_typer is (wait_receive,rec_mux0,rec_mux1); -- receiver state machine states
type state_typet is (wait_send,send_mux0,hold_mux0,send_mux1,hold_mux1); -- transmitter state machine states
signal slowclk:std_logic; -- 40 kHz clock
signal slowcount:std_logic_vector(slow_cnt_width downto 0);
signal transmit: state_typet;
signal receive: state_typer;
signal load_reg_in, load_reg_out : std_logic; -- internal control lines for UART I/O
signal mux_select : std_logic_vector(mux_sel_width downto 0); -- mux select line
signal data_out_int: std_logic_vector(data_in_width-1 downto 0); -- intermediate value before separated into nibbles
signal mux_input : std_logic_2D(mux_in_width downto 0, data_out_width-1 downto 0);
signal mux_in_high, mux_in_low : std_logic_vector(data_out_width-1 downto 0);
begin
slowclk <= slowcount(slow_cnt_width);
process(clk)
-- this process creates a 40 kHz clock
begin
if clk'event and clk = '1' then
slowcount <= slowcount + '1';
end if;
end process;
process (clk)
-- this process deals with receiving data from the computer and feeding it to the system
begin
if clk'event and clk = '1' then
case receive is
when wait_receive =>
if send_req_comp = '1' then
receive <= rec_mux0;
else
receive <= wait_receive;
end if;
when rec_mux0 =>
if data_ack = '1' then
receive <= rec_mux1;
else
receive <= rec_mux0;
end if;
when rec_mux1 =>
if send_req_comp = '0' then
receive <= wait_receive;
else
receive <= rec_mux1;
end if;
when others =>
receive <= wait_receive;
end case;
end if;
end process;
process (slowclk)
-- this process deals with the transmission of data to the computer from the system
begin
if slowclk'event and slowclk = '1' then
case transmit is
when wait_send =>
if data_send = '1' then
transmit <= send_mux0;
else
transmit <= wait_send;
end if;
when send_mux0 =>
if ack_comp = '1' then
transmit <= hold_mux0;
else
transmit <= send_mux0;
end if;
when hold_mux0 =>
if ack_comp = '0' then
transmit <= send_mux1;
else
transmit <= hold_mux0;
end if;
when send_mux1 =>
if ack_comp = '1' then
transmit <= hold_mux1;
else
transmit <= send_mux1;
end if;
when hold_mux1 =>
if ack_comp = '0' then
transmit <= wait_send;
else
transmit <= hold_mux1;
end if;
when others =>
transmit <= wait_send;
end case;
end if;
end process;
with receive select
CTS_comp <= '1' when wait_receive,
'0' when others;
with receive select
load_reg_in <= '1' when rec_mux0,
'0' when others;
with receive select
data_rec <= '1' when rec_mux0,
'0' when others;
with transmit select
ready_to_send <= '1' when wait_send,
'0' when others;
with transmit select
mux_select <= "1" when send_mux1,
"1" when hold_mux1,
"0" when others;
with transmit select
load_reg_out <= '1' when wait_send,
'0' when others;
with transmit select
trans_req_comp <= '1' when send_mux0,
'1' when send_mux1,
'0' when others;
reg_in: component lpm_ff
generic map( LPM_WIDTH => data_in_width )
port map( data => data_in_comp,
clock => clk,
sload => load_reg_in,
q => data_in );
reg_out: component lpm_ff
generic map( LPM_WIDTH => data_in_width )
port map( data => data_out,
clock => clk,
sload => load_reg_out,
q => data_out_int);
-- create output nibbles
mux_in_high <= data_out_int(data_in_width-1 downto data_out_width);
mux_in_low <= data_out_int(data_out_width-1 downto 0);
output_mux : FOR i IN 3 downto 0 GENERATE
mux_input(0,i) <= mux_in_low(i);
mux_input(1,i) <= mux_in_high(i);
END GENERATE output_mux;
out_mux : component lpm_mux -- mux used for output nibble selection
generic map( LPM_WIDTH => data_out_width,
LPM_SIZE => mux_size,
LPM_WIDTHS => mux_in_width )
port map( data => mux_input,
sel => mux_select,
result => data_out_comp );
end architecture behavioural;