OpenCores
URL https://opencores.org/ocsvn/wbuart32/wbuart32/trunk

Subversion Repositories wbuart32

[/] [wbuart32/] [trunk/] [rtl/] [rxuartlite.v] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    rxuartlite.v
4
//
5
// Project:     wbuart32, a full featured UART with simulator
6
//
7
// Purpose:     Receive and decode inputs from a single UART line.
8
//
9
//
10
//      To interface with this module, connect it to your system clock,
11
//      and a UART input.  Set the parameter to the number of clocks per
12
//      baud.  When data becomes available, the o_wr line will be asserted
13
//      for one clock cycle.
14
//
15
//      This interface only handles 8N1 serial port communications.  It does
16
//      not handle the break, parity, or frame error conditions.
17
//
18
//
19
// Creator:     Dan Gisselquist, Ph.D.
20
//              Gisselquist Technology, LLC
21
//
22
////////////////////////////////////////////////////////////////////////////////
23
//
24 26 dgisselq
// Copyright (C) 2015-2019, Gisselquist Technology, LLC
25 15 dgisselq
//
26
// This program is free software (firmware): you can redistribute it and/or
27
// modify it under the terms of  the GNU General Public License as published
28
// by the Free Software Foundation, either version 3 of the License, or (at
29
// your option) any later version.
30
//
31
// This program is distributed in the hope that it will be useful, but WITHOUT
32
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
33
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
34
// for more details.
35
//
36
// You should have received a copy of the GNU General Public License along
37
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
38
// target there if the PDF file isn't present.)  If not, see
39
// <http://www.gnu.org/licenses/> for a copy.
40
//
41
// License:     GPL, v3, as defined and found on www.gnu.org,
42
//              http://www.gnu.org/licenses/gpl.html
43
//
44
//
45
////////////////////////////////////////////////////////////////////////////////
46
//
47
//
48 17 dgisselq
`default_nettype        none
49
//
50
`define RXUL_BIT_ZERO           4'h0
51
`define RXUL_BIT_ONE            4'h1
52
`define RXUL_BIT_TWO            4'h2
53
`define RXUL_BIT_THREE          4'h3
54
`define RXUL_BIT_FOUR           4'h4
55
`define RXUL_BIT_FIVE           4'h5
56
`define RXUL_BIT_SIX            4'h6
57
`define RXUL_BIT_SEVEN          4'h7
58
`define RXUL_STOP               4'h8
59 21 dgisselq
`define RXUL_WAIT               4'h9
60 17 dgisselq
`define RXUL_IDLE               4'hf
61 15 dgisselq
 
62
module rxuartlite(i_clk, i_uart_rx, o_wr, o_data);
63 21 dgisselq
        parameter                       TIMER_BITS = 10;
64 26 dgisselq
`ifdef  FORMAL
65
        parameter  [(TIMER_BITS-1):0]    CLOCKS_PER_BAUD = 16; // Necessary for formal proof
66
`else
67 21 dgisselq
        parameter  [(TIMER_BITS-1):0]    CLOCKS_PER_BAUD = 868;  // 115200 MBaud at 100MHz
68 26 dgisselq
`endif
69 21 dgisselq
        localparam                      TB = TIMER_BITS;
70 17 dgisselq
        input   wire            i_clk;
71
        input   wire            i_uart_rx;
72 15 dgisselq
        output  reg             o_wr;
73
        output  reg     [7:0]    o_data;
74
 
75
 
76 21 dgisselq
        wire    [(TB-1):0]       half_baud;
77
        reg     [3:0]            state;
78 15 dgisselq
 
79 21 dgisselq
        assign  half_baud = { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] };
80
        reg     [(TB-1):0]       baud_counter;
81
        reg                     zero_baud_counter;
82 15 dgisselq
 
83
 
84
        // Since this is an asynchronous receiver, we need to register our
85
        // input a couple of clocks over to avoid any problems with 
86
        // metastability.  We do that here, and then ignore all but the
87
        // ck_uart wire.
88
        reg     q_uart, qq_uart, ck_uart;
89 21 dgisselq
        initial q_uart  = 1'b1;
90
        initial qq_uart = 1'b1;
91
        initial ck_uart = 1'b1;
92 15 dgisselq
        always @(posedge i_clk)
93 21 dgisselq
                { ck_uart, qq_uart, q_uart } <= { qq_uart, q_uart, i_uart_rx };
94 15 dgisselq
 
95
        // Keep track of the number of clocks since the last change.
96
        //
97
        // This is used to determine if we are in either a break or an idle
98
        // condition, as discussed further below.
99 21 dgisselq
        reg     [(TB-1):0]       chg_counter;
100
        initial chg_counter = {(TB){1'b1}};
101 15 dgisselq
        always @(posedge i_clk)
102 26 dgisselq
        if (qq_uart != ck_uart)
103
                chg_counter <= 0;
104
        else if (chg_counter != { (TB){1'b1} })
105
                chg_counter <= chg_counter + 1;
106 15 dgisselq
 
107
        // Are we in the middle of a baud iterval?  Specifically, are we
108
        // in the middle of a start bit?  Set this to high if so.  We'll use
109
        // this within our state machine to transition out of the IDLE
110
        // state.
111
        reg     half_baud_time;
112
        initial half_baud_time = 0;
113
        always @(posedge i_clk)
114 21 dgisselq
                half_baud_time <= (!ck_uart)&&(chg_counter >= half_baud-1'b1-1'b1);
115 15 dgisselq
 
116
 
117 17 dgisselq
        initial state = `RXUL_IDLE;
