blob: b91fb6669318df7acc0c630d264137fc5df7aceb (
plain)
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
|
-- UART TX implementation
--
-- (c) 2008 - 2015, Martin Strubel <strubel@section5.ch>
--
-- This implementation depends on an external FIFO that can be emptied
-- as follows:
-- When 'data_out_en' == 1 on rising edge of 'clk', 'data' is latched
-- into the shift register and clocked out to the 'tx' pin. The FIFO
-- increments its pointer and asserts the next data byte to 'data'.
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all; -- for TO_UNSIGNED
entity UARTtx is
port (
busy : out std_logic;
data : in unsigned(7 downto 0);
data_ready : in std_logic; -- Data in FIFO ready
data_out_en : out std_logic; -- Data out enable
tx : out std_logic; -- TX UART
reset : in std_logic; -- Reset pin, LOW active
txclken : in std_logic;
clk : in std_logic
);
end UARTtx;
architecture behaviour of UARTtx is
type uart_state_t is (S_IDLE, S_START, S_SHIFT, S_STOP);
signal state : uart_state_t := S_IDLE;
signal nextstate : uart_state_t;
-- Data Shift register:
signal dsr : unsigned(7 downto 0) := x"00";
signal bitcount : unsigned(2 downto 0) := "000"; -- Bit counter
begin
sync_state_advance:
process (clk)
begin
if falling_edge(clk) then
if txclken = '1' then
if reset = '1' then
state <= S_IDLE;
else
state <= nextstate;
end if;
end if;
end if;
end process;
state_decode:
process (state, nextstate, bitcount, data_ready)
begin
case state is
when S_STOP =>
if data_ready = '1' then
nextstate <= S_START;
else
nextstate <= S_IDLE;
end if;
when S_IDLE =>
if data_ready = '1' then
nextstate <= S_START;
else
nextstate <= S_IDLE;
end if;
when S_START =>
nextstate <= S_SHIFT;
when S_SHIFT =>
if bitcount = "000" then
nextstate <= S_STOP;
else
nextstate <= S_SHIFT;
end if;
when others =>
nextstate <= S_IDLE;
end case;
end process;
bitcounter:
process (clk)
begin
if rising_edge(clk) then
if txclken = '1' then
case state is
when S_SHIFT =>
bitcount <= bitcount + 1;
when others =>
bitcount <= "000";
end case;
end if;
end if;
end process;
shift:
process (clk)
begin
if falling_edge(clk) then
data_out_en <= '0';
if txclken = '1' then
case state is
when S_START =>
dsr <= data;
data_out_en <= '1';
tx <= '0';
when S_SHIFT =>
dsr <= '1' & dsr(7 downto 1);
tx <= dsr(0);
when others =>
tx <= '1';
end case;
end if;
end if;
end process;
-- d_state <= std_logic_vector(TO_UNSIGNED(uart_state_t'pos(state), 4));
busy <= '1' when state /= S_IDLE else '0';
end behaviour;
|