Merge pull request #273 from antonblanchard/wishbone-checking
[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 rxd2 : std_logic := '1';
111 signal rxd3 : std_logic := '1';
112 signal txd2 : std_ulogic := '1';
113 begin
114
115 irq <= (irq_recv_enable and (not recv_buffer_empty))
116 or (irq_tx_ready_enable and send_buffer_empty);
117
118 ---------- UART receive ----------
119
120 recv_buffer_input <= rx_byte;
121
122 -- Add a few FFs on the RX input to avoid metastability issues
123 process (clk) is
124 begin
125 if rising_edge(clk) then
126 rxd3 <= rxd2;
127 rxd2 <= rxd;
128 end if;
129 end process;
130 txd <= txd2;
131
132 uart_receive: process(clk)
133 begin
134 if rising_edge(clk) then
135 if reset = '1' then
136 rx_state <= IDLE;
137 recv_buffer_push <= '0';
138 else
139 case rx_state is
140 when IDLE =>
141 if recv_buffer_push = '1' then
142 recv_buffer_push <= '0';
143 end if;
144
145 if sample_clk = '1' and rxd3 = '0' then
146 rx_sample_value <= rx_sample_counter;
147 rx_sample_delay <= 0;
148 rx_current_bit <= 0;
149 rx_state <= STARTBIT;
150 end if;
151 when STARTBIT =>
152 if sample_clk = '1' then
153 if rx_sample_delay = 7 then
154 rx_state <= RECEIVE;
155 rx_sample_value <= rx_sample_counter;
156 rx_sample_delay <= 0;
157 else
158 rx_sample_delay <= rx_sample_delay + 1;
159 end if;
160 end if;
161 when RECEIVE =>
162 if sample_clk = '1' and rx_sample_counter = rx_sample_value then
163 if rx_current_bit /= 7 then
164 rx_byte(rx_current_bit) <= rxd3;
165 rx_current_bit <= rx_current_bit + 1;
166 else
167 rx_byte(rx_current_bit) <= rxd3;
168 rx_state <= STOPBIT;
169 end if;
170 end if;
171 when STOPBIT =>
172 if sample_clk = '1' and rx_sample_counter = rx_sample_value then
173 rx_state <= IDLE;
174
175 if recv_buffer_full = '0' then
176 recv_buffer_push <= '1';
177 end if;
178 end if;
179 end case;
180 end if;
181 end if;
182 end process uart_receive;
183
184 sample_counter: process(clk)
185 begin
186 if rising_edge(clk) then
187 if reset = '1' then
188 rx_sample_counter <= 0;
189 elsif sample_clk = '1' then
190 if rx_sample_counter = 15 then
191 rx_sample_counter <= 0;
192 else
193 rx_sample_counter <= rx_sample_counter + 1;
194 end if;
195 end if;
196 end if;
197 end process sample_counter;
198
199 ---------- UART transmit ----------
200
201 tx_byte <= send_buffer_output;
202
203 uart_transmit: process(clk)
204 begin
205 if rising_edge(clk) then
206 if reset = '1' then
207 txd2 <= '1';
208 tx_state <= IDLE;
209 send_buffer_pop <= '0';
210 tx_current_bit <= 0;
211 else
212 case tx_state is
213 when IDLE =>
214 if send_buffer_empty = '0' and uart_tx_clk = '1' then
215 txd2 <= '0';
216 send_buffer_pop <= '1';
217 tx_current_bit <= 0;
218 tx_state <= TRANSMIT;
219 elsif uart_tx_clk = '1' then
220 txd2 <= '1';
221 end if;
222 when TRANSMIT =>
223 if send_buffer_pop = '1' then
224 send_buffer_pop <= '0';
225 elsif uart_tx_clk = '1' and tx_current_bit = 7 then
226 txd2 <= tx_byte(tx_current_bit);
227 tx_state <= STOPBIT;
228 elsif uart_tx_clk = '1' then
229 txd2 <= tx_byte(tx_current_bit);
230 tx_current_bit <= tx_current_bit + 1;
231 end if;
232 when STOPBIT =>
233 if uart_tx_clk = '1' then
234 txd2 <= '1';
235 tx_state <= IDLE;
236 end if;
237 end case;
238 end if;
239 end if;
240 end process uart_transmit;
241
242 uart_tx_clock_generator: process(clk)
243 begin
244 if rising_edge(clk) then
245 if reset = '1' then
246 uart_tx_counter <= 0;
247 uart_tx_clk <= '0';
248 else
249 if sample_clk = '1' then
250 if uart_tx_counter = 15 then
251 uart_tx_counter <= 0;
252 uart_tx_clk <= '1';
253 else
254 uart_tx_counter <= uart_tx_counter + 1;
255 uart_tx_clk <= '0';
256 end if;
257 else
258 uart_tx_clk <= '0';
259 end if;
260 end if;
261 end if;
262 end process uart_tx_clock_generator;
263
264 ---------- Sample clock generator ----------
265
266 sample_clock_generator: process(clk)
267 begin
268 if rising_edge(clk) then
269 if reset = '1' then
270 sample_clk_counter <= (others => '0');
271 sample_clk <= '0';
272 else
273 if sample_clk_divisor /= x"00" then
274 if sample_clk_counter = sample_clk_divisor then
275 sample_clk_counter <= (others => '0');
276 sample_clk <= '1';
277 else
278 sample_clk_counter <= std_logic_vector(unsigned(sample_clk_counter) + 1);
279 sample_clk <= '0';
280 end if;
281 end if;
282 end if;
283 end if;
284 end process sample_clock_generator;
285
286 ---------- Data Buffers ----------
287
288 send_buffer: entity work.pp_fifo
289 generic map(
290 DEPTH => FIFO_DEPTH,
291 WIDTH => 8
292 ) port map(
293 clk => clk,
294 reset => reset,
295 full => send_buffer_full,
296 empty => send_buffer_empty,
297 data_in => send_buffer_input,
298 data_out => send_buffer_output,
299 push => send_buffer_push,
300 pop => send_buffer_pop
301 );
302
303 recv_buffer: entity work.pp_fifo
304 generic map(
305 DEPTH => FIFO_DEPTH,
306 WIDTH => 8
307 ) port map(
308 clk => clk,
309 reset => reset,
310 full => recv_buffer_full,
311 empty => recv_buffer_empty,
312 data_in => recv_buffer_input,
313 data_out => recv_buffer_output,
314 push => recv_buffer_push,
315 pop => recv_buffer_pop
316 );
317
318 ---------- Wishbone Interface ----------
319
320 wishbone: process(clk)
321 begin
322 if rising_edge(clk) then
323 if reset = '1' then
324 wb_ack_out <= '0';
325 wb_state <= IDLE;
326 send_buffer_push <= '0';
327 recv_buffer_pop <= '0';
328 sample_clk_divisor <= (others => '0');
329 irq_recv_enable <= '0';
330 irq_tx_ready_enable <= '0';
331 else
332 case wb_state is
333 when IDLE =>
334 if wb_cyc_in = '1' and wb_stb_in = '1' then
335 if wb_we_in = '1' then -- Write to register
336 if wb_adr_in = x"000" then
337 send_buffer_input <= wb_dat_in;
338 send_buffer_push <= '1';
339 elsif wb_adr_in = x"018" then
340 sample_clk_divisor <= wb_dat_in;
341 elsif wb_adr_in = x"020" then
342 irq_recv_enable <= wb_dat_in(0);
343 irq_tx_ready_enable <= wb_dat_in(1);
344 end if;
345
346 -- Invalid writes are acked and ignored.
347 wb_ack_out <= '1';
348 wb_state <= WRITE_ACK;
349 else -- Read from register
350 if wb_adr_in = x"008" then
351 recv_buffer_pop <= '1';
352 elsif wb_adr_in = x"010" then
353 wb_dat_out <= x"0" & send_buffer_full & recv_buffer_full &
354 send_buffer_empty & recv_buffer_empty;
355 wb_ack_out <= '1';
356 elsif wb_adr_in = x"018" then
357 wb_dat_out <= sample_clk_divisor;
358 wb_ack_out <= '1';
359 elsif wb_adr_in = x"020" then
360 wb_dat_out <= (0 => irq_recv_enable,
361 1 => irq_tx_ready_enable,
362 others => '0');
363 wb_ack_out <= '1';
364 else
365 wb_dat_out <= (others => '0');
366 wb_ack_out <= '1';
367 end if;
368 wb_state <= READ_ACK;
369 end if;
370 end if;
371 when WRITE_ACK =>
372 send_buffer_push <= '0';
373
374 if wb_stb_in = '0' then
375 wb_ack_out <= '0';
376 wb_state <= IDLE;
377 end if;
378 when READ_ACK =>
379 if recv_buffer_pop = '1' then
380 recv_buffer_pop <= '0';
381 else
382 wb_dat_out <= recv_buffer_output;
383 wb_ack_out <= '1';
384 end if;
385
386 if wb_stb_in = '0' then
387 wb_ack_out <= '0';
388 wb_state <= IDLE;
389 end if;
390 end case;
391 end if;
392 end if;
393 end process wishbone;
394
395 end architecture behaviour;