// ********************************************************************
// Actel Corporation Proprietary and Confidential
//  Copyright 2008 Actel Corporation.  All rights reserved.
//
// ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
// ACCORDANCE WITH THE ACTEL LICENSE AGREEMENT AND MUST BE APPROVED
// IN ADVANCE IN WRITING.
//
// Description: CoreUART/ CoreUARTapb UART core
//
//
//  Revision Information:
// Date     Description
// Jun09    Revision 4.1
// Aug10    Revision 4.2
//
// SVN Revision Information:
// SVN $Revision: 8508 $
// SVN $Date: 2009-06-15 16:49:49 -0700 (Mon, 15 Jun 2009) $
//
// Resolved SARs
// SAR      Date     Who   Description
// 20741    2Sep10   AS    Increased baud rate by ensuring fifo ctrl runs off
//                         sys clk (not baud clock).  See note below.
//
// Notes:
// best viewed with tabstops set to "4"
`timescale 1 ns / 1 ns // timescale for following modules

module UART_INTERFACE_COREUART_0_Rx_async (clk,
  baud_clock,
  reset_n,
  bit8,
  parity_en,
  odd_n_even,
  read_rx_byte,
  clear_parity,
  rx,
  overflow,
  parity_err,
  clear_parity_en,
  receive_full,
  rx_byte, 
  fifo_write,
  framing_error,
  clear_framing_error,
  clear_framing_error_en,
  stop_strobe,
  rx_idle
);

// RX Parameters
parameter RX_FIFO = 0; // 0=without rx fifo, 1=with rx fifo 

input   clk; //  system clock
input   baud_clock; //  8x baud clock pulse
input   reset_n; //  active low async reset  
input   bit8; //  if set to one 8 data bits otherwise 7 data bits
input   parity_en; //  if set to one parity is enabled otherwise disabled
input   odd_n_even; //  if set to one odd parity otherwise even parity
input   read_rx_byte; //  read rx byte register
input   clear_parity; //  clear parity error 
input   clear_framing_error; // clear framing error signal (AS)
input   rx; 
output  overflow; //  receiver overflow
output  parity_err; //  parity error indicator on recieved data
output  clear_parity_en; // clear parity error enable
output  receive_full; //  receiver has a byte ready
output  [7:0] rx_byte;
output  fifo_write;
output  framing_error; // stop bit not detected flag (AS)
output  clear_framing_error_en; // clear framing error enable (AS)
output  stop_strobe;   // stop bit strobe (for RX legacy mode) (AS)
// AS: added idle wire for framing_err assigmnet using
// stop_strobe
output  rx_idle;
reg     framing_error; // stop bit not detected flag (AS) 
reg     stop_strobe;   // stop bit strobe (for RX legacy mode) (AS)
reg     overflow; 
reg     parity_err; 
reg     fifo_write;
//  receive byte register
wire    receive_full; 
reg     [7:0] rx_byte; 
reg     [1:0] rx_state; //  receive state machine
reg     [3:0] receive_count; //  counts bits received
reg     rx_filtered; //  filtered rx data
reg     [8:0] rx_shift; //  receive shift register
reg     rx_parity_calc; //  received parity, calculated
reg     [3:0] rx_bit_cnt; //  count of received bits 
reg     receive_full_int; //  receiver has a byte ready
reg     [2:0] samples; 
reg     overflow_int; 
reg     framing_error_int;   // internal framing error bit (AS)
reg     clear_parity_en; 
reg     clear_framing_error_en; // clear framing error enable (AS)
wire    [1:0] shift_choice; 
wire    [1:0] parity_choice; 
// ----------------------------------------------------------------------------
wire    [3:0] last_bit;

// TYPE receive_states:
parameter receive_states_rx_idle = 0;
parameter receive_states_rx_data_bits = 1;
parameter receive_states_rx_stop_bit = 2;

//  filter the receive data
// ----------------------------------------------------------------------------
//  The receive data filter is a simple majority voter that accepts three
//  samples of the "raw" data and reports the most populus result.  This
//  provides a simple single-cycle glitch filter.
//  This input needs to go to both the state machine start bit detector as
//  well as the data shift register as this filter introduces a three-clock 
//  delay and we need to keep the phases lined up.
// 
always @(posedge clk or negedge reset_n)
begin : majority
  if (reset_n == 1'b0)
  begin
    samples <= 3'b000;        
  end
  else
  begin
    if (baud_clock == 1'b1)
    begin
      samples[1:0] <= samples[2:1];  
      samples[2] <= rx;      
    end
  end
end

//  our voter
always @(samples)
begin
  case (samples)
    3'b000:
    begin
      rx_filtered <= 1'b0;      
    end
    3'b001:
    begin
      rx_filtered <= 1'b0;      
    end
    3'b010:
    begin
      rx_filtered <= 1'b0;      
    end
    3'b011:
    begin
      rx_filtered <= 1'b1;      
    end
    3'b100:
    begin
      rx_filtered <= 1'b0;      
    end
    3'b101:
    begin
      rx_filtered <= 1'b1;      
    end
    3'b110:
    begin
      rx_filtered <= 1'b1;      
    end
    default:
    begin
      rx_filtered <= 1'b1;      
    end
  endcase
end
// ----------------------------------------------------------------------------
//  receive bit counter
// ----------------------------------------------------------------------------
always @(posedge clk or negedge reset_n)
begin : rcv_cnt
  if (reset_n == 1'b0)
  begin
    receive_count <= 4'b0000; 
  end
  else
  begin
    //  no start bit yet or begin sample period for data
    if (baud_clock == 1'b1)
    begin
      if (rx_state == receive_states_rx_idle & (rx_filtered == 1'b1 | receive_count == 4'b1000))
      begin
        receive_count <= 4'b0000;   
      end
      else
      begin
        receive_count <= receive_count + 1'b1;      
      end
    end
  end
end
// ----------------------------------------------------------------------------
//  registering of the overflow signal
// ----------------------------------------------------------------------------
always @(posedge clk or negedge reset_n)
begin : make_overflow
  if (reset_n == 1'b0)
  begin
    overflow <= 1'b0; 
  end
  else
  begin
    if (baud_clock == 1'b1)
    begin
      if (overflow_int == 1'b1)
      begin
        overflow <= 1'b1;   
      end
    end
    if (read_rx_byte == 1'b1)
    begin
      overflow <= 1'b0;      
    end
  end
end

// ----------------------------------------------------------------------------
//  registering of the framing_error signal
// ----------------------------------------------------------------------------
always @(posedge clk or negedge reset_n)
begin : make_framing_error
  if (reset_n == 1'b0)
  begin
    framing_error <= 1'b0; 
  end
  else if (clear_framing_error == 1'b1)
  begin
    framing_error <= 1'b0;
  end
  else
  begin
    if (baud_clock == 1'b1)
    begin
      if (framing_error_int == 1'b1)
      begin
        framing_error <= 1'b1;   
      end
    end
    else begin
      framing_error <= framing_error;
    end
  end
end
// ----------------------------------------------------------------------------
//  receive state machine & byte register
// ----------------------------------------------------------------------------
assign last_bit = bit8 == 1'b0 & parity_en == 1'b0 ? 4'b0111 : 
bit8 == 1'b0 & parity_en == 1'b1 ? 4'b1000 : 
bit8 == 1'b1 & parity_en == 1'b0 ? 4'b1000 : 
4'b1001;
assign  rx_idle = (rx_state == receive_states_rx_idle);
always @(posedge clk or negedge reset_n)
begin : rcv_sm
  if (reset_n == 1'b0)
  begin
    rx_state <= receive_states_rx_idle;       
    rx_byte <= 8'b00000000;   
    overflow_int <= 1'b0;     
    framing_error_int <= 1'b0;
    stop_strobe <= 1'b0;
  end
  else
  begin
    if (baud_clock == 1'b1)
    begin
      overflow_int <= 1'b0;
      stop_strobe <= 1'b0;
      framing_error_int <= 1'b0;
      case (rx_state)
        receive_states_rx_idle:
        begin
          if (receive_count == 4'b1000)
          begin
            rx_state <= receive_states_rx_data_bits; 
          end
          else
          begin
            rx_state <= receive_states_rx_idle;      
          end
        end
        receive_states_rx_data_bits:
        begin
          //  last bit has been received
          if (rx_bit_cnt == last_bit)
          begin
            // overflow
            rx_state <= receive_states_rx_stop_bit;  
            overflow_int <= receive_full_int;
            if (receive_full_int == 1'b0)
            begin
              rx_byte <= {(bit8 & rx_shift[7]), rx_shift[6:0]};     
            end
          end
          else
          begin
            rx_state <= receive_states_rx_data_bits; //  still clocking in bits
          end
        end
        receive_states_rx_stop_bit:
        begin
          // framing error
          if (receive_count == 4'b1110)
          begin
            if (rx_filtered == 1'b0)
            begin
              framing_error_int <= 1'b1;
            end
          end
          else if (receive_count == 4'b1111)
          begin
            stop_strobe <= 1'b1;
            rx_state <= receive_states_rx_idle;      
          end
          else
          begin
            rx_state <= receive_states_rx_stop_bit;  
          end
        end
        default:
        begin
          rx_state <= receive_states_rx_idle; 
        end
      endcase
    end
  end
end

// ----------------------------------------------------------------------------
//  receive shift register and parity calculation
// ----------------------------------------------------------------------------
assign shift_choice = {bit8, parity_en}; 
always @(posedge clk or negedge reset_n)
begin : receive_shift
  if (reset_n == 1'b0)
  begin
    rx_shift[8:0] <= 9'b000000000;    
    rx_bit_cnt <= 4'b0000;    
  end
  else
  begin
    if (baud_clock == 1'b1)
    begin
      if (rx_state == receive_states_rx_idle)
      begin
        rx_shift[8:0] <= 9'b000000000;      
        rx_bit_cnt <= 4'b0000;      
      end
      else if (receive_count == 4'b1111 )
      begin
        //  sample new data bit
        rx_bit_cnt <= rx_bit_cnt + 1'b1;    
        case (shift_choice)
          2'b00:
          begin
            rx_shift[5:0] <= rx_shift[6:1];  
            rx_shift[6] <= rx_filtered;      
          end
          2'b11:
          begin
            rx_shift[7:0] <= rx_shift[8:1];  
            rx_shift[8] <= rx_filtered;      
          end
          default:
          begin
            rx_shift[6:0] <= rx_shift[7:1];  
            rx_shift[7] <= rx_filtered;      
          end
        endcase
      end
    end
  end
end
// ----------------------------------------------------------------------------
//  receiver parity calculation
// ----------------------------------------------------------------------------
always @(posedge clk or negedge reset_n)
begin : rx_par_calc
  if (reset_n == 1'b0)
  begin
    rx_parity_calc <= 1'b0;   
  end
  else
  begin
    if (baud_clock == 1'b1)
    begin
      if (receive_count == 4'b1111 & parity_en == 1'b1)
      begin
        rx_parity_calc <= rx_parity_calc ^ rx_filtered;     
      end
      if (rx_state == receive_states_rx_stop_bit)
      begin
        rx_parity_calc <= 1'b0;     
      end
    end
  end
end

// ----------------------------------------------------------------------------
//  latch parity error for even or odd parity
// ----------------------------------------------------------------------------
assign parity_choice = {bit8, odd_n_even}; 
always @(posedge clk or negedge reset_n)
begin : make_parity_err
  if (reset_n == 1'b0)
  begin
    parity_err <= 1'b0;       
  end
  else
  begin
    if (baud_clock == 1'b1 & parity_en == 1'b1 & receive_count == 4'b1111)
    begin
      case (parity_choice)
        2'b00:
        begin
          if (rx_bit_cnt == 4'b0111)
          begin
            parity_err <= rx_parity_calc ^ rx_filtered;      
          end
        end
        2'b01:
        begin
          if (rx_bit_cnt == 4'b0111)
          begin
            parity_err <= ~(rx_parity_calc ^ rx_filtered);   
          end
        end
        2'b10:
        begin
          if (rx_bit_cnt == 4'b1000)
          begin
            parity_err <= rx_parity_calc ^ rx_filtered;      
          end
        end
        2'b11:
        begin
          if (rx_bit_cnt == 4'b1000)
          begin
            parity_err <= ~(rx_parity_calc ^ rx_filtered);   
          end
        end
        default:
        begin
          parity_err <= 1'b0; 
        end
      endcase
    end
    if (clear_parity == 1'b1)
    begin
      parity_err <= 1'b0;    
    end
  end
end
// ----------------------------------------------------------------------------
//  receive full indicator process
// ----------------------------------------------------------------------------
always @(posedge clk or negedge reset_n)
begin : receive_full_indicator
  if (reset_n == 1'b0)
  begin
    receive_full_int <= 1'b0; 
    fifo_write <= 1'b1;
    clear_parity_en <= 1'b0;
    clear_framing_error_en <= 1'b0;
  end
  else
  begin
    fifo_write <= 1'b1;
    clear_parity_en <= 1'b0;
    clear_framing_error_en <= 1'b0;
    if (baud_clock == 1'b1)
      //  last bit has been received 
    begin
      if (bit8 == 1'b1)
      begin
        if (parity_en == 1'b1)
        begin
          if (rx_bit_cnt == 4'b1001 & rx_state == receive_states_rx_data_bits)
          begin
            fifo_write <= 1'b0;
            clear_parity_en <= 1'b1;
            clear_framing_error_en <= 1'b1;
            if (RX_FIFO == 1'b0)
            begin
              receive_full_int <= 1'b1;   
            end
          end
        end
        else
        begin
          if (rx_bit_cnt == 4'b1000 & rx_state == receive_states_rx_data_bits)
          begin
            fifo_write <= 1'b0;
            clear_parity_en <= 1'b1;
            clear_framing_error_en <= 1'b1;
            if (RX_FIFO == 1'b0)
            begin
              receive_full_int <= 1'b1;   
            end
          end
        end
      end
      else
      begin
        if (parity_en == 1'b1)
        begin
          if (rx_bit_cnt == 4'b1000 & rx_state == receive_states_rx_data_bits)
          begin
            fifo_write <= 1'b0;
            clear_parity_en <= 1'b1;
            clear_framing_error_en <= 1'b1;
            if (RX_FIFO == 1'b0)
            begin
              receive_full_int <= 1'b1;   
            end
          end
        end
        else
        begin
          if (rx_bit_cnt == 4'b0111 & rx_state == receive_states_rx_data_bits)
          begin
            fifo_write <= 1'b0;
            clear_parity_en <= 1'b1;
            clear_framing_error_en <= 1'b1;
            if (RX_FIFO == 1'b0)
            begin
              receive_full_int <= 1'b1;   
            end
          end
        end
      end
    end
    if (read_rx_byte == 1'b1)
    begin
      receive_full_int <= 1'b0;      
    end 
  end
end

assign receive_full = receive_full_int; 

endmodule // module UART_INTERFACE_COREUART_0_Rx_async

