../src/lowrisc_ip_uart_0.1/rtl/uart_rx.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: //
   5: // Description: UART Receive Module
   6: //
   7: 
   8: module uart_rx (
   9:   input           clk_i,
  10:   input           rst_ni,
  11: 
  12:   input           rx_enable,
  13:   input           tick_baud_x16,
  14:   input           parity_enable,
  15:   input           parity_odd,
  16: 
  17:   output logic    tick_baud,
  18:   output logic    rx_valid,
  19:   output [7:0]    rx_data,
  20:   output logic    idle,
  21:   output          frame_err,
  22:   output          rx_parity_err,
  23: 
  24:   input           rx
  25: );
  26: 
  27:   logic            rx_valid_q;
  28:   logic   [10:0]   sreg_q, sreg_d;
  29:   logic    [3:0]   bit_cnt_q, bit_cnt_d;
  30:   logic    [3:0]   baud_div_q, baud_div_d;
  31:   logic            tick_baud_d, tick_baud_q;
  32:   logic            idle_d, idle_q;
  33: 
  34:   assign tick_baud = tick_baud_q;
  35:   assign idle      = idle_q;
  36: 
  37:   always_ff @(posedge clk_i or negedge rst_ni) begin
  38:     if (!rst_ni) begin
  39:       sreg_q      <= 11'h0;
  40:       bit_cnt_q   <= 4'h0;
  41:       baud_div_q  <= 4'h0;
  42:       tick_baud_q <= 1'b0;
  43:       idle_q      <= 1'b1;
  44:     end else begin
  45:       sreg_q      <= sreg_d;
  46:       bit_cnt_q   <= bit_cnt_d;
  47:       baud_div_q  <= baud_div_d;
  48:       tick_baud_q <= tick_baud_d;
  49:       idle_q      <= idle_d;
  50:     end
  51:   end
  52: 
  53:   always_comb begin
  54:     if (!rx_enable) begin
  55:       sreg_d      = 11'h0;
  56:       bit_cnt_d   = 4'h0;
  57:       baud_div_d  = 4'h0;
  58:       tick_baud_d = 1'b0;
  59:       idle_d      = 1'b1;
  60:     end else begin
  61:       tick_baud_d = 1'b0;
  62:       sreg_d      = sreg_q;
  63:       bit_cnt_d   = bit_cnt_q;
  64:       baud_div_d  = baud_div_q;
  65:       idle_d      = idle_q;
  66:       if (tick_baud_x16) begin
  67:         {tick_baud_d, baud_div_d} = {1'b0,baud_div_q} + 5'h1;
  68:       end
  69: 
  70:       if (idle_q && !rx) begin
  71:         // start of char, sample in the middle of the bit time
  72:         baud_div_d  = 4'd8;
  73:         tick_baud_d = 1'b0;
  74:         bit_cnt_d   = (parity_enable ? 4'd11 : 4'd10);
  75:         sreg_d      = 11'h0;
  76:         idle_d      = 1'b0;
  77:       end else if (!idle_q && tick_baud_q) begin
  78:         if ((bit_cnt_q == (parity_enable ? 4'd11 : 4'd10)) && rx) begin
  79:           // must have been a glitch on the input, start bit is not set
  80:           // in the middle of the bit time, abort
  81:           idle_d    = 1'b1;
  82:           bit_cnt_d = 4'h0;
  83:         end else begin
  84:           sreg_d    = {rx, sreg_q[10:1]};
  85:           bit_cnt_d = bit_cnt_q - 4'h1;
  86:           idle_d    = (bit_cnt_q == 4'h1);
  87:         end
  88:       end
  89:     end
  90:   end
  91: 
  92:   always_ff @(posedge clk_i or negedge rst_ni) begin
  93:     if (!rst_ni) rx_valid_q <= 1'b0;
  94:     else         rx_valid_q <= tick_baud_q & (bit_cnt_q == 4'h1);
  95: 
  96:   end
  97: 
  98:   assign rx_valid      = rx_valid_q;
  99:   assign rx_data       = parity_enable ? sreg_q[8:1] : sreg_q[9:2];
 100:   //    (rx_parity     = sreg_q[9])
 101:   assign frame_err     = rx_valid_q & ~sreg_q[10];
 102:   assign rx_parity_err = parity_enable & rx_valid_q &
 103:                          (^{sreg_q[9:1],parity_odd});
 104: 
 105: endmodule
 106: