| 1 | 2 | motilito | //------------------------------------------------------------------------------
 | 
      
         | 2 |  |  | // uart tasks:
 | 
      
         | 3 |  |  | //              send_serial             serial transmitter 
 | 
      
         | 4 |  |  | //              get_serial              serial receiver 
 | 
      
         | 5 |  |  | //
 | 
      
         | 6 |  |  | //------------------------------------------------------------------------------
 | 
      
         | 7 |  |  |  
 | 
      
         | 8 |  |  | /*  Serial Parameters used for send_serial task and its callers. */
 | 
      
         | 9 |  |  | `define PARITY_OFF              1'b0
 | 
      
         | 10 |  |  | `define PARITY_ON               1'b1
 | 
      
         | 11 |  |  | `define PARITY_ODD              1'b0
 | 
      
         | 12 |  |  | `define PARITY_EVEN             1'b1
 | 
      
         | 13 |  |  | `define NSTOPS_1                1'b0
 | 
      
         | 14 |  |  | `define NSTOPS_2                1'b1
 | 
      
         | 15 |  |  | `define BAUD_115200             3'b000
 | 
      
         | 16 |  |  | `define BAUD_38400              3'b001
 | 
      
         | 17 |  |  | `define BAUD_28800              3'b010
 | 
      
         | 18 |  |  | `define BAUD_19200              3'b011
 | 
      
         | 19 |  |  | `define BAUD_9600               3'b100
 | 
      
         | 20 |  |  | `define BAUD_4800               3'b101
 | 
      
         | 21 |  |  | `define BAUD_2400               3'b110
 | 
      
         | 22 |  |  | `define BAUD_1200               3'b111
 | 
      
         | 23 |  |  | `define NBITS_7                 1'b0
 | 
      
         | 24 |  |  | `define NBITS_8                 1'b1
 | 
      
         | 25 |  |  | // constants for status from get_serial task 
 | 
      
         | 26 |  |  | `define RECEIVE_RESULT_OK                       4'b1000
 | 
      
         | 27 |  |  | `define RECEIVE_RESULT_FALSESTART       4'b0001
 | 
      
         | 28 |  |  | `define RECEIVE_RESULT_BADPARITY        4'b0010
 | 
      
         | 29 |  |  | `define RECEIVE_RESULT_BADSTOP          4'b0100
 | 
      
         | 30 |  |  |  
 | 
      
         | 31 |  |  | // uart tasks global interfaces signals 
 | 
      
         | 32 |  |  | reg serial_out;         // transmit serial output 
 | 
      
         | 33 |  |  | reg serial_in;          // receive serial input 
 | 
      
         | 34 |  |  | reg [7:0] get_serial_data;               // data received from serial 
 | 
      
         | 35 |  |  | reg [7:0] get_serial_status;     // status of receive operation 
 | 
      
         | 36 |  |  |  
 | 
      
         | 37 |  |  | //------------------------------------------------------------------------------
 | 
      
         | 38 |  |  | // uart transmit task 
 | 
      
         | 39 |  |  | // 
 | 
      
         | 40 |  |  | // usage:
 | 
      
         | 41 |  |  | //              send_serial (data, baud_rate, parity_type, parity_on, stop_bits_num, 
 | 
      
         | 42 |  |  | //                                                                                                              data_bit_num, baud_error);
 | 
      
         | 43 |  |  | // where:
 | 
      
         | 44 |  |  | //              data                    data character for transmission 
 | 
      
         | 45 |  |  | //              parity_type             this is a flag indicating that parity should be even 
 | 
      
         | 46 |  |  | //                                              (either 'PARITY_ODD or 'PARITY_EVEN)
 | 
      
         | 47 |  |  | //              parity_on               indicates that the parity is used 
 | 
      
         | 48 |  |  | //                                              (either 'PARITY_OFF or 'PARITY_ON)
 | 
      
         | 49 |  |  | //              stop_bits_num   number of stop bits (either NSTOPS_1 or NSTOPS_2)
 | 
      
         | 50 |  |  | //              data_bit_num    number of data bits (either NBITS_7 or NBITS_8)
 | 
      
         | 51 |  |  | //              baud_error              baud error in precentage (-5 is -5%)
 | 
      
         | 52 |  |  | // 
 | 
      
         | 53 |  |  |  
 | 
      
         | 54 |  |  | task send_serial;
 | 
      
         | 55 |  |  | // task input parameters 
 | 
      
         | 56 |  |  | input [7:0] inputchar;
 | 
      
         | 57 |  |  | input baud;
 | 
      
         | 58 |  |  | input paritytype;
 | 
      
         | 59 |  |  | input parityenable;
 | 
      
         | 60 |  |  | input nstops;
 | 
      
         | 61 |  |  | input nbits;
 | 
      
         | 62 |  |  | input baud_error_factor;
 | 
      
         | 63 |  |  | // internal registers 
 | 
      
         | 64 |  |  | reg       nbits;
 | 
      
         | 65 |  |  | reg       parityenable;
 | 
      
         | 66 |  |  | reg       paritytype;
 | 
      
         | 67 |  |  | reg [1:0] baud;
 | 
      
         | 68 |  |  | reg       nstops;
 | 
      
         | 69 |  |  | integer         baud_error_factor;  // e.g. +5 means 5% too fast and -5 means 5% too slow
 | 
      
         | 70 |  |  | reg     [7:0]    char;
 | 
      
         | 71 |  |  | reg [7:0]        disp_char;
 | 
      
         | 72 |  |  | reg         parity_bit;
 | 
      
         | 73 |  |  | integer     bit_time;
 | 
      
         | 74 |  |  | integer         num_of_bits;
 | 
      
         | 75 |  |  | // task implementation 
 | 
      
         | 76 |  |  | begin
 | 
      
         | 77 |  |  |         char = inputchar;
 | 
      
         | 78 |  |  |         parity_bit = 1'b0;
 | 
      
         | 79 |  |  |         // calculate bit time from input baud rate - this assumes a simulation resolution of 1ns 
 | 
      
         | 80 |  |  |         case (baud)
 | 
      
         | 81 |  |  |                 `BAUD_115200: bit_time = 1000000000/(115200 + 1152*baud_error_factor);
 | 
      
         | 82 |  |  | //              `BAUD_115200: bit_time = 40000000000/(115200 + 1152*baud_error_factor);
 | 
      
         | 83 |  |  |                 `BAUD_38400:  bit_time = 1000000000/(38400 + 384*baud_error_factor);
 | 
      
         | 84 |  |  |                 `BAUD_28800:  bit_time = 1000000000/(28800 + 288*baud_error_factor);
 | 
      
         | 85 |  |  |                 `BAUD_19200:  bit_time = 1000000000/(19200 + 192*baud_error_factor);
 | 
      
         | 86 |  |  |                 `BAUD_9600:   bit_time = 1000000000/(9600 + 96*baud_error_factor);
 | 
      
         | 87 |  |  |                 `BAUD_4800:   bit_time = 1000000000/(4800 + 48*baud_error_factor);
 | 
      
         | 88 |  |  |                 `BAUD_2400:   bit_time = 1000000000/(2400 + 24*baud_error_factor);
 | 
      
         | 89 |  |  |                 `BAUD_1200:   bit_time = 1000000000/(1200 + 12*baud_error_factor);
 | 
      
         | 90 |  |  |         endcase
 | 
      
         | 91 |  |  |  
 | 
      
         | 92 |  |  |         // display info 
 | 
      
         | 93 |  |  |         disp_char = (char >= 8'h20) ? char : 8'hb0;
 | 
      
         | 94 |  |  |         $display ("Sending character 0x%h (\"%c\"), at %0d baud (err=%0d), %0d bits, %0s parity, %0d stops",
 | 
      
         | 95 |  |  |                 (nbits == `NBITS_7) ? (char & 8'h7f) : char,
 | 
      
         | 96 |  |  |                 (nbits == `NBITS_7) ? (disp_char & 8'h7f) : disp_char,
 | 
      
         | 97 |  |  |                 1000000000/bit_time,
 | 
      
         | 98 |  |  |                 baud_error_factor,
 | 
      
         | 99 |  |  |                 (nbits == `NBITS_7) ? 7 : 8,
 | 
      
         | 100 |  |  |                 (parityenable == `PARITY_OFF) ? "NONE" : (paritytype == `PARITY_EVEN) ? "EVEN" : "ODD",
 | 
      
         | 101 |  |  |                 (nstops == `NSTOPS_1) ? 1 : 2
 | 
      
         | 102 |  |  |         );
 | 
      
         | 103 |  |  |  
 | 
      
         | 104 |  |  |         // Start bit
 | 
      
         | 105 |  |  |         serial_out = 1'b0;   // Start bit.
 | 
      
         | 106 |  |  |         #(bit_time);
 | 
      
         | 107 |  |  |  
 | 
      
         | 108 |  |  |         // Output data bits
 | 
      
         | 109 |  |  |         num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
 | 
      
         | 110 |  |  |         repeat (num_of_bits)
 | 
      
         | 111 |  |  |         begin
 | 
      
         | 112 |  |  |                 serial_out = char[0];
 | 
      
         | 113 |  |  |                 #(bit_time);
 | 
      
         | 114 |  |  |                 char = {1'b0, char[7:1]};
 | 
      
         | 115 |  |  |         end
 | 
      
         | 116 |  |  |  
 | 
      
         | 117 |  |  |         // check if parity is enabled 
 | 
      
         | 118 |  |  |         if (parityenable == `PARITY_ON) begin
 | 
      
         | 119 |  |  |                 parity_bit = (nbits == `NBITS_7) ? ^inputchar[6:0] : ^inputchar[7:0];
 | 
      
         | 120 |  |  |                 // even parity
 | 
      
         | 121 |  |  |                 if (paritytype == `PARITY_ODD)
 | 
      
         | 122 |  |  |                         parity_bit = ~parity_bit;
 | 
      
         | 123 |  |  |  
 | 
      
         | 124 |  |  |                 serial_out = parity_bit;
 | 
      
         | 125 |  |  |                 #(bit_time);
 | 
      
         | 126 |  |  |         end
 | 
      
         | 127 |  |  |  
 | 
      
         | 128 |  |  |         // Stop bit.
 | 
      
         | 129 |  |  |         serial_out = 1'b1;
 | 
      
         | 130 |  |  |         #(bit_time);
 | 
      
         | 131 |  |  |         // Second stop bit
 | 
      
         | 132 |  |  |         if (nstops)
 | 
      
         | 133 |  |  |                 #(bit_time);
 | 
      
         | 134 |  |  | end
 | 
      
         | 135 |  |  | endtask
 | 
      
         | 136 |  |  |  
 | 
      
         | 137 |  |  | //------------------------------------------------------------------------------
 | 
      
         | 138 |  |  | // uart receive task 
 | 
      
         | 139 |  |  | // 
 | 
      
         | 140 |  |  | // usage:
 | 
      
         | 141 |  |  | //              get_serial (baud_rate, parity_type, parity_on, stop_bits_num, data_bit_num);
 | 
      
         | 142 |  |  | // where:
 | 
      
         | 143 |  |  | //              data                    data character for transmission 
 | 
      
         | 144 |  |  | //              parity_type             this is a flag indicating that parity should be even 
 | 
      
         | 145 |  |  | //                                              (either 'PARITY_ODD or 'PARITY_EVEN)
 | 
      
         | 146 |  |  | //              parity_on               indicates that the parity is used 
 | 
      
         | 147 |  |  | //                                              (either 'PARITY_OFF or 'PARITY_ON)
 | 
      
         | 148 |  |  | //              stop_bits_num   number of stop bits (either NSTOPS_1 or NSTOPS_2)
 | 
      
         | 149 |  |  | //              data_bit_num    number of data bits (either NBITS_7 or NBITS_8)
 | 
      
         | 150 |  |  | // 
 | 
      
         | 151 |  |  | task get_serial;
 | 
      
         | 152 |  |  | // input parameters 
 | 
      
         | 153 |  |  | input baud;
 | 
      
         | 154 |  |  | input paritytype;
 | 
      
         | 155 |  |  | input parityenable;
 | 
      
         | 156 |  |  | input nstops;
 | 
      
         | 157 |  |  | input nbits;
 | 
      
         | 158 |  |  | // internal registers 
 | 
      
         | 159 |  |  | reg       nbits;
 | 
      
         | 160 |  |  | reg       parityenable;
 | 
      
         | 161 |  |  | reg       paritytype;
 | 
      
         | 162 |  |  | reg [1:0] baud;
 | 
      
         | 163 |  |  | reg       nstops;
 | 
      
         | 164 |  |  | integer     bit_time;
 | 
      
         | 165 |  |  | reg         expected_parity;
 | 
      
         | 166 |  |  | integer         num_of_bits;
 | 
      
         | 167 |  |  | // task implementation 
 | 
      
         | 168 |  |  | begin
 | 
      
         | 169 |  |  |         // init receive globals 
 | 
      
         | 170 |  |  |         get_serial_status = 0;
 | 
      
         | 171 |  |  |         get_serial_data = 0;
 | 
      
         | 172 |  |  |  
 | 
      
         | 173 |  |  |         // calculate bit time from input baud rate - this assumes a simulation resolution of 1ns 
 | 
      
         | 174 |  |  |         case (baud)
 | 
      
         | 175 |  |  |                 `BAUD_115200: bit_time = 1000000000/115200;
 | 
      
         | 176 |  |  |                 `BAUD_38400:  bit_time = 1000000000/38400;
 | 
      
         | 177 |  |  |                 `BAUD_28800:  bit_time = 1000000000/28800;
 | 
      
         | 178 |  |  |                 `BAUD_19200:  bit_time = 1000000000/19200;
 | 
      
         | 179 |  |  |                 `BAUD_9600:   bit_time = 1000000000/9600;
 | 
      
         | 180 |  |  |                 `BAUD_4800:   bit_time = 1000000000/4800;
 | 
      
         | 181 |  |  |                 `BAUD_2400:   bit_time = 1000000000/2400;
 | 
      
         | 182 |  |  |                 `BAUD_1200:   bit_time = 1000000000/1200;
 | 
      
         | 183 |  |  |         endcase
 | 
      
         | 184 |  |  |  
 | 
      
         | 185 |  |  |         // Assume OK until bad things happen.
 | 
      
         | 186 |  |  |         get_serial_status = `RECEIVE_RESULT_OK;
 | 
      
         | 187 |  |  |  
 | 
      
         | 188 |  |  |         // wait for start bit edge 
 | 
      
         | 189 |  |  |         @(negedge serial_in);
 | 
      
         | 190 |  |  |  
 | 
      
         | 191 |  |  |         // wait till center of start bit 
 | 
      
         | 192 |  |  |         #(bit_time/2);
 | 
      
         | 193 |  |  |  
 | 
      
         | 194 |  |  |         // make sure its really a start bit
 | 
      
         | 195 |  |  |         if (serial_in != 0)
 | 
      
         | 196 |  |  |                 get_serial_status = get_serial_status | `RECEIVE_RESULT_FALSESTART;
 | 
      
         | 197 |  |  |         else
 | 
      
         | 198 |  |  |         begin
 | 
      
         | 199 |  |  |                 // get all the data bits (7 or 8) 
 | 
      
         | 200 |  |  |                 num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
 | 
      
         | 201 |  |  |                 repeat (num_of_bits)
 | 
      
         | 202 |  |  |                 begin
 | 
      
         | 203 |  |  |                         // wait till center 
 | 
      
         | 204 |  |  |                         #(bit_time);
 | 
      
         | 205 |  |  |                         // sample a data bit
 | 
      
         | 206 |  |  |                         get_serial_data = {serial_in, get_serial_data[7:1]};
 | 
      
         | 207 |  |  |                 end
 | 
      
         | 208 |  |  |  
 | 
      
         | 209 |  |  |                 // If we are only expecting 7 bits, go ahead and right-justify what we have
 | 
      
         | 210 |  |  |                 if (nbits == `NBITS_7)
 | 
      
         | 211 |  |  |                         get_serial_data = {1'b0, get_serial_data[7:1]};
 | 
      
         | 212 |  |  |  
 | 
      
         | 213 |  |  |                 // wait for next bit to start 
 | 
      
         | 214 |  |  |                 #(bit_time);
 | 
      
         | 215 |  |  |  
 | 
      
         | 216 |  |  |                 // now, we have either a parity bit, or a stop bit
 | 
      
         | 217 |  |  |                 if (parityenable == `PARITY_ON) begin
 | 
      
         | 218 |  |  |                         if (paritytype == `PARITY_EVEN)
 | 
      
         | 219 |  |  |                                 expected_parity = (nbits == `NBITS_7) ? (^get_serial_data[6:0]) :
 | 
      
         | 220 |  |  |                                                                                                                         (^get_serial_data[7:0]);
 | 
      
         | 221 |  |  |                         else
 | 
      
         | 222 |  |  |                                 expected_parity = (nbits == `NBITS_7) ? (~(^get_serial_data[6:0])) :
 | 
      
         | 223 |  |  |                                                                                                                         (~(^get_serial_data[7:0]));
 | 
      
         | 224 |  |  |  
 | 
      
         | 225 |  |  |                         if (expected_parity != serial_in)
 | 
      
         | 226 |  |  |                                 get_serial_status = get_serial_status | `RECEIVE_RESULT_BADPARITY;
 | 
      
         | 227 |  |  |                 end
 | 
      
         | 228 |  |  |                 // wait for either 1 or 2 stop bits
 | 
      
         | 229 |  |  |                 else begin
 | 
      
         | 230 |  |  |                         // this is a stop bit.
 | 
      
         | 231 |  |  |                         if (serial_in != 1)
 | 
      
         | 232 |  |  |                                 get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
 | 
      
         | 233 |  |  |                         else
 | 
      
         | 234 |  |  |                                 // that was cool.  if 2 stops, then do this again
 | 
      
         | 235 |  |  |                                 if (nstops)
 | 
      
         | 236 |  |  |                                 begin
 | 
      
         | 237 |  |  |                                         #(bit_time);
 | 
      
         | 238 |  |  |                                         if (serial_in != 1)
 | 
      
         | 239 |  |  |                                                 get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
 | 
      
         | 240 |  |  |                                 end
 | 
      
         | 241 |  |  |                         #(bit_time/2);
 | 
      
         | 242 |  |  |                 end
 | 
      
         | 243 |  |  |         end
 | 
      
         | 244 |  |  | end
 | 
      
         | 245 |  |  | endtask
 | 
      
         | 246 |  |  |  
 |