118 15 dgisselq
        always @(posedge i_clk)
119 26 dgisselq
        if (state == `RXUL_IDLE)
120
        begin // Idle state, independent of baud counter
121
                // By default, just stay in the IDLE state
122
                state <= `RXUL_IDLE;
123
                if ((!ck_uart)&&(half_baud_time))
124
                        // UNLESS: We are in the center of a valid
125
                        // start bit
126
                        state <= `RXUL_BIT_ZERO;
127
        end else if ((state >= `RXUL_WAIT)&&(ck_uart))
128
                state <= `RXUL_IDLE;
129
        else if (zero_baud_counter)
130 15 dgisselq
        begin
131 26 dgisselq
                if (state <= `RXUL_STOP)
132
                        // Data arrives least significant bit first.
133
                        // By the time this is clocked in, it's what
134
                        // you'll have.
135
                        state <= state + 1;
136 15 dgisselq
        end
137
 
138
        // Data bit capture logic.
139
        //
140
        // This is drastically simplified from the state machine above, based
141
        // upon: 1) it doesn't matter what it is until the end of a captured
142
        // byte, and 2) the data register will flush itself of any invalid
143
        // data in all other cases.  Hence, let's keep it real simple.
144
        reg     [7:0]    data_reg;
145
        always @(posedge i_clk)
146 26 dgisselq
        if ((zero_baud_counter)&&(state != `RXUL_STOP))
147
                data_reg <= { qq_uart, data_reg[7:1] };
148 15 dgisselq
 
149
        // Our data bit logic doesn't need nearly the complexity of all that
150
        // work above.  Indeed, we only need to know if we are at the end of
151
        // a stop bit, in which case we copy the data_reg into our output
152
        // data register, o_data, and tell others (for one clock) that data is
153
        // available.
154
        //
155 21 dgisselq
        initial o_wr = 1'b0;
156 15 dgisselq
        initial o_data = 8'h00;
157
        always @(posedge i_clk)
158 26 dgisselq
        if ((zero_baud_counter)&&(state == `RXUL_STOP)&&(ck_uart))
159
        begin
160
                o_wr   <= 1'b1;
161
                o_data <= data_reg;
162
        end else
163
                o_wr   <= 1'b0;
164 15 dgisselq
 
165
        // The baud counter
166
        //
167
        // This is used as a "clock divider" if you will, but the clock needs
168
        // to be reset before any byte can be decoded.  In all other respects,
169 18 dgisselq
        // we set ourselves up for CLOCKS_PER_BAUD counts between baud
170 15 dgisselq
        // intervals.
171 21 dgisselq
        initial baud_counter = 0;
172 15 dgisselq
        always @(posedge i_clk)
