Add Nexys Video support
[microwatt.git] / fpga / pp_soc_uart.vhd
1 -- The Potato Processor - A simple processor for FPGAs
2 -- (c) Kristian Klomsten Skordal 2014 - 2016 <kristian.skordal@wafflemail.net>
3
4 library ieee;
5 use ieee.std_logic_1164.all;
6 use ieee.numeric_std.all;
7
8 --! @brief Simple UART module.
9 --! The following registers are defined:
10 --! |--------------------|--------------------------------------------|
11 --! | Address | Description |
12 --! |--------------------|--------------------------------------------|
13 --! | 0x00 | Transmit register (write-only) |
14 --! | 0x08 | Receive register (read-only) |
15 --! | 0x10 | Status register (read-only) |
16 --! | 0x18 | Sample clock divisor register (read/write) |
17 --! | 0x20 | Interrupt enable register (read/write) |
18 --! |--------------------|--------------------------------------------|
19 --!
20 --! The status register contains the following bits:
21 --! - Bit 0: receive buffer empty
22 --! - Bit 1: transmit buffer empty
23 --! - Bit 2: receive buffer full
24 --! - Bit 3: transmit buffer full
25 --!
26 --! The sample clock divisor should be set according to the formula:
27 --! sample_clk = (f_clk / (baudrate * 16)) - 1
28 --!
29 --! If the sample clock divisor register is set to 0, the sample clock
30 --! is stopped.
31 --!
32 --! Interrupts are enabled by setting the corresponding bit in the interrupt
33 --! enable register. The following bits are available:
34 --! - Bit 0: data received (receive buffer not empty)
35 --! - Bit 1: ready to send data (transmit buffer empty)
36 entity pp_soc_uart is
37 generic(
38 FIFO_DEPTH : natural := 64 --! Depth of the input and output FIFOs.
39 );
40 port(
41 clk : in std_logic;
42 reset : in std_logic;
43
44 -- UART ports:
45 txd : out std_logic;
46 rxd : in std_logic;
47
48 -- Interrupt signal:
49 irq : out std_logic;
50
51 -- Wishbone ports:
52 wb_adr_in : in std_logic_vector(11 downto 0);
53 wb_dat_in : in std_logic_vector( 7 downto 0);
54 wb_dat_out : out std_logic_vector( 7 downto 0);
55 wb_we_in : in std_logic;
56 wb_cyc_in : in std_logic;
57 wb_stb_in : in std_logic;
58 wb_ack_out : out std_logic
59 );
60 end entity pp_soc_uart;
61
62 architecture behaviour of pp_soc_uart is
63
64 subtype bitnumber is natural range 0 to 7; --! Type representing the index of a bit.
65
66 -- UART sample clock signals:
67 signal sample_clk : std_logic;
68 signal sample_clk_divisor : std_logic_vector(7 downto 0);
69 signal sample_clk_counter : std_logic_vector(sample_clk_divisor'range);
70
71 -- UART receive process signals:
72 type rx_state_type is (IDLE, RECEIVE, STARTBIT, STOPBIT);
73 signal rx_state : rx_state_type;
74 signal rx_byte : std_logic_vector(7 downto 0);
75 signal rx_current_bit : bitnumber;
76
77 subtype rx_sample_counter_type is natural range 0 to 15;
78 signal rx_sample_counter : rx_sample_counter_type;
79 signal rx_sample_value : rx_sample_counter_type;
80
81 subtype rx_sample_delay_type is natural range 0 to 7;
82 signal rx_sample_delay : rx_sample_delay_type;
83
84 -- UART transmit process signals:
85 type tx_state_type is (IDLE, TRANSMIT, STOPBIT);
86 signal tx_state : tx_state_type;
87 signal tx_byte : std_logic_vector(7 downto 0);
88 signal tx_current_bit : bitnumber;
89
90 -- UART transmit clock:
91 subtype uart_tx_counter_type is natural range 0 to 15;
92 signal uart_tx_counter : uart_tx_counter_type := 0;
93 signal uart_tx_clk : std_logic;
94
95 -- Buffer signals:
96 signal send_buffer_full, send_buffer_empty : std_logic;
97 signal recv_buffer_full, recv_buffer_empty : std_logic;
98 signal send_buffer_input, send_buffer_output : std_logic_vector(7 downto 0);
99 signal recv_buffer_input, recv_buffer_output : std_logic_vector(7 downto 0);
100 signal send_buffer_push, send_buffer_pop : std_logic := '0';
101 signal recv_buffer_push, recv_buffer_pop : std_logic := '0';
102
103 -- IRQ enable signals:
104 signal irq_recv_enable, irq_tx_ready_enable : std_logic := '0';
105
106 -- Wishbone signals:
107 type wb_state_type is (IDLE, WRITE_ACK, READ_ACK);
108 signal wb_state : wb_state_type;
109
110 signal wb_ack : std_logic; --! Wishbone acknowledge signal
111
112 begin
113
114 irq <= (irq_recv_enable and (not recv_buffer_empty))
115 or (irq_tx_ready_enable and send_buffer_empty);
116
117 ---------- UART receive ----------
118
119 recv_buffer_input <= rx_byte;
120
121 uart_receive: process(clk)
122 begin
123 if rising_edge(clk) then
124 if reset = '1' then
125 rx_state <= IDLE;
126 recv_buffer_push <= '0';
127 else
128 case rx_state is
129 when IDLE =>
130 if recv_buffer_push = '1' then
131 recv_buffer_push <= '0';
132 end if;
133
134 if sample_clk = '1' and rxd = '0' then
135 rx_sample_value <= rx_sample_counter;
136 rx_sample_delay <= 0;
137 rx_current_bit <= 0;
138 rx_state <= STARTBIT;
139 end if;
140 when STARTBIT =>
141 if sample_clk = '1' then
142 if rx_sample_delay = 7 then
143 rx_state <= RECEIVE;
144 rx_sample_value <= rx_sample_counter;
145 rx_sample_delay <= 0;
146 else
147 rx_sample_delay <= rx_sample_delay + 1;
148 end if;
149 end if;
150 when RECEIVE =>
151 if sample_clk = '1' and rx_sample_counter = rx_sample_value then
152 if rx_current_bit /= 7 then
153 rx_byte(rx_current_bit) <= rxd;
154 rx_current_bit <= rx_current_bit + 1;
155 else
156 rx_byte(rx_current_bit) <= rxd;
157 rx_state <= STOPBIT;
158 end if;
159 end if;
160 when STOPBIT =>
161 if sample_clk = '1' and rx_sample_counter = rx_sample_value then
162 rx_state <= IDLE;
163
164 if recv_buffer_full = '0' then
165 recv_buffer_push <= '1';
166 end if;
167 end if;
168 end case;
169 end if;
170 end if;
171 end process uart_receive;
172
173 sample_counter: process(clk)
174 begin
175 if rising_edge(clk) then
176 if reset = '1' then
177 rx_sample_counter <= 0;
178 elsif sample_clk = '1' then
179 if rx_sample_counter = 15 then
180 rx_sample_counter <= 0;
181 else
182 rx_sample_counter <= rx_sample_counter + 1;
183 end if;
184 end if;
185 end if;
186 end process sample_counter;
187
188 ---------- UART transmit ----------
189
190 tx_byte <= send_buffer_output;
191
192 uart_transmit: process(clk)
193 begin
194 if rising_edge(clk) then
195 if reset = '1' then
196 txd <= '1';
197 tx_state <= IDLE;
198 send_buffer_pop <= '0';
199 tx_current_bit <= 0;
200 else
201 case tx_state is
202 when IDLE =>
203 if send_buffer_empty = '0' and uart_tx_clk = '1' then
204 txd <= '0';
205 send_buffer_pop <= '1';
206 tx_current_bit <= 0;
207 tx_state <= TRANSMIT;
208 elsif uart_tx_clk = '1' then
209 txd <= '1';
210 end if;
211 when TRANSMIT =>
212 if send_buffer_pop = '1' then
213 send_buffer_pop <= '0';
214 elsif uart_tx_clk = '1' and tx_current_bit = 7 then
215 txd <= tx_byte(tx_current_bit);
216 tx_state <= STOPBIT;
217 elsif uart_tx_clk = '1' then
218 txd <= tx_byte(tx_current_bit);
219 tx_current_bit <= tx_current_bit + 1;
220 end if;
221 when STOPBIT =>
222 if uart_tx_clk = '1' then
223 txd <= '1';
224 tx_state <= IDLE;
225 end if;
226 end case;
227 end if;
228 end if;
229 end process uart_transmit;
230
231 uart_tx_clock_generator: process(clk)
232 begin
233 if rising_edge(clk) then
234 if reset = '1' then
235 uart_tx_counter <= 0;
236 uart_tx_clk <= '0';
237 else
238 if sample_clk = '1' then
239 if uart_tx_counter = 15 then
240 uart_tx_counter <= 0;
241 uart_tx_clk <= '1';
242 else
243 uart_tx_counter <= uart_tx_counter + 1;
244 uart_tx_clk <= '0';
245 end if;
246 else
247 uart_tx_clk <= '0';
248 end if;
249 end if;
250 end if;
251 end process uart_tx_clock_generator;
252
253 ---------- Sample clock generator ----------
254
255 sample_clock_generator: process(clk)
256 begin
257 if rising_edge(clk) then
258 if reset = '1' then
259 sample_clk_counter <= (others => '0');
260 sample_clk <= '0';
261 else
262 if sample_clk_divisor /= x"00" then
263 if sample_clk_counter = sample_clk_divisor then
264 sample_clk_counter <= (others => '0');
265 sample_clk <= '1';
266 else
267 sample_clk_counter <= std_logic_vector(unsigned(sample_clk_counter) + 1);
268 sample_clk <= '0';
269 end if;
270 end if;
271 end if;
272 end if;
273 end process sample_clock_generator;
274
275 ---------- Data Buffers ----------
276
277 send_buffer: entity work.pp_fifo
278 generic map(
279 DEPTH => FIFO_DEPTH,
280 WIDTH => 8
281 ) port map(
282 clk => clk,
283 reset => reset,
284 full => send_buffer_full,
285 empty => send_buffer_empty,
286 data_in => send_buffer_input,
287 data_out => send_buffer_output,
288 push => send_buffer_push,
289 pop => send_buffer_pop
290 );
291
292 recv_buffer: entity work.pp_fifo
293 generic map(
294 DEPTH => FIFO_DEPTH,
295 WIDTH => 8
296 ) port map(
297 clk => clk,
298 reset => reset,
299 full => recv_buffer_full,
300 empty => recv_buffer_empty,
301 data_in => recv_buffer_input,
302 data_out => recv_buffer_output,
303 push => recv_buffer_push,
304 pop => recv_buffer_pop
305 );
306
307 ---------- Wishbone Interface ----------
308
309 wb_ack_out <= wb_ack and wb_cyc_in and wb_stb_in;
310
311 wishbone: process(clk)
312 begin
313 if rising_edge(clk) then
314 if reset = '1' then
315 wb_ack <= '0';
316 wb_state <= IDLE;
317 send_buffer_push <= '0';
318 recv_buffer_pop <= '0';
319 sample_clk_divisor <= (others => '0');
320 irq_recv_enable <= '0';
321 irq_tx_ready_enable <= '0';
322 else
323 case wb_state is
324 when IDLE =>
325 if wb_cyc_in = '1' and wb_stb_in = '1' then
326 if wb_we_in = '1' then -- Write to register
327 if wb_adr_in = x"000" then
328 send_buffer_input <= wb_dat_in;
329 send_buffer_push <= '1';
330 elsif wb_adr_in = x"018" then
331 sample_clk_divisor <= wb_dat_in;
332 elsif wb_adr_in = x"020" then
333 irq_recv_enable <= wb_dat_in(0);
334 irq_tx_ready_enable <= wb_dat_in(1);
335 end if;
336
337 -- Invalid writes are acked and ignored.
338
339 wb_ack <= '1';
340 wb_state <= WRITE_ACK;
341 else -- Read from register
342 if wb_adr_in = x"008" then
343 recv_buffer_pop <= '1';
344 elsif wb_adr_in = x"010" then
345 wb_dat_out <= x"0" & send_buffer_full & recv_buffer_full & send_buffer_empty & recv_buffer_empty;
346 wb_ack <= '1';
347 elsif wb_adr_in = x"018" then
348 wb_dat_out <= sample_clk_divisor;
349 wb_ack <= '1';
350 elsif wb_adr_in = x"020" then
351 wb_dat_out <= (0 => irq_recv_enable, 1 => irq_tx_ready_enable, others => '0');
352 wb_ack <= '1';
353 else
354 wb_dat_out <= (others => '0');
355 wb_ack <= '1';
356 end if;
357 wb_state <= READ_ACK;
358 end if;
359 end if;
360 when WRITE_ACK =>
361 send_buffer_push <= '0';
362
363 if wb_stb_in = '0' then
364 wb_ack <= '0';
365 wb_state <= IDLE;
366 end if;
367 when READ_ACK =>
368 if recv_buffer_pop = '1' then
369 recv_buffer_pop <= '0';
370 else
371 wb_dat_out <= recv_buffer_output;
372 wb_ack <= '1';
373 end if;
374
375 if wb_stb_in = '0' then
376 wb_ack <= '0';
377 wb_state <= IDLE;
378 end if;
379 end case;
380 end if;
381 end if;
382 end process wishbone;
383
384 end architecture behaviour;