1 /* ****************************************************************************
\r
2 -- (C) Copyright 2015 Kevin M. Hubbard - Black Mesa Labs
\r
3 -- Source file: mesa_uart.v
\r
4 -- Date: June 1, 2015
\r
6 -- Description: A UART that autobauds to first "\n" 0x0A character.
\r
7 -- Language: Verilog-2001
\r
8 -- License: This project is licensed with the CERN Open Hardware Licence
\r
9 -- v1.2. You may redistribute and modify this project under the
\r
10 -- terms of the CERN OHL v.1.2. (http://ohwr.org/cernohl).
\r
11 -- This project is distributed WITHOUT ANY EXPRESS OR IMPLIED
\r
12 -- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY
\r
13 -- AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL
\r
14 -- v.1.2 for applicable Conditions.
\r
15 -- License: This project is licensed with the CERN Open Hardware Licence
\r
16 -- v1.2. You may redistribute and modify this project under the
\r
17 -- terms of the CERN OHL v.1.2. (http://ohwr.org/cernohl).
\r
18 -- This project is distributed WITHOUT ANY EXPRESS OR IMPLIED
\r
19 -- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY
\r
20 -- AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL
\r
21 -- v.1.2 for applicable Conditions.
\r
23 -- RXD \START/<D0><D1><D2><..><D7>/STOP
\r
24 -- Design Statistics after Packing
\r
26 -- Number of LUTs : 190 / 384
\r
27 -- Number of DFFs : 110 / 384
\r
29 -- Revision History:
\r
30 -- Ver# When Who What
\r
31 -- ---- -------- -------- ---------------------------------------------------
\r
32 -- 0.1 06.01.15 khubbard Creation
\r
33 -- 0.2 08.18.16 khubbard rx_sr[2:0] fix for metastable sampling issue.
\r
34 -- ***************************************************************************/
\r
35 //`default_nettype none // Strictly enforce all nets to be declared
\r
41 input wire clr_baudlock,
\r
42 input wire en_autobaud,
\r
46 output reg [7:0] dbg,
\r
47 output wire [7:0] rx_byte,
\r
49 input wire [7:0] tx_byte,
\r
53 output wire rx_idle,
\r
54 output wire [15:0] baud_rate,
\r
55 output wire baud_lock
\r
56 ); // module mesa_uart
\r
59 reg [8:0] rx_byte_sr;
\r
60 reg [3:0] rx_bit_cnt;
\r
61 reg [3:0] tx_bit_cnt;
\r
69 reg dbg_sample_togl;
\r
70 reg dbg_sample_togl_p1;
\r
80 wire [7:0] rx_byte_loc;
\r
81 reg [15:0] rx_cnt_16b;
\r
82 reg [15:0] tx_cnt_16b;
\r
83 reg [15:0] baud_rate_loc;
\r
85 reg rx_cnt_16b_roll;
\r
93 wire en_fast_autobaud;
\r
94 reg [7:0] tx_byte_loc;
\r
100 reg [7:0] rxd_fal_sr;
\r
106 reg [7:0] dbg_loc_p1;
\r
111 // Send RXD to TXD to test circuit
\r
112 assign en_loopback = 0;
\r
113 //assign en_fast_autobaud = 0;
\r
114 assign en_fast_autobaud = 1;
\r
115 assign rx_idle = 0;
\r
117 // When baud_lock asserts, send "\n" to downstream nodes for detection
\r
118 assign baud_rate = baud_rate_loc[15:0];
\r
119 assign baud_lock = baud_lock_jk;
\r
121 //-----------------------------------------------------------------------------
\r
122 // Output some debug signals for Saleae. Pulse extend short events
\r
123 //-----------------------------------------------------------------------------
\r
124 always @ ( posedge clk ) begin : proc_dbg
\r
126 // dbg_loc[0] <= ~ rxd_meta;
\r
127 dbg_loc[0] <= rxd_sample;
\r
128 dbg_loc[1] <= txd_loc;
\r
129 dbg_loc[2] <= bit_lock_jk;
\r
130 dbg_loc[3] <= baud_lock_jk;
\r
131 // dbg_loc[4] <= sample_now;
\r
132 dbg_loc[4] <= reset;
\r
133 // dbg_loc[5] <= rx_rdy_loc;
\r
134 dbg_loc[5] <= clr_jk;
\r
135 dbg_loc[6] <= dbg_sample_togl;
\r
136 dbg_loc[7] <= dbg_byte_togl;
\r
137 // dbg_loc[7] <= bad_jk;
\r
138 // dbg_loc[7] <= rx_ascii_cr;
\r
139 dbg_loc_p1 <= dbg_loc[7:0];
\r
141 // Extend transitions for Saleae
\r
142 if ( dbg_cnt != 4'hF ) begin
\r
143 dbg_cnt <= dbg_cnt + 1;
\r
146 if ( dbg_loc[7:4] != dbg_loc_p1[7:4] && dbg_cnt == 4'hF ) begin
\r
147 dbg <= dbg_loc[7:0];
\r
150 if ( reset == 1 ) begin
\r
154 dbg[0] <= dbg_loc[0];
\r
155 dbg[1] <= dbg_loc[1];
\r
156 dbg[2] <= dbg_loc[2];
\r
157 dbg[3] <= dbg_loc[3];
\r
163 //-----------------------------------------------------------------------------
\r
164 // Asynchronous sampling of RXD into 4 bit Shift Register
\r
165 // Note: RXD is immediately inverted to prevent runt '0's from pipeline
\r
166 // being detected as start bits. FPGA Flops powerup to '0', so inverting fixes.
\r
167 //-----------------------------------------------------------------------------
\r
168 always @ ( posedge clk ) begin : proc_din
\r
170 rxd_meta <= ~ rxd;// Note Inversion to prevent runt post config
\r
171 rxd_loc <= rxd_meta;
\r
172 // rxd_sr[7:0] <= { rxd_sr[6:0], rxd_meta };
\r
173 rxd_sr[7:0] <= { rxd_sr[6:0], rxd_loc };
\r
177 // if ( rxd_sr[3:0] == 4'b0001 ) begin
\r
178 // if ( rxd_sr[2:0] == 3'b001 ) begin
\r
179 // if ( rxd_sr[2:0] == 3'b011 ) begin
\r
180 if ( rxd_sr[7:6] == 2'b00 && rxd_sr[2:0] == 3'b011 ) begin
\r
183 // if ( rxd_sr[3:0] == 4'b1110 ) begin
\r
184 // if ( rxd_sr[2:0] == 3'b110 ) begin
\r
185 // if ( rxd_sr[2:0] == 3'b100 ) begin
\r
186 if ( rxd_sr[7:6] == 2'b11 && rxd_sr[2:0] == 3'b100 ) begin
\r
192 assign rxd_sample = ~ rxd_sr[2];
\r
195 //-----------------------------------------------------------------------------
\r
196 // 16bit Counter used for both rx_start_bit width count and sample count
\r
197 //-----------------------------------------------------------------------------
\r
198 always @ ( posedge clk ) begin : proc_cnt
\r
201 if ( rx_start_a == 1 || rx_start_b == 1 ) begin
\r
202 rx_cnt_16b <= 16'd0;
\r
203 end else if ( rx_cnt_en_a_jk == 1 ||
\r
204 rx_cnt_en_b == 1 ) begin
\r
205 rx_cnt_16b <= rx_cnt_16b + 1;
\r
208 if ( en_fast_autobaud == 1 ) begin
\r
209 rx_cnt_16b[15:12] <= 4'd0;
\r
210 rx_cnt_16b_p1 <= rx_cnt_16b[11];
\r
211 rx_cnt_16b_roll <= rx_cnt_16b_p1 & ~ rx_cnt_16b[11];
\r
213 rx_cnt_16b_p1 <= rx_cnt_16b[15];
\r
214 rx_cnt_16b_roll <= rx_cnt_16b_p1 & ~ rx_cnt_16b[15];
\r
217 rx_cnt_16b[15:8] <= 8'd0;// 2016_10_17
\r
224 //-----------------------------------------------------------------------------
\r
225 // Autobaud off "\n" character. Tricky, as both start bit at D0 are 0.
\r
226 // When there is no bit_lock, look for falling edge of RXD and count width of
\r
227 // StartBit and the 1st '0' of 0xA "\n" "01010000".
\r
228 // bit_lock remains on unless we don't get baud_lock
\r
229 // bit_lock == Think we know where to sample each symbol.
\r
230 // baud_lock == We sampled 8 symbols and got 0x0A or "\n"
\r
231 //-----------------------------------------------------------------------------
\r
232 always @ ( posedge clk ) begin : proc_s1
\r
236 bit_lock_jk_p1 <= bit_lock_jk;
\r
237 if ( bit_lock_jk == 0 && baud_lock_jk == 0 ) begin
\r
238 if ( rxd_fal == 1 ) begin
\r
240 rx_cnt_en_a_jk <= 1;
\r
241 end else if ( rxd_ris == 1 && rx_cnt_en_a_jk == 1 ) begin
\r
242 baud_rate_loc <= { 1'b0, rx_cnt_16b[15:1] } - 16'd1;// Div2 Shift
\r
245 rx_cnt_en_a_jk <= 0;
\r
249 rx_cnt_en_a_jk <= 0;
\r
252 if ( clr_bit_lock == 1 ) begin
\r
256 if ( en_fast_autobaud == 1 ) begin
\r
257 baud_rate_loc[15:12] <= 4'd0;
\r
260 //if ( en_autobaud == 0 ) begin
\r
261 // baud_rate_loc <= 16'd43;
\r
262 // bit_lock_jk <= 1;
\r
265 // fix baud rate for smaller design. Note the subtract-2
\r
266 //baud_rate_loc[15:0] <= 16'd109;// 100 MHz / 921600 baud
\r
267 //baud_rate_loc[15:0] <= 16'd104;// 96 MHz / 921600 baud = WORKS
\r
268 //baud_rate_loc[15:0] <= 16'd104;// 12 MHz / 115200 baud = WORKS
\r
269 baud_rate_loc[15:0] <= 16'd24;// 24 MHz / 921600 baud = WORKS
\r
270 //baud_rate_loc[15:0] <= 16'd12;// 12 MHz / 921600 baud = DOESNT WORK
\r
271 //bit_lock_jk <= 1;
\r
275 assign flush = rx_ascii_cr;
\r
278 //-----------------------------------------------------------------------------
\r
279 // Decode the character bytes
\r
280 //-----------------------------------------------------------------------------
\r
281 always @ ( posedge clk ) begin : proc_s3
\r
284 rx_bad_symbol <= 0;
\r
285 clr_bit_lock <= 0;
\r
287 rx_rdy <= rx_rdy_loc & baud_lock_jk;
\r
289 // Assert baud_lock if 1st char is "\n" else clear and start over.
\r
290 if ( sample_now_p1 == 1 && rx_bit_cnt == 4'd9 ) begin
\r
291 if ( rx_byte_loc[7:0] == 8'h0a ) begin
\r
296 end else if ( baud_lock_jk == 0 ) begin
\r
299 // Only expect ASCII 0x20 - 0x7F, detect 0x80+ as bad and clear baud lock
\r
300 if ( rx_byte_loc[7] == 1 ) begin
\r
301 rx_bad_symbol <= 1;
\r
303 // Only expect ASCII 0x20 - 0x7F, detect under 0x20 and clear baud lock
\r
304 if ( rx_byte_loc != 8'h0A && rx_byte_loc < 8'h20 ) begin
\r
305 rx_bad_symbol <= 1;
\r
309 // Grab received byte after last bit received
\r
310 if ( sample_now_p1 == 1 && rx_bit_cnt == 4'd9 ) begin
\r
314 if ( reset == 1 || rx_bad_symbol == 1 || clr_baudlock == 1 ) begin
\r
320 // if ( dbg_sample_togl != dbg_sample_togl_p1 ) begin
\r
324 if ( rx_bad_symbol == 1 ) begin
\r
327 if ( clr_baudlock == 1 ) begin
\r
330 if ( reset == 1 ) begin
\r
339 assign rx_byte_loc = rx_byte_sr[8:1];
\r
340 assign rx_byte = rx_byte_sr[8:1];
\r
343 //-----------------------------------------------------------------------------
\r
344 // look for falling edge of rx_start_bit and count 1/2 way into bit and sample
\r
345 //-----------------------------------------------------------------------------
\r
346 always @ ( posedge clk ) begin : proc_s2
\r
352 rx_byte_jk_p1 <= rx_byte_jk;
\r
353 sample_now_p1 <= sample_now;
\r
354 dbg_sample_togl_p1 <= dbg_sample_togl;
\r
356 if ( rx_byte_jk == 0 ) begin
\r
357 rx_bit_cnt <= 4'd0;
\r
358 if ( rxd_fal == 1 ) begin
\r
360 rx_byte_jk <= 1;// Starting a new Byte
\r
361 dbg_byte_togl <= ~dbg_byte_togl;
\r
365 // When to start sample_now is tricky as for bit_lock, it is 1/2 baud into
\r
366 // the D1 data bit of \n, after lock, it is 1/2 baud into D0 data bit.
\r
367 // cnt=0 is StartBit, cnt=1 is D0, cnt=2 is D1
\r
368 if ( bit_lock_jk == 1 && rx_byte_jk == 1 ) begin
\r
371 ( baud_lock_jk == 0 && rx_bit_cnt == 4'd2 ) ||
\r
372 ( baud_lock_jk == 1 && rx_bit_cnt == 4'd1 ) ) begin
\r
373 // Div-2 baud count to sample middle of eye
\r
374 if ( rx_cnt_16b[15:0] == { 1'b0, baud_rate_loc[15:1] } ) begin
\r
375 rx_bit_cnt <= rx_bit_cnt + 1;
\r
379 end else if ( rx_cnt_16b[15:0] == baud_rate_loc[15:0] ) begin
\r
380 rx_bit_cnt <= rx_bit_cnt + 1;
\r
386 // Assume "\n" and stuff the 1st 0 since it already flew by
\r
387 if ( sample_first == 1 ) begin
\r
388 rx_bit_cnt <= 4'd2;
\r
389 rx_byte_sr[8] <= 0;
\r
390 rx_byte_sr[7:0] <= rx_byte_sr[8:1];
\r
393 if ( sample_now == 1 ) begin
\r
394 rx_byte_sr[8] <= rxd_sample;
\r
395 rx_byte_sr[7:0] <= rx_byte_sr[8:1];
\r
396 dbg_sample_togl <= ~dbg_sample_togl;
\r
399 if ( sample_now_p1 == 1 && rx_bit_cnt == 4'd9 ) begin
\r
401 rx_bit_cnt <= 4'd0;
\r
404 if ( rx_rdy_loc == 1 && baud_lock_jk == 1 && en_loopback == 1 ) begin
\r
405 tx_byte_loc <= rx_byte_loc[7:0];
\r
407 end else if ( tx_en == 1 ) begin
\r
408 tx_byte_loc <= tx_byte[7:0];
\r
412 if ( reset == 1 ) begin
\r
414 rx_byte_sr[8:0] <= 9'd0;
\r
415 dbg_sample_togl <= 0;
\r
416 dbg_byte_togl <= 0;
\r
423 //-----------------------------------------------------------------------------
\r
424 // TX : Load 8bits into 10bit SR and shift out at the RX baud rate
\r
425 //-----------------------------------------------------------------------------
\r
426 always @ ( posedge clk ) begin : proc_tx
\r
432 txd_loc <= tx_sr[0];
\r
433 //txd_loc <= tx_sr[0] | ~ baud_lock;
\r
436 // Load a new Byte to send
\r
437 if ( tx_en_loc == 1 ) begin
\r
438 tx_bit_cnt <= 4'd10;
\r
439 tx_cnt_16b <= 16'h0000;
\r
443 tx_sr[9:0] <= { 1'b1, tx_byte_loc[7:0], 1'b0 };
\r
445 // Shift and send the byte until bit_cnt goes to 0
\r
446 end else if ( tx_bit_cnt != 4'd0 ) begin
\r
447 tx_cnt_16b <= tx_cnt_16b + 1;
\r
450 if ( tx_now == 1 ) begin
\r
452 tx_bit_cnt <= tx_bit_cnt[3:0] - 1;
\r
453 tx_cnt_16b <= 16'h0000;
\r
454 tx_sr[9:0] <= { 1'b1, tx_sr[9:1] };
\r
458 if ( tx_now == 1 ) begin
\r
461 tx_cnt_16b <= tx_cnt_16b + 1;
\r
465 if ( tx_cnt_16b[15:0] == baud_rate_loc[15:0] ) begin
\r
469 if ( reset == 1 ) begin
\r
470 tx_bit_cnt <= 4'd0;
\r
474 if ( en_fast_autobaud == 1 ) begin
\r
475 tx_cnt_16b[15:12] <= 4'd0;
\r
482 endmodule // mesa_uart
\r