173 26 dgisselq
        if (((state==`RXUL_IDLE))&&(!ck_uart)&&(half_baud_time))
174
                baud_counter <= CLOCKS_PER_BAUD-1'b1;
175
        else if (state == `RXUL_WAIT)
176
                baud_counter <= 0;
177
        else if ((zero_baud_counter)&&(state < `RXUL_STOP))
178
                baud_counter <= CLOCKS_PER_BAUD-1'b1;
179
        else if (!zero_baud_counter)
180
                baud_counter <= baud_counter-1'b1;
181 15 dgisselq
 
182
        // zero_baud_counter
183
        //
184
        // Rather than testing whether or not (baud_counter == 0) within our
185
        // (already too complicated) state transition tables, we use
186
        // zero_baud_counter to pre-charge that test on the clock
187
        // before--cleaning up some otherwise difficult timing dependencies.
188 21 dgisselq
        initial zero_baud_counter = 1'b1;
189 15 dgisselq
        always @(posedge i_clk)
190 26 dgisselq
        if ((state == `RXUL_IDLE)&&(!ck_uart)&&(half_baud_time))
191
                zero_baud_counter <= 1'b0;
192
        else if (state == `RXUL_WAIT)
193
                zero_baud_counter <= 1'b1;
194
        else if ((zero_baud_counter)&&(state < `RXUL_STOP))
195
                zero_baud_counter <= 1'b0;
196
        else if (baud_counter == 1)
197
                zero_baud_counter <= 1'b1;
198 21 dgisselq
 
199
`ifdef  FORMAL
200
`define FORMAL_VERILATOR
201
`else
202
`ifdef  VERILATOR
203
`define FORMAL_VERILATOR
204
`endif
205
`endif
206
 
207
`ifdef  FORMAL
208 23 dgisselq
`define ASSUME  assume
209 26 dgisselq
`define ASSERT  assert
210
`ifdef  VERIFIC
211
        (* gclk *) wire gbl_clk;
212
        global clocking @(posedge gbl_clk); endclocking
213
`endif
214 23 dgisselq
 
215 21 dgisselq
 
216
        localparam      F_CKRES = 10;
217
 
218 26 dgisselq
        (* anyseq *) wire       f_tx_start;
219
        (* anyconst *) wire     [(F_CKRES-1):0]  f_tx_step;
220 21 dgisselq
        reg                     f_tx_zclk;
221
        reg     [(TB-1):0]       f_tx_timer;
222
        wire    [7:0]            f_rx_newdata;
223
        reg     [(TB-1):0]       f_tx_baud;
224
        wire                    f_tx_zbaud;
225
 
226
        wire    [(TB-1):0]       f_max_baud_difference;
227
        reg     [(TB-1):0]       f_baud_difference;
228
        reg     [(TB+3):0]       f_tx_count, f_rx_count;
229 26 dgisselq
        (* anyseq *) wire       [7:0]            f_tx_data;
230 21 dgisselq
 
231
 
232
 
233
        wire                    f_txclk;
234
        reg     [1:0]            f_rx_clock;
235
        reg     [(F_CKRES-1):0]  f_tx_clock;
236
        reg                     f_past_valid, f_past_valid_tx;
237
 
238
        initial f_past_valid = 1'b0;
239
        always @(posedge i_clk)
240
                f_past_valid <= 1'b1;
241
 
242
        initial f_rx_clock = 3'h0;
243
        always @($global_clock)
244
                f_rx_clock <= f_rx_clock + 1'b1;
245
 
246
        always @(*)
247
                assume(i_clk == f_rx_clock[1]);
248
 
249
 
250
 
251
        ///////////////////////////////////////////////////////////
252
        //
253
        //
254
        // Generate a transmitted signal
255
        //
256
        //
257
        ///////////////////////////////////////////////////////////
258
 
259
 
260
        // First, calculate the transmit clock
261
        localparam [(F_CKRES-1):0] F_MIDSTEP = { 2'b01, {(F_CKRES-2){1'b0}} };
262
        //
263
        // Need to allow us to slip by half a baud clock over 10 baud intervals
264
        //
265
        // (F_STEP / (2^F_CKRES)) * (CLOCKS_PER_BAUD)*10 < CLOCKS_PER_BAUD/2
266
        // F_STEP * 2 * 10 < 2^F_CKRES
267
        localparam [(F_CKRES-1):0] F_HALFSTEP= F_MIDSTEP/32;
268
        localparam [(F_CKRES-1):0] F_MINSTEP = F_MIDSTEP - F_HALFSTEP + 1;
269
        localparam [(F_CKRES-1):0] F_MAXSTEP = F_MIDSTEP + F_HALFSTEP - 1;
270
 
271
        initial assert(F_MINSTEP <= F_MIDSTEP);
272
        initial assert(F_MIDSTEP <= F_MAXSTEP);
273
 
274
        //      assume((f_tx_step >= F_MINSTEP)&&(f_tx_step <= F_MAXSTEP));
275
        //
276
        //
