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