-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuart_loopback.vhd
More file actions
155 lines (145 loc) · 5.21 KB
/
Copy pathuart_loopback.vhd
File metadata and controls
155 lines (145 loc) · 5.21 KB
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
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: UART LOOPBACK EXAMPLE TOP MODULE
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- LICENSE: The MIT License (MIT), please read LICENSE file
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- UART FOR FPGA REQUIRES: 1 START BIT, 8 DATA BITS, 1 STOP BIT!!!
-- OTHER PARAMETERS CAN BE SET USING GENERICS.
entity UART_LOOPBACK is
Generic (
CLK_FREQ : integer := 100e6; -- 100e6 << 100MHz set system clock frequency in Hz
BAUD_RATE : integer := 9600; -- baud rate value
PARITY_BIT : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
);
Port (
CLK : in std_logic; -- system clock
RST_N : in std_logic; -- low active synchronous reset
-- UART INTERFACE
UART_TXD : out std_logic;
UART_RXD : in std_logic;
-- DEBUG INTERFACE
--BUSY : out std_logic;
--FRAME_ERR : out std_logic;
-- LED
--DATA_OUT : out std_logic_vector(7 downto 0);
--reset_LED : out std_logic;
-- Slave
Hsel : in STD_LOGIC;
Haddress : in STD_LOGIC_VECTOR(15 downto 0);
HWrite : in STD_LOGIC;
HTrans : in STD_LOGIC_VECTOR(1 downto 0);
HWData : in STD_LOGIC_VECTOR(31 downto 0);
HRData : out STD_LOGIC_VECTOR(31 downto 0);
HReady : out STD_LOGIC
);
end UART_LOOPBACK;
architecture FULL of UART_LOOPBACK is
Type State is (
IDLE,
WRITE_TO_PC,
WRITE_WAIT,
READ_FROM_PC,
READ_COMPLETE_1,
READ_COMPLETE_2,
WRITE_LOOPBACK,
WRITE_COMPLETE_1,
WRITE_COMPLETE_2
);
Type newlineState is (
LF,
CHAR
);
signal BUSY : STD_LOGIC;
signal FRAME_ERR : STD_LOGIC;
signal data_in_temp : std_logic_vector(7 downto 0);
signal data_out_temp : std_logic_vector(7 downto 0);
signal data_send_temp : STD_LOGIC;
signal valid : std_logic;
signal valid_reg : std_logic := '0';
signal curr_state : State:=IDLE;
signal char_state : newlineState:=CHAR;
begin
uart_i: entity work.UART
generic map (
CLK_FREQ => CLK_FREQ,
BAUD_RATE => BAUD_RATE,
PARITY_BIT => PARITY_BIT
)
port map (
CLK => CLK,
RST => RST_N,
-- UART INTERFACE
UART_TXD => UART_TXD,
UART_RXD => UART_RXD,
-- USER DATA OUTPUT INTERFACE
DATA_OUT => data_out_temp,
DATA_VLD => valid,
FRAME_ERROR => FRAME_ERR,
-- USER DATA INPUT INTERFACE
DATA_IN => data_in_temp,
DATA_SEND => data_send_temp,
BUSY => BUSY
);
process(CLK, RST_N)
begin
if RST_N = '1' then
curr_state<=IDLE;
elsif rising_edge(CLK) then
case curr_state is
when IDLE =>
if HTrans = "10" and HSel ='1' and BUSY = '0' then
if HWrite = '1' then
curr_state <= WRITE_TO_PC;
else
curr_state <= READ_FROM_PC;
end if;
end if;
when READ_FROM_PC =>
if valid_reg = '1' then
curr_state <= READ_COMPLETE_1;
end if;
when READ_COMPLETE_1=>
curr_state <= READ_COMPLETE_2;
when WRITE_TO_PC =>
curr_state <= WRITE_WAIT;
when WRITE_WAIT=>
if BUSY = '0' then
curr_state <= WRITE_COMPLETE_1;
end if;
when WRITE_COMPLETE_1=>
curr_state <= WRITE_COMPLETE_2;
when others => curr_state <= IDLE;
end case;
end if;
end process;
process(CLK, RST_N)
begin
if RST_N = '1' then
char_state<=CHAR;
elsif rising_edge(CLK) then
case char_state is
when CHAR=>
if data_out_temp = "00001010" and valid = '1' then
char_state <= LF;
end if;
when others=> char_state <= CHAR;
end case;
end if;
end process;
valid_reg <= valid;
data_send_temp <= '1' when curr_state = WRITE_TO_PC or valid = '1' else '0';--or char_state = LF else '0';
data_in_temp <= HWData(7 downto 0) when curr_state = WRITE_TO_PC or curr_state = WRITE_WAIT else
--"00001101" when char_state = LF else
data_out_temp;
HRData <= "000000000000000000000000" & data_out_temp;
HReady <= '1' when curr_state = READ_COMPLETE_1 or
curr_state = READ_COMPLETE_2 or
curr_state = WRITE_COMPLETE_1 or
curr_state = WRITE_COMPLETE_2 else '0';
end FULL;