277
        always @(*) assume((f_tx_step == F_MINSTEP)
278
                        ||(f_tx_step == F_MIDSTEP)
279
                        ||(f_tx_step == F_MAXSTEP));
280
 
281
        always @($global_clock)
282
                f_tx_clock <= f_tx_clock + f_tx_step;
283
 
284
        assign  f_txclk = f_tx_clock[F_CKRES-1];
285
        // 
286
        initial f_past_valid_tx = 1'b0;
287
        always @(posedge f_txclk)
288
                f_past_valid_tx <= 1'b1;
289
 
290
        initial assume(i_uart_rx);
291
 
292
 
293
        //////////////////////////////////////////////
294
        //
295
        //
296
        // Build a simulated transmitter
297
        //
298
        //
299
        //////////////////////////////////////////////
300
        //
301
        // First, the simulated timing generator
302
 
303
        // parameter    TIMER_BITS = 10;
304
        // parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 868;
305
        // localparam   TB = TIMER_BITS;
306
 
307
        always @(*)
308
        if (f_tx_busy)
309
                assume(!f_tx_start);
310
 
311
        initial f_tx_baud = 0;
312
        always @(posedge f_txclk)
313
        if ((f_tx_zbaud)&&((f_tx_busy)||(f_tx_start)))
314
                f_tx_baud <= CLOCKS_PER_BAUD-1'b1;
315
        else if (!f_tx_zbaud)
316
                f_tx_baud <= f_tx_baud - 1'b1;
317
 
318
        always @(*)
319 26 dgisselq
                `ASSERT(f_tx_baud < CLOCKS_PER_BAUD);
320 21 dgisselq
 
321
        always @(*)
322
        if (!f_tx_busy)
323 26 dgisselq
                `ASSERT(f_tx_baud == 0);
324 21 dgisselq
 
325
        assign  f_tx_zbaud = (f_tx_baud == 0);
326
 
327
        // But only if we aren't busy
328
        initial assume(f_tx_data == 0);
329
        always @(posedge f_txclk)
330
        if ((!f_tx_zbaud)||(f_tx_busy)||(!f_tx_start))
331
                assume(f_tx_data == $past(f_tx_data));
332
 
333
        // Force the data to change on a clock only
334
        always @($global_clock)
335
        if ((f_past_valid)&&(!$rose(f_txclk)))
336
                assume($stable(f_tx_data));
337
        else if (f_tx_busy)
338
                assume($stable(f_tx_data));
339
 
340
        //
341
        always @($global_clock)
342
        if ((!f_past_valid)||(!$rose(f_txclk)))
343
        begin
344
                assume($stable(f_tx_start));
345
                assume($stable(f_tx_data));
346
        end
347
 
348
        //
349
        //
350
        //
351
 
352
        reg     [9:0]    f_tx_reg;
353
        reg             f_tx_busy;
354
 
355
        // Here's the transmitter itself (roughly)
356
        initial f_tx_busy   = 1'b0;
357
        initial f_tx_reg    = 0;
358
        always @(posedge f_txclk)
359
        if (!f_tx_zbaud)
360
        begin
