Review Verification Of UART

In

1. Overview

If the designer creates the product, the simulator is the person who ensures that the product has to meet the best quality when it reaches the customer. 

The most important purpose of the tester is not just to find bugs (design defects) but to make sure the design works completely exactly as required. That is, not only the function is properly designed, but other parameters such as processing performance, response speed, ... if any, must also be guaranteed.

The cost for each fabrication and production of microchips is extremely expensive. Depending on the technology, if only trial production, the amount can be from tens to hundreds of USD for a batch of 20 to 40 chips. Just one error can cause the product to be completely discarded, so the inspection work is increasingly standardized, professional and has specific methods.

2. Content:

Verification Of UART Part - I

Verification Of UART Part – II

Verification Of UART Part - III

Verification Of UART Part - I

This testbench will slightly different from what we have seen till now.

So the verification components are split into following blocks

  • TX generator
  • RX generator
  • TX monitor
  • RX monitor
  • Scoreboard
  • E testbench top
  • HDL Testbench top

We are going to have some more components that like reset. Logic to control when to terminate. 

+  Verification Of UART Part – II

Device Under Test

   1 //-----------------------------------------------------

   2 // Design Name : uart

   3 // File Name   : uart.v

   4 // Function    : Simple UART

   5 // Coder       : Deepak Kumar Tala

   6 //-----------------------------------------------------

   7 module uart (

   8 reset          ,

   9 txclk          ,

  10 ld_tx_data     ,

  11 tx_data        ,

  12 tx_enable      ,

  13 tx_out         ,

  14 tx_empty       ,

  15 rxclk          ,

  16 uld_rx_data    ,

  17 rx_data        ,

  18 rx_enable      ,

  19 rx_in          ,

  20 rx_empty

  21 );

  22 // Port declarations

  23 input        reset          ;

  24 input        txclk          ;

  25 input        ld_tx_data     ;

  26 input  [7:0] tx_data        ;

  27 input        tx_enable      ;

  28 output       tx_out         ;

  29 output       tx_empty       ;

  30 input        rxclk          ;

  31 input        uld_rx_data    ;

  32 output [7:0] rx_data        ;

  33 input        rx_enable      ;

  34 input        rx_in          ;

  35 output       rx_empty       ;

  36

  37 // Internal Variables

  38 reg [7:0]    tx_reg         ;

  39 reg          tx_empty       ;

  40 reg          tx_over_run    ;

  41 reg [3:0]    tx_cnt         ;

  42 reg          tx_out         ;

  43 reg [7:0]    rx_reg         ;

  44 reg [7:0]    rx_data        ;

  45 reg [3:0]    rx_sample_cnt  ;

  46 reg [3:0]    rx_cnt         ; 

  47 reg          rx_frame_err   ;

  48 reg          rx_over_run    ;

  49 reg          rx_empty       ;

  50 reg          rx_d1          ;

  51 reg          rx_d2          ;

  52 reg          rx_busy        ;

  53

  54 // UART RX Logic

  55 always @ (posedge rxclk or posedge reset)

  56 if (reset) begin

  57   rx_reg        <= 0;

  58   rx_data       <= 0;

  59   rx_sample_cnt <= 0;

  60   rx_cnt        <= 0;

  61   rx_frame_err  <= 0;

  62   rx_over_run   <= 0;

  63   rx_empty      <= 1;

  64   rx_d1         <= 1;

  65   rx_d2         <= 1;

  66   rx_busy       <= 0;

  67 end else begin

  68   // Synchronize the asynch signal

  69   rx_d1 <= rx_in;

  70   rx_d2 <= rx_d1;

  71   // Uload the rx data

  72   if (uld_rx_data) begin

  73     rx_data  <= rx_reg;

  74     rx_empty <= 1;

  75   end

  76   // Receive data only when rx is enabled

  77   if (rx_enable) begin

  78     // Check if just received start of frame

  79     if ( ! rx_busy &&  rx_d2) begin

  80       rx_busy       <= 1;

  81       rx_sample_cnt <= 1;

  82       rx_cnt        <= 0;

  83     end

  84     // Start of frame detected, Proceed with rest of data

  85     if (rx_busy) begin

  86        rx_sample_cnt <= rx_sample_cnt + 1;

  87        // Logic to sample at middle of data

  88        if (rx_sample_cnt == 7) begin

  89           if ((rx_d2 == 1) && (rx_cnt == 0)) begin

  90             rx_busy <= 0;

  91           end else begin

  92             rx_cnt <= rx_cnt + 1;

  93             // Start storing the rx data

  94             if (rx_cnt > 0 && rx_cnt < 9) begin

  95               rx_reg[rx_cnt - 1] <= rx_d2;

  96             end

  97             if (rx_cnt == 9) begin

  98                rx_busy <= 0;

  99                // Check if End of frame received correctly

 100                if (rx_d2 == 0) begin

 101                  rx_frame_err <= 1;

 102                end else begin

 103                  rx_empty     <= 0;

 104                  rx_frame_err <= 0;

 105                  // Check if last rx data was not unloaded,

 106                  rx_over_run  <= (rx_empty) ? 0 : 1;

 107                end

 108             end

 109           end

 110        end

 111     end

 112   end

 113   if ( ! rx_enable) begin

 114     rx_busy <= 0;

 115   end

 116 end

 117

 118 // UART TX Logic

 119 always @ (posedge txclk or posedge reset)

 120 if (reset) begin

 121   tx_reg        <= 0;

 122   tx_empty      <= 1;

 123   tx_over_run   <= 0;

 124   tx_out        <= 1;

 125   tx_cnt        <= 0;

 126 end else begin

 127    if (ld_tx_data) begin

 128       if ( ! tx_empty) begin

 129         tx_over_run <= 0;

 130       end else begin

 131         tx_reg   <= tx_data;

 132         tx_empty <= 0;

 133       end

 134    end

 135    if (tx_enable &&  tx_empty) begin

 136      tx_cnt <= tx_cnt + 1;

 137      if (tx_cnt == 0) begin

 138        tx_out <= 0;

 139      end

 140      if (tx_cnt > 0 && tx_cnt < 9) begin

 141         tx_out <= tx_reg[tx_cnt -1];

 142      end

 143      if (tx_cnt == 9) begin

 144        tx_out <= 1;

 145        tx_cnt <= 0;

 146        tx_empty <= 1;

 147      end

 148    end

 149    if ( ! tx_enable) begin

 150      tx_cnt <= 0;

 151    end

 152 end

 153

 154 endmodule

