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;