361 26 dgisselq
                `ASSERT(f_tx_busy);
362 21 dgisselq
        end else begin
363
                f_tx_reg  <= { 1'b0, f_tx_reg[9:1] };
364
                if (f_tx_start)
365
                        f_tx_reg <= { 1'b1, f_tx_data, 1'b0 };
366
        end
367
 
368
        // Create a busy flag that we'll use
369
        always @(*)
370
        if (!f_tx_zbaud)
371
                f_tx_busy <= 1'b1;
372
        else if (|f_tx_reg)
373
                f_tx_busy <= 1'b1;
374
        else
375
                f_tx_busy <= 1'b0;
376
 
377
        //
378
        // Tie the TX register to the TX data
379
        always @(posedge f_txclk)
380
        if (f_tx_reg[9])
381 26 dgisselq
                `ASSERT(f_tx_reg[8:0] == { f_tx_data, 1'b0 });
382 21 dgisselq
        else if (f_tx_reg[8])
383 26 dgisselq
                `ASSERT(f_tx_reg[7:0] == f_tx_data[7:0] );
384 21 dgisselq
        else if (f_tx_reg[7])
385 26 dgisselq
                `ASSERT(f_tx_reg[6:0] == f_tx_data[7:1] );
386 21 dgisselq
        else if (f_tx_reg[6])
387 26 dgisselq
                `ASSERT(f_tx_reg[5:0] == f_tx_data[7:2] );
388 21 dgisselq
        else if (f_tx_reg[5])
389 26 dgisselq
                `ASSERT(f_tx_reg[4:0] == f_tx_data[7:3] );
390 21 dgisselq
        else if (f_tx_reg[4])
391 26 dgisselq
                `ASSERT(f_tx_reg[3:0] == f_tx_data[7:4] );
392 21 dgisselq
        else if (f_tx_reg[3])
393 26 dgisselq
                `ASSERT(f_tx_reg[2:0] == f_tx_data[7:5] );
394 21 dgisselq
        else if (f_tx_reg[2])
395 26 dgisselq
                `ASSERT(f_tx_reg[1:0] == f_tx_data[7:6] );
396 21 dgisselq
        else if (f_tx_reg[1])
397 26 dgisselq
                `ASSERT(f_tx_reg[0] == f_tx_data[7]);
398 21 dgisselq
 
399
        // Our counter since we start
400
        initial f_tx_count = 0;
401
        always @(posedge f_txclk)
402
        if (!f_tx_busy)
403
                f_tx_count <= 0;
404
        else
405
                f_tx_count <= f_tx_count + 1'b1;
406
 
407
        always @(*)
408
        if (f_tx_reg == 10'h0)
409
                assume(i_uart_rx);
410
        else
411
                assume(i_uart_rx == f_tx_reg[0]);
412
 
413
        //
414
        // Make sure the absolute transmit clock timer matches our state
415
        //
416
        always @(posedge f_txclk)
417
        if (!f_tx_busy)
418
        begin
419
                if ((!f_past_valid_tx)||(!$past(f_tx_busy)))
420 26 dgisselq
                        `ASSERT(f_tx_count == 0);
421 21 dgisselq
        end else if (f_tx_reg[9])
422 26 dgisselq
                `ASSERT(f_tx_count ==
423 21 dgisselq
                                    CLOCKS_PER_BAUD -1 -f_tx_baud);
424
        else if (f_tx_reg[8])
425 26 dgisselq
                `ASSERT(f_tx_count ==
426 21 dgisselq
                                2 * CLOCKS_PER_BAUD -1 -f_tx_baud);
427
        else if (f_tx_reg[7])
428 26 dgisselq
                `ASSERT(f_tx_count ==
429 21 dgisselq
                                3 * CLOCKS_PER_BAUD -1 -f_tx_baud);
430
        else if (f_tx_reg[6])
431 26 dgisselq
                `ASSERT(f_tx_count ==
432 21 dgisselq
                                4 * CLOCKS_PER_BAUD -1 -f_tx_baud);
433
        else if (f_tx_reg[5])
434 26 dgisselq
                `ASSERT(f_tx_count ==
435 21 dgisselq
                                5 * CLOCKS_PER_BAUD -1 -f_tx_baud);
436
        else if (f_tx_reg[4])
437 26 dgisselq
                `ASSERT(f_tx_count ==
438 21 dgisselq
                                6 * CLOCKS_PER_BAUD -1 -f_tx_baud);
439
        else if (f_tx_reg[3])
440 26 dgisselq
                `ASSERT(f_tx_count ==
441 21 dgisselq
                                7 * CLOCKS_PER_BAUD -1 -f_tx_baud);
442
        else if (f_tx_reg[2])
443 26 dgisselq
                `ASSERT(f_tx_count ==
444 21 dgisselq
                                8 * CLOCKS_PER_BAUD -1 -f_tx_baud);
445
        else if (f_tx_reg[1])
446 26 dgisselq
                `ASSERT(f_tx_count ==
447 21 dgisselq
                                9 * CLOCKS_PER_BAUD -1 -f_tx_baud);
448
        else if (f_tx_reg[0])
449 26 dgisselq
                `ASSERT(f_tx_count ==
450 21 dgisselq
                                10 * CLOCKS_PER_BAUD -1 -f_tx_baud);
451
        else
452 26 dgisselq
                `ASSERT(f_tx_count ==
453 21 dgisselq
                                11 * CLOCKS_PER_BAUD -1 -f_tx_baud);
454
 
455
 
456
        ///////////////////////////////////////
457
        //
458
        // Receiver
459
        //
460
        ///////////////////////////////////////
461
        //
462
        // Count RX clocks since the start of the first stop bit, measured in
463
        // rx clocks
464
        initial f_rx_count = 0;
465
        always @(posedge i_clk)
466
        if (state == `RXUL_IDLE)
467
                f_rx_count = (!ck_uart) ? (chg_counter+2) : 0;
468
        else
469
                f_rx_count <= f_rx_count + 1'b1;
470
        always @(posedge i_clk)
471
        if (state == 0)
472 26 dgisselq
                `ASSERT(f_rx_count
473 21 dgisselq
                                == half_baud + (CLOCKS_PER_BAUD-baud_counter));
474
        else if (state == 1)
475 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 2 * CLOCKS_PER_BAUD
476 21 dgisselq
                                        - baud_counter);
477
        else if (state == 2)
478 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 3 * CLOCKS_PER_BAUD
479 21 dgisselq
                                        - baud_counter);
480
        else if (state == 3)
481 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 4 * CLOCKS_PER_BAUD
482 21 dgisselq
                                        - baud_counter);
483
        else if (state == 4)
484 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 5 * CLOCKS_PER_BAUD
485 21 dgisselq
                                        - baud_counter);