HDL Testbench Top

  1 `include "uart.v"
  2 module top();
  3 
  4 reg        reset          ;
  5 reg        txclk          ;
  6 reg        ld_tx_data     ;
  7 reg  [7:0] tx_data        ;
  8 reg        tx_enable      ;
  9 wire       tx_out         ;
 10 wire       tx_empty       ;
 11 reg        rxclk          ;
 12 reg        uld_rx_data    ;
 13 wire [7:0] rx_data        ;
 14 reg        rx_enable      ;
 15 wire       rx_in          ;
 16 wire       rx_empty       ;
 17 reg        loopback       ; 
 18 reg        rx_tb_in       ;
 19 
 20 initial begin
 21   reset       = 0;
 22   txclk       = 0;
 23   ld_tx_data  = 0;
 24   tx_data     = 0;
 25   tx_enable   = 0;
 26   rxclk       = 0;
 27   uld_rx_data = 0;
 28   rx_enable   = 0;
 29   loopback    = 0;
 30   rx_tb_in    = 1;
 31 end
 32 // Loopback control logic
 33 assign rx_in = (loopback) ? tx_out : rx_tb_in;
 34 // RX and TX Clock generation
 35 always  #1  rxclk = ~rxclk;
 36 always  #16  txclk = ~txclk;
 37 
 38 // DUT Connected here
 39 uart U (
 40 .reset          (reset),
 41 .txclk          (txclk),
 42 .ld_tx_data     (ld_tx_data),
 43 .tx_data        (tx_data),
 44 .tx_enable      (tx_enable),
 45 .tx_out         (tx_out),
 46 .tx_empty       (tx_empty),
 47 .rxclk          (rxclk),
 48 .uld_rx_data    (uld_rx_data),
 49 .rx_data        (rx_data),
 50 .rx_enable      (rx_enable),
 51 .rx_in          (rx_in),
 52 .rx_empty       (rx_empty)
 53 );
 54 
 55 endmodule

E Testbench Top

  1 <'
  2 import uart_clk.e;
  3 import uart_sb.e;
  4 import uart_txgen.e;
  5 
  6 struct uart_tb {
  7 
  8   sb    : uart_sb;
  9   txgen : uart_txgen;
 10     keep txgen.sb == sb;
 11 
 12   go()@sys.any is {
 13     start txgen.goTxgen();
 14     start terminate();
 15   };
 16 
 17   terminate()@sys.txclk is {
 18     var timeout : uint = 0;
 19     while ( ! txgen.isDone()) {
 20       wait cycle;
 21     };
 22     wait [20]*cycle;
 23     outf("%dns : Termintating the simulation\n",sys.time);
 24     stop_run();
 25   };
 26 };
 27 
 28 extend sys {
 29   tb  : uart_tb;
 30   run() is also {
 31     start tb.go();
 32   };
 33 };
 34 '>

UART Clock

1 <'
 2 extend sys {
 3   event rxclk is rise('top.rxclk') @sim;
 4   event txclk is rise('top.txclk') @sim;
 5 };

 6 '>

+  Verification Of UART Part - III

UART Scoreboard

  1 <'
  2 struct uart_sb {
  3    ! tx : list of byte;
  4    ! rx : list of byte;
  5 
  6   txAdd(data : byte) is {
  7     tx.push(data);
  8   };
  9 
 10   rxAdd(data : byte) is {
 11     rx.push(data);
 12   };
 13 
 14   txCompare(data : byte) is {
 15     var org_data : byte = tx.pop0();
 16     if (data  ! = org_data) {
 17       outf("%dns : txCompare : Error : Expected data %x, Got %x\n",
 18        sys.time, org_data, data); 
 19     };
 20   };
 21 
 22   rxCompare(data : byte) is {
 23     var org_data : byte = rx.pop0();
 24     if (data  ! = org_data) {
 25       outf("%dns : rxCompare : Error : Expected data %x, Got %x\n",
 26         sys.time, org_data, data); 
 27     };
 28   };
 29 
 30 };
 31 '>

UART Transcation Generator

   1 <'
   2 struct uart_txgen {
   3    sb : uart_sb;
   4 
   5     ! tx_done      : bit;
   6     ! rx_done      : bit;
   7 
   8    // Connects the transmitter output to recevier input
   9    loopback     : bit;
  10      keep loopback == 0;
  11    // Number of frames to send to transmitter
  12    no_tx_cmds   : uint;
  13      keep no_tx_cmds == 1;
  14    // Number of frames to send to receiver
  15    no_rx_cmds   : uint;
  16      keep no_rx_cmds == 1;
  17    // Delay the reading of data from receiver
  18    rx_over_flow : bit;
  19      keep rx_over_flow == 0;
  20    // Send frame to transmitter before it has sent out last frame
  21    tx_over_flow : bit;
  22      keep tx_over_flow == 0;
  23    // Insert framming error (stop bit) in frame sent to receiver
  24    rx_frame_err : bit;
  25      keep rx_frame_err == 0;
  26   
  27    // Main method, which starts rest of methods 
  28    goTxgen()@sys.any is {
  29      tx_done = 0;
  30      rx_done = 0;
  31      assertReset();
  32      start txDriver();
  33      start rxDriver();
  34      start txMonitor();
  35      start rxMonitor();
  36    };
  37    // This method asserts method
  38    assertReset()@sys.rxclk is {
  39       wait cycle;
  40       'top.reset' = 1;
  41       outf("%dns : Asserting reset to Uart\n",sys.time);
  42       wait [5]*cycle;
  43       'top.reset' = 0;
  44    };
  45 
  46    txDriver()@sys.txclk is {
  47      var tx_timeout : uint = 0;
  48      var tx_data : byte = 0;
  49      'top.tx_enable' = 1;
  50      for {var i : uint = 0; i < no_tx_cmds; i = i + 1} do {
  51        gen tx_data;
  52        sb.txAdd(tx_data);
  53        if (loopback == 1) {
  54          sb.rxAdd(tx_data);
  55        };
  56        // Check if uart is ready to accept data for transmission
  57        while ('top.tx_empty' == 0) {
  58          wait cycle;
  59          tx_timeout =+ 1 ;
  60          if (tx_timeout > 10) {
  61            outf("%dns : txDriver : Warning : tx_empty is 0 for more then 10 clocks\n",
  62              sys.time);
  63          };
  64        };
  65        tx_timeout = 0;
  66        // Drive the data in UART for transmitting
  67        wait cycle;
  68        'top.ld_tx_data' = 1;
  69        'top.tx_data'    = tx_data;
  70        outf("%dns : txDriver : Transmitting data %x\n",sys.time, tx_data);
  71        wait cycle;
  72        'top.ld_tx_data' = 0;
  73        'top.tx_data'    = 0;
  74        while ('top.tx_empty' == 1) {
  75          wait cycle;
  76          tx_timeout =+ 1 ;
  77          if (tx_timeout > 10) {
  78            outf("%dns : txDriver : Warning : tx_empty is 1 for more then 10 clocks\n",
  79              sys.time);
  80          };
  81        };
  82        tx_timeout = 0;
  83      };
  84      tx_done = 1;
  85    };
  86 
  87    rxDriver()@sys.txclk is {
  88      var rx_data : byte = 0;
  89      'top.rx_enable' = 1;
  90      if (loopback == 1) {
  91        'top.loopback' = 1;
  92      } else {
  93        'top.loopback' = 0;
  94        for {var i : uint = 0; i < no_rx_cmds; i = i + 1} do {
  95          gen rx_data; 
  96          sb.rxAdd(rx_data);
  97          outf("%dns : rxDriver : Transmitting data %x\n",sys.time, rx_data);
  98          wait cycle;
  99          'top.rx_in' = 0;
 100          for {var j : uint = 0; j < 8; j = j + 1} do {
 101            wait cycle;
 102            'top.rx_in' = rx_data[j:j];
 103          };
 104          wait cycle;
 105          'top.rx_in' = 1;
 106          wait cycle;
 107        };
 108      };
 109      rx_done = 1;
 110    };
 111 
 112    txMonitor()@sys.txclk is {
 113      var tx_data : byte = 0;
 114      while (TRUE) {
 115        wait cycle;
 116        if ('top.tx_out' == 0) {
 117           outf("%dns : txMonitor : Found start of frame\n",sys.time);
 118           for {var i : uint = 0; i < 8; i = i + 1} do {
 119             wait cycle;
 120             tx_data[i:i] = 'top.tx_out';
 121           };
 122           wait cycle;
 123           if ('top.tx_out' == 0) {
 124             outf("%dns : txMonitor Error : Framing error detecting\n",sys.time);
 125             sb.txCompare(8'b0);
 126           } else {
 127             outf("%dns : txMonitor : Sampled data %x\n",sys.time, tx_data);
 128             sb.txCompare(tx_data);
 129           };
 130        };
 131      };
 132    };
 133 
 134    rxMonitor()@sys.rxclk is {
 135      var rx_data : byte = 0;
 136      while (TRUE) {
 137        wait cycle;
 138        if ('top.rx_empty' == 0) {
 139          'top.uld_rx_data' = 1;
 140          wait cycle;
 141          rx_data = 'top.rx_data';
 142          'top.uld_rx_data' = 0;
 143          outf("%dns : rxMonitor : Sampled data %x\n",sys.time, rx_data);
 144          sb.rxCompare(rx_data);
 145          wait cycle;
 146        };
 147      };
 148    };
 149    
 150    isDone() : bool is {
 151      var status : bool = FALSE;
 152      if (tx_done == 1 && rx_done == 1) {
 153        status =  TRUE;
 154      };
 155      return status;
 156    };
 157 };

 158 '>

   Bạn Có Đam Mê Với Vi Mạch hay Nhúng      -     Bạn Muốn Trau Dồi Thêm Kĩ Năng

Mong Muốn Có Thêm Cơ Hội Trong Công Việc

Và Trở Thành Một Người Có Giá Trị Hơn

Bạn Chưa Biết Phương Thức Nào Nhanh Chóng Để Đạt Được Chúng

Hãy Để Chúng Tôi Hỗ Trợ Cho Bạn. SEMICON  

 

Lần cập nhật cuối ( Thứ ba, 03 Tháng 5 2022 19:35 )