1 |
2 |
heshamelma |
----------------------------------------------------------------------------
|
2 |
|
|
-- UART_TX_CTRL.vhd -- UART Data Transfer Component
|
3 |
|
|
----------------------------------------------------------------------------
|
4 |
|
|
-- Author: Sam Bobrowicz
|
5 |
|
|
-- Copyright 2011 Digilent, Inc.
|
6 |
|
|
----------------------------------------------------------------------------
|
7 |
|
|
--
|
8 |
|
|
----------------------------------------------------------------------------
|
9 |
|
|
-- This component may be used to transfer data over a UART device. It will
|
10 |
|
|
-- serialize a byte of data and transmit it over a TXD line. The serialized
|
11 |
|
|
-- data has the following characteristics:
|
12 |
|
|
-- *115200 Baud Rate
|
13 |
|
|
-- *8 data bits, LSB first
|
14 |
|
|
-- *1 stop bit
|
15 |
|
|
-- *no parity
|
16 |
|
|
--
|
17 |
|
|
-- Port Descriptions:
|
18 |
|
|
--
|
19 |
|
|
-- SEND - Used to trigger a send operation. The upper layer logic should
|
20 |
|
|
-- set this signal high for a single clock cycle to trigger a
|
21 |
|
|
-- send. When this signal is set high DATA must be valid . Should
|
22 |
|
|
-- not be asserted unless READY is high.
|
23 |
|
|
-- DATA - The parallel data to be sent. Must be valid the clock cycle
|
24 |
|
|
-- that SEND has gone high.
|
25 |
|
|
-- CLK - A 100 MHz clock is expected
|
26 |
|
|
-- READY - This signal goes low once a send operation has begun and
|
27 |
|
|
-- remains low until it has completed and the module is ready to
|
28 |
|
|
-- send another byte.
|
29 |
|
|
-- UART_TX - This signal should be routed to the appropriate TX pin of the
|
30 |
|
|
-- external UART device.
|
31 |
|
|
--
|
32 |
|
|
----------------------------------------------------------------------------
|
33 |
|
|
--
|
34 |
|
|
----------------------------------------------------------------------------
|
35 |
|
|
-- Revision History:
|
36 |
|
|
-- 08/08/2011(SamB): Created using Xilinx Tools 13.2
|
37 |
|
|
----------------------------------------------------------------------------
|
38 |
|
|
library IEEE;
|
39 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
40 |
|
|
use IEEE.std_logic_unsigned.all;
|
41 |
|
|
|
42 |
|
|
entity UART_TX_CTRL is
|
43 |
|
|
Port ( SEND : in STD_LOGIC;
|
44 |
|
|
DATA : in STD_LOGIC_VECTOR (7 downto 0);
|
45 |
|
|
CLK : in STD_LOGIC;
|
46 |
|
|
READY : out STD_LOGIC;
|
47 |
|
|
UART_TX : out STD_LOGIC);
|
48 |
|
|
end UART_TX_CTRL;
|
49 |
|
|
|
50 |
|
|
architecture Behavioral of UART_TX_CTRL is
|
51 |
|
|
|
52 |
|
|
type TX_STATE_TYPE is (RDY, LOAD_BIT, SEND_BIT);
|
53 |
|
|
-- 00101000101100 for 25 MHz 00000110110010
|
54 |
|
|
constant BIT_TMR_MAX : std_logic_vector(13 downto 0) := "00000110110010";
|
55 |
|
|
--434 = (round(50MHz / 115200)) - 1
|
56 |
|
|
constant BIT_INDEX_MAX : natural := 10;
|
57 |
|
|
|
58 |
|
|
--Counter that keeps track of the number of clock cycles the current bit has been held stable over the
|
59 |
|
|
--UART TX line. It is used to signal when the ne
|
60 |
|
|
signal bitTmr : std_logic_vector(13 downto 0) := (others => '0');
|
61 |
|
|
|
62 |
|
|
--combinatorial logic that goes high when bitTmr has counted to the proper value to ensure
|
63 |
|
|
--a 9600 baud rate
|
64 |
|
|
signal bitDone : std_logic;
|
65 |
|
|
|
66 |
|
|
--Contains the index of the next bit in txData that needs to be transferred
|
67 |
|
|
signal bitIndex : natural;
|
68 |
|
|
|
69 |
|
|
--a register that holds the current data being sent over the UART TX line
|
70 |
|
|
signal txBit : std_logic := '1';
|
71 |
|
|
|
72 |
|
|
--A register that contains the whole data packet to be sent, including start and stop bits.
|
73 |
|
|
signal txData : std_logic_vector(9 downto 0);
|
74 |
|
|
|
75 |
|
|
signal txState : TX_STATE_TYPE := RDY;
|
76 |
|
|
|
77 |
|
|
begin
|
78 |
|
|
|
79 |
|
|
--Next state logic
|
80 |
|
|
next_txState_process : process (CLK)
|
81 |
|
|
begin
|
82 |
|
|
if (rising_edge(CLK)) then
|
83 |
|
|
case txState is
|
84 |
|
|
when RDY =>
|
85 |
|
|
if (SEND = '1') then
|
86 |
|
|
txState <= LOAD_BIT;
|
87 |
|
|
end if;
|
88 |
|
|
when LOAD_BIT =>
|
89 |
|
|
txState <= SEND_BIT;
|
90 |
|
|
when SEND_BIT =>
|
91 |
|
|
if (bitDone = '1') then
|
92 |
|
|
if (bitIndex = BIT_INDEX_MAX) then
|
93 |
|
|
txState <= RDY;
|
94 |
|
|
else
|
95 |
|
|
txState <= LOAD_BIT;
|
96 |
|
|
end if;
|
97 |
|
|
end if;
|
98 |
|
|
when others=> --should never be reached
|
99 |
|
|
txState <= RDY;
|
100 |
|
|
end case;
|
101 |
|
|
end if;
|
102 |
|
|
end process;
|
103 |
|
|
|
104 |
|
|
bit_timing_process : process (CLK)
|
105 |
|
|
begin
|
106 |
|
|
if (rising_edge(CLK)) then
|
107 |
|
|
if (txState = RDY) then
|
108 |
|
|
bitTmr <= (others => '0');
|
109 |
|
|
else
|
110 |
|
|
if (bitDone = '1') then
|
111 |
|
|
bitTmr <= (others => '0');
|
112 |
|
|
else
|
113 |
|
|
bitTmr <= bitTmr + 1;
|
114 |
|
|
end if;
|
115 |
|
|
end if;
|
116 |
|
|
end if;
|
117 |
|
|
end process;
|
118 |
|
|
|
119 |
|
|
bitDone <= '1' when (bitTmr = BIT_TMR_MAX) else
|
120 |
|
|
'0';
|
121 |
|
|
|
122 |
|
|
bit_counting_process : process (CLK)
|
123 |
|
|
begin
|
124 |
|
|
if (rising_edge(CLK)) then
|
125 |
|
|
if (txState = RDY) then
|
126 |
|
|
bitIndex <= 0;
|
127 |
|
|
elsif (txState = LOAD_BIT) then
|
128 |
|
|
bitIndex <= bitIndex + 1;
|
129 |
|
|
end if;
|
130 |
|
|
end if;
|
131 |
|
|
end process;
|
132 |
|
|
|
133 |
|
|
tx_data_latch_process : process (CLK)
|
134 |
|
|
begin
|
135 |
|
|
if (rising_edge(CLK)) then
|
136 |
|
|
if (SEND = '1') then
|
137 |
|
|
txData <= '1' & DATA & '0';
|
138 |
|
|
end if;
|
139 |
|
|
end if;
|
140 |
|
|
end process;
|
141 |
|
|
|
142 |
|
|
tx_bit_process : process (CLK)
|
143 |
|
|
begin
|
144 |
|
|
if (rising_edge(CLK)) then
|
145 |
|
|
if (txState = RDY) then
|
146 |
|
|
txBit <= '1';
|
147 |
|
|
elsif (txState = LOAD_BIT) then
|
148 |
|
|
txBit <= txData(bitIndex);
|
149 |
|
|
end if;
|
150 |
|
|
end if;
|
151 |
|
|
end process;
|
152 |
|
|
|
153 |
|
|
UART_TX <= txBit;
|
154 |
|
|
READY <= '1' when (txState = RDY) else
|
155 |
|
|
'0';
|
156 |
|
|
|
157 |
|
|
end Behavioral;
|
158 |
|
|
|