486
        else if (state == 5)
487 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 6 * CLOCKS_PER_BAUD
488 21 dgisselq
                                        - baud_counter);
489
        else if (state == 6)
490 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 7 * CLOCKS_PER_BAUD
491 21 dgisselq
                                        - baud_counter);
492
        else if (state == 7)
493 26 dgisselq
                `ASSERT(f_rx_count == half_baud + 8 * CLOCKS_PER_BAUD
494 21 dgisselq
                                        - baud_counter);
495
        else if (state == 8)
496 26 dgisselq
                `ASSERT((f_rx_count == half_baud + 9 * CLOCKS_PER_BAUD
497 21 dgisselq
                                        - baud_counter)
498
                        ||(f_rx_count == half_baud + 10 * CLOCKS_PER_BAUD
499
                                        - baud_counter));
500
 
501
        always @(*)
502 26 dgisselq
                `ASSERT( ((!zero_baud_counter)
503 21 dgisselq
                                &&(state == `RXUL_IDLE)
504
                                &&(baud_counter == 0))
505
                        ||((zero_baud_counter)&&(baud_counter == 0))
506
                        ||((!zero_baud_counter)&&(baud_counter != 0)));
507
 
508
        always @(posedge i_clk)
509
        if (!f_past_valid)
510 26 dgisselq
                `ASSERT((state == `RXUL_IDLE)&&(baud_counter == 0)
511 21 dgisselq
                        &&(zero_baud_counter));
512
 
513
        always @(*)
514
        begin
515 26 dgisselq
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h2);
516
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h4);
517
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h5);
518
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h6);
519
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h9);
520
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'ha);
521
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'hb);
522
                `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'hd);
523 21 dgisselq
        end
524
 
525
        always @(posedge i_clk)
526
        if ((f_past_valid)&&($past(state) >= `RXUL_WAIT)&&($past(ck_uart)))
527 26 dgisselq
                `ASSERT(state == `RXUL_IDLE);
528 21 dgisselq
 
529
        always @(posedge i_clk)
