https://blackmesalabs.wordpress.com/2016/10/24/sump2-96-msps-logic-analyzer-for-22/
[BML_sump2] / sump2 / source / mesa_uart.v
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
5 -- Author:      khubbard\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
22 --\r
23 -- RXD    \START/<D0><D1><D2><..><D7>/STOP\r
24 -- Design Statistics after Packing\r
25 -- en_clr_lock = 1;\r
26 --    Number of LUTs  : 190 / 384\r
27 --    Number of DFFs  : 110 / 384\r
28 --\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
36                                                                                 \r
37 module mesa_uart\r
38 (\r
39   input  wire         reset,\r
40   input  wire         clk,\r
41   input  wire         clr_baudlock,\r
42   input  wire         en_autobaud,\r
43   output wire         flush,\r
44   input  wire         rxd,\r
45   output reg          txd,\r
46   output reg  [7:0]   dbg,\r
47   output wire [7:0]   rx_byte,\r
48   output reg          rx_rdy,\r
49   input  wire [7:0]   tx_byte,\r
50   input  wire         tx_en,\r
51   output reg          tx_busy,\r
52   output reg          tx_idle,\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
57 \r
58 \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
62   reg           sample_now;\r
63   reg           sample_now_p1;\r
64   reg           rxd_meta;\r
65   reg           rxd_loc;\r
66   wire          rxd_sample;\r
67   reg  [7:0]    rxd_sr;\r
68   reg           clr_bit_lock;\r
69   reg           dbg_sample_togl;\r
70   reg           dbg_sample_togl_p1;\r
71   reg           dbg_byte_togl;\r
72   reg           clr_jk;\r
73   reg           bad_jk;\r
74   reg           bit_lock_jk;\r
75   reg           bit_lock_jk_p1;\r
76   reg           baud_lock_jk;\r
77   reg           rx_byte_jk;\r
78   reg           rx_byte_jk_p1;\r
79 \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
84   reg           rx_cnt_16b_p1;\r
85   reg           rx_cnt_16b_roll;\r
86   reg           rx_start_a;\r
87   reg           rx_start_b;\r
88   reg           rx_cnt_en_a_jk;\r
89   reg           rx_cnt_en_b;\r
90   reg           rx_rdy_loc;\r
91   reg           rx_rdy_pre;\r
92   wire          en_loopback;\r
93   wire          en_fast_autobaud;\r
94   reg  [7:0]    tx_byte_loc;\r
95   reg           tx_en_loc;\r
96   reg  [9:0]    tx_sr;\r
97   reg           txd_loc;\r
98   reg           rxd_fal;\r
99   reg           rxd_ris;\r
100   reg  [7:0]    rxd_fal_sr;\r
101   reg           tx_shift;\r
102   reg           tx_now;\r
103   reg           rx_ascii_cr;\r
104   reg           rx_bad_symbol;\r
105   reg  [7:0]    dbg_loc;\r
106   reg  [7:0]    dbg_loc_p1;\r
107   reg  [3:0]    dbg_cnt;\r
108   reg           sample_first;\r
109 \r
110 \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
116 \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
120 \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
125  begin\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
140 \r
141    // Extend transitions for Saleae\r
142    if ( dbg_cnt != 4'hF ) begin\r
143      dbg_cnt <= dbg_cnt + 1;\r
144    end\r
145 \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
148      dbg_cnt <= 4'h0;\r
149    end\r
150    if ( reset == 1 ) begin\r
151      dbg_cnt <= 4'h0;\r
152    end\r
153 \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
158 \r
159  end \r
160 end // proc_din\r
161 \r
162 \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
169  begin\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
174    rxd_fal <= 0;\r
175    rxd_ris <= 0;\r
176 \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
181      rxd_fal <= 1;\r
182    end \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
187      rxd_ris <= 1;\r
188    end \r
189 \r
190  end \r
191 end // proc_din\r
192   assign rxd_sample = ~ rxd_sr[2];\r
193 \r
194 \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
199  begin\r
200 \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
206   end\r
207 \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
212   end else begin\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
215   end\r
216 \r
217   rx_cnt_16b[15:8] <= 8'd0;// 2016_10_17\r
218 \r
219  end\r
220 end // proc_cnt\r
221 \r
222 \r
223 \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
233  begin\r
234   sample_first   <= 0;\r
235   rx_start_a     <= 0;\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
239       rx_start_a     <= 1;\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
243       bit_lock_jk    <= 1;\r
244       rx_start_a     <= 1;\r
245       rx_cnt_en_a_jk <= 0;\r
246       sample_first   <= 1;\r
247     end\r
248   end else begin\r
249     rx_cnt_en_a_jk <= 0;\r
250   end\r
251 \r
252   if (   clr_bit_lock == 1 ) begin\r
253     bit_lock_jk <= 0;\r
254   end\r
255 \r
256   if ( en_fast_autobaud == 1 ) begin\r
257     baud_rate_loc[15:12] <= 4'd0;\r
258   end\r
259 \r
260 //if ( en_autobaud == 0 ) begin\r
261 //  baud_rate_loc <= 16'd43;\r
262 //  bit_lock_jk   <= 1;\r
263 //end\r
264 \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
272 \r
273  end\r
274 end // proc_s1 \r
275   assign flush = rx_ascii_cr;\r
276 \r
277 \r
278 //-----------------------------------------------------------------------------\r
279 // Decode the character bytes\r
280 //-----------------------------------------------------------------------------\r
281 always @ ( posedge clk ) begin : proc_s3 \r
282  begin\r
283    rx_ascii_cr   <= 0;\r
284    rx_bad_symbol <= 0;\r
285    clr_bit_lock  <= 0; \r
286    rx_rdy_loc    <= 0;\r
287    rx_rdy        <= rx_rdy_loc & baud_lock_jk;\r
288 \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
292        baud_lock_jk <= 1;\r
293        rx_ascii_cr  <= 1;\r
294        clr_jk <= 0;\r
295        bad_jk <= 0;\r
296      end else if ( baud_lock_jk == 0 ) begin\r
297        clr_bit_lock <= 1;\r
298      end\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
302      end\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
306      end\r
307    end\r
308 \r
309    // Grab received byte after last bit received\r
310    if ( sample_now_p1  == 1 && rx_bit_cnt == 4'd9 ) begin\r
311      rx_rdy_loc <= 1;\r
312    end\r
313 \r
314    if ( reset == 1 || rx_bad_symbol == 1 || clr_baudlock == 1 ) begin\r
315      baud_lock_jk <= 0;\r
316      clr_bit_lock <= 1;\r
317      rx_rdy_loc   <= 0;\r
318    end\r
319 \r
320 // if ( dbg_sample_togl != dbg_sample_togl_p1 ) begin\r
321 //   clr_jk <= 0;\r
322 //   bad_jk <= 0;\r
323 // end\r
324    if ( rx_bad_symbol == 1 ) begin\r
325      bad_jk <= 1;\r
326    end \r
327    if ( clr_baudlock == 1 ) begin\r
328      clr_jk <= 1;\r
329    end \r
330    if ( reset == 1 ) begin\r
331      clr_jk <= 0;\r
332      bad_jk <= 0;\r
333    end\r
334    \r
335 \r
336  end\r
337 end // proc_s3 \r
338 \r
339   assign rx_byte_loc = rx_byte_sr[8:1];\r
340   assign rx_byte     = rx_byte_sr[8:1];\r
341 \r
342 \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
347  begin\r
348   tx_en_loc     <= 0;\r
349   sample_now    <= 0;\r
350   rx_start_b    <= 0;\r
351   rx_cnt_en_b   <= 0;\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
355 \r
356   if ( rx_byte_jk == 0 ) begin\r
357     rx_bit_cnt <= 4'd0;\r
358     if ( rxd_fal == 1 ) begin\r
359       rx_start_b <= 1;\r
360       rx_byte_jk <= 1;// Starting a new Byte\r
361       dbg_byte_togl <= ~dbg_byte_togl;\r
362     end\r
363   end\r
364 \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
369     rx_cnt_en_b  <= 1;\r
370     if ( \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
376         rx_start_b <= 1;\r
377         sample_now <= 1;\r
378       end\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
381       rx_start_b <= 1;\r
382       sample_now <= 1;\r
383     end\r
384   end\r
385 \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
391   end\r
392 \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
397   end\r
398 \r
399   if ( sample_now_p1 == 1 && rx_bit_cnt == 4'd9  ) begin\r
400     rx_byte_jk <= 0;\r
401     rx_bit_cnt <= 4'd0;\r
402   end\r
403 \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
406     tx_en_loc   <= 1;\r
407   end else if ( tx_en == 1 ) begin\r
408     tx_byte_loc <= tx_byte[7:0];  \r
409     tx_en_loc   <= 1;\r
410   end\r
411 \r
412   if ( reset == 1 ) begin\r
413     rx_byte_jk <= 0;\r
414     rx_byte_sr[8:0] <= 9'd0;\r
415     dbg_sample_togl <= 0;\r
416     dbg_byte_togl <= 0;\r
417   end\r
418 \r
419  end\r
420 end // proc_s2 \r
421 \r
422 \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
427  begin\r
428   tx_shift <= 0;\r
429   tx_busy  <= 0;\r
430 //txd      <= txd_loc;\r
431   txd      <= tx_sr[0];\r
432   txd_loc  <= tx_sr[0];\r
433 //txd_loc  <= tx_sr[0] | ~ baud_lock;\r
434   tx_now   <= 0;\r
435 \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
440     tx_idle    <= 0;\r
441     tx_busy    <= 1;\r
442     tx_shift   <= 1;\r
443     tx_sr[9:0] <= { 1'b1, tx_byte_loc[7:0], 1'b0 };\r
444 \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
448     tx_busy    <= 1;\r
449     tx_idle    <= 0;\r
450     if ( tx_now == 1 ) begin\r
451       tx_shift   <= 1;\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
455     end\r
456   end else begin\r
457     tx_sr <= 10'H3FF;\r
458     if ( tx_now == 1 ) begin\r
459       tx_idle <= 1;\r
460     end else begin\r
461       tx_cnt_16b <= tx_cnt_16b + 1;\r
462     end\r
463   end\r
464 \r
465   if ( tx_cnt_16b[15:0] == baud_rate_loc[15:0] ) begin\r
466     tx_now <= 1;\r
467   end\r
468 \r
469   if ( reset == 1 ) begin\r
470     tx_bit_cnt <= 4'd0;\r
471     tx_idle    <= 1;\r
472   end\r
473 \r
474   if ( en_fast_autobaud == 1 ) begin\r
475     tx_cnt_16b[15:12] <= 4'd0;\r
476   end\r
477 \r
478  end\r
479 end // proc_tx\r
480 \r
481 \r
482 endmodule // mesa_uart\r