530
        if ((f_past_valid)&&($past(state) >= `RXUL_WAIT)
531
                        &&(($past(state) != `RXUL_IDLE)||(state == `RXUL_IDLE)))
532 26 dgisselq
                `ASSERT(zero_baud_counter);
533 21 dgisselq
 
534
        // Calculate an absolute value of the difference between the two baud
535
        // clocks
536
        always @(posedge i_clk)
537
        if ((f_past_valid)&&($past(state)==`RXUL_IDLE)&&(state == `RXUL_IDLE))
538
        begin
539 26 dgisselq
                `ASSERT(($past(ck_uart))
540 21 dgisselq
                        ||(chg_counter <=
541
                                { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] }));
542
        end
543
 
544
        always @(posedge f_txclk)
545
        if (!f_past_valid_tx)
546 26 dgisselq
                `ASSERT((state == `RXUL_IDLE)&&(baud_counter == 0)
547 21 dgisselq
                        &&(zero_baud_counter)&&(!f_tx_busy));
548
 
549
        wire    [(TB+3):0]       f_tx_count_two_clocks_ago;
550
        assign  f_tx_count_two_clocks_ago = f_tx_count - 2;
551
        always @(*)
552
        if (f_tx_count >= f_rx_count + 2)
553
                f_baud_difference = f_tx_count_two_clocks_ago - f_rx_count;
554
        else
555
                f_baud_difference = f_rx_count - f_tx_count_two_clocks_ago;
556
 
557
        localparam      F_SYNC_DLY = 8;
558
 
559 26 dgisselq
        reg     [(TB+4+F_CKRES-1):0]     f_sub_baud_difference;
560 21 dgisselq
        reg     [F_CKRES-1:0]    ck_tx_clock;
561
        reg     [((F_SYNC_DLY-1)*F_CKRES)-1:0]   q_tx_clock;
562
        reg     [TB+3:0] ck_tx_count;
563
        reg     [(F_SYNC_DLY-1)*(TB+4)-1:0]      q_tx_count;
564
        initial q_tx_count = 0;
565
        initial ck_tx_count = 0;
566
        initial q_tx_clock = 0;
567
        initial ck_tx_clock = 0;
568
        always @($global_clock)
569
                { ck_tx_clock, q_tx_clock } <= { q_tx_clock, f_tx_clock };
570
        always @($global_clock)
571
                { ck_tx_count, q_tx_count } <= { q_tx_count, f_tx_count };
572
 
573
 
574 26 dgisselq
        reg     [TB+4+F_CKRES-1:0]       f_ck_tx_time, f_rx_time;
575 21 dgisselq
        always @(*)
576
                f_ck_tx_time = { ck_tx_count, !ck_tx_clock[F_CKRES-1],
577
                                                ck_tx_clock[F_CKRES-2:0] };
578
        always @(*)
579
                f_rx_time = { f_rx_count, !f_rx_clock[1], f_rx_clock[0],
580
                                                {(F_CKRES-2){1'b0}} };
581
 
582 26 dgisselq
        reg     [TB+4+F_CKRES-1:0]       f_signed_difference;
583 21 dgisselq
        always @(*)
584
                f_signed_difference = f_ck_tx_time - f_rx_time;
585
 
586
        always @(*)
587
        if (f_signed_difference[TB+4+F_CKRES-1])
588
                f_sub_baud_difference = -f_signed_difference;
589
        else
590
                f_sub_baud_difference =  f_signed_difference;
591
 
592
        always @($global_clock)
593
        if (state == `RXUL_WAIT)
594 26 dgisselq
                `ASSERT((!f_tx_busy)||(f_tx_reg[9:1] == 0));
595 21 dgisselq
 
596
        always @($global_clock)
597
        if (state == `RXUL_IDLE)
598
        begin
599 26 dgisselq
                `ASSERT((!f_tx_busy)||(f_tx_reg[9])||(f_tx_reg[9:1]==0));
600 21 dgisselq
                if (!ck_uart)
601
                        ;//`PHASE_TWO_ASSERT((f_rx_count < 4)||(f_sub_baud_difference <= ((CLOCKS_PER_BAUD<<F_CKRES)/20)));
602 15 dgisselq
                else
603 26 dgisselq
                        `ASSERT((f_tx_reg[9:1]==0)||(f_tx_count < (3 + CLOCKS_PER_BAUD/2)));
604 21 dgisselq
        end else if (state == 0)
605 26 dgisselq
                `ASSERT(f_sub_baud_difference
606 21 dgisselq
                                <=  2 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
607
        else if (state == 1)
608 26 dgisselq
                `ASSERT(f_sub_baud_difference
609 21 dgisselq
                                <=  3 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
610
        else if (state == 2)
611 26 dgisselq
                `ASSERT(f_sub_baud_difference
612 21 dgisselq
                                <=  4 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
613
        else if (state == 3)
614 26 dgisselq
                `ASSERT(f_sub_baud_difference
615 21 dgisselq
                                <=  5 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
616
        else if (state == 4)
617 26 dgisselq
                `ASSERT(f_sub_baud_difference
618 21 dgisselq
                                <=  6 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
619
        else if (state == 5)
620 26 dgisselq
                `ASSERT(f_sub_baud_difference
621 21 dgisselq
                                <=  7 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
622
        else if (state == 6)
623 26 dgisselq
                `ASSERT(f_sub_baud_difference
624 21 dgisselq
                                <=  8 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
625
        else if (state == 7)
626 26 dgisselq
                `ASSERT(f_sub_baud_difference
627 21 dgisselq
                                <=  9 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
628
        else if (state == 8)
629 26 dgisselq
                `ASSERT(f_sub_baud_difference
630 21 dgisselq
                                <= 10 * ((CLOCKS_PER_BAUD<<F_CKRES)/20));
631 15 dgisselq
 
632 21 dgisselq
        always @(posedge i_clk)
633
        if (o_wr)
634 26 dgisselq
                `ASSERT(o_data == $past(f_tx_data,4));
635 15 dgisselq
 
636 21 dgisselq
        // always @(posedge i_clk)
637
        // if ((zero_baud_counter)&&(state != 4'hf)&&(CLOCKS_PER_BAUD > 6))
638
                // assert(i_uart_rx == ck_uart);
639
 
640
        // Make sure the data register matches
641
        always @(posedge i_clk)
642
        // if ((f_past_valid)&&(state != $past(state)))
643
        begin
644
                if (state == 4'h0)
645 26 dgisselq
                        `ASSERT(!data_reg[7]);
646 21 dgisselq
 
647
                if (state == 4'h1)
648 26 dgisselq
                        `ASSERT((data_reg[7]
649 21 dgisselq
                                == $past(f_tx_data[0]))&&(!data_reg[6]));
650
 
651
                if (state == 4'h2)
652 26 dgisselq
                        `ASSERT(data_reg[7:6]
653 21 dgisselq
                                        == $past(f_tx_data[1:0]));
654
 
655
                if (state == 4'h3)
656 26 dgisselq
                        `ASSERT(data_reg[7:5] == $past(f_tx_data[2:0]));
657 21 dgisselq
 
658
                if (state == 4'h4)
659 26 dgisselq
                        `ASSERT(data_reg[7:4] == $past(f_tx_data[3:0]));
660 21 dgisselq
 
661
                if (state == 4'h5)
662 26 dgisselq
                        `ASSERT(data_reg[7:3] == $past(f_tx_data[4:0]));
663 21 dgisselq
 
664
                if (state == 4'h6)
665 26 dgisselq
                        `ASSERT(data_reg[7:2] == $past(f_tx_data[5:0]));
666 21 dgisselq
 
667
                if (state == 4'h7)
668 26 dgisselq
                        `ASSERT(data_reg[7:1] == $past(f_tx_data[6:0]));
669 21 dgisselq
 
670
                if (state == 4'h8)
671 26 dgisselq
                        `ASSERT(data_reg[7:0] == $past(f_tx_data[7:0]));
672 21 dgisselq
        end
673 26 dgisselq
        ////////////////////////////////////////////////////////////////////////
674
        //
675
        // Cover properties
676
        //
677
        ////////////////////////////////////////////////////////////////////////
678
        //
679
        always @(posedge i_clk)
680
                cover(o_wr); // Step 626, takes about 20mins
681 21 dgisselq
 
682
        always @(posedge i_clk)
683 26 dgisselq
        begin
684
                cover(!ck_uart);
685
                cover((f_past_valid)&&($rose(ck_uart)));               //  82
686
                cover((zero_baud_counter)&&(state == `RXUL_BIT_ZERO)); // 110
687
                cover((zero_baud_counter)&&(state == `RXUL_BIT_ONE));  // 174
688
                cover((zero_baud_counter)&&(state == `RXUL_BIT_TWO));  // 238
689
                cover((zero_baud_counter)&&(state == `RXUL_BIT_THREE));// 302
690
                cover((zero_baud_counter)&&(state == `RXUL_BIT_FOUR)); // 366
691
                cover((zero_baud_counter)&&(state == `RXUL_BIT_FIVE)); // 430
692
                cover((zero_baud_counter)&&(state == `RXUL_BIT_SIX));  // 494
693
                cover((zero_baud_counter)&&(state == `RXUL_BIT_SEVEN));// 558
694
                cover((zero_baud_counter)&&(state == `RXUL_STOP));     // 622
695
                cover((zero_baud_counter)&&(state == `RXUL_WAIT));     // 626
696
        end
697
 
698 21 dgisselq
`endif
699
`ifdef  FORMAL_VERILATOR
700
        // FORMAL properties which can be tested via Verilator as well as
701
        // Yosys FORMAL
702
        always @(*)
703
                assert((state == 4'hf)||(state <= `RXUL_WAIT));
704
        always @(*)
705
                assert(zero_baud_counter == (baud_counter == 0)? 1'b1:1'b0);
706
        always @(*)
707
                assert(baud_counter <= CLOCKS_PER_BAUD-1'b1);
708
 
709
`endif
710
 
711 15 dgisselq
endmodule
712
 
713
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.