//===========================================================================//
//
//  S Y N T H E Z I A B L E    miniUART   C O R E
//
//  www.OpenCores.Org - January 2000
//  This core adheres to the GNU public license  
//
// Design units   : miniUART core for the OCRP-1
//
// File name      : cbaf_uart_rxunit.v (formerly RxUnit.vhd)
//
// Purpose        : Implements an miniUART device for communication purposes 
//                  between the OR1K processor and the Host computer through
//                  an RS-232 communication protocol.
//                  
//
//===========================================================================//
//
// Revision list
// Version   Author                 Date                        Changes
//
// 0.1      Ovidiu Lupas     15 January 2000                   New model
// 2.0      Ovidiu Lupas     17 April   2000  samples counter cleared for bit 0
//        olupas@opencores.org
// 3.0      Chuck Benz       20 November 2005 Translate to verilog
//
//////////////////////////////////////////////////////////////////////////////-
// Description    : Implements the receive unit of the miniUART core. Samples
//                  16 times the RxD line and retain the value in the middle of
//                  the time interval. 
//////////////////////////////////////////////////////////////////////////////-
// Entity for Receive Unit                                  //
//////////////////////////////////////////////////////////////////////////////-
module cbaf_uart_rxunit (/*AUTOARG*/
   // Outputs
   ferr, oerr, drdy, datain, 
   // Inputs
   clk, reset, enable, rxd, rd
   ) ;
   input	clk ;
   input 	reset ;
   input 	enable ;
   input 	rxd ;    // serial data
   input 	rd ;     // parallel data was taken
   output 	ferr ;
   output 	oerr ;
   output 	drdy ;   // parallel data is ready
   output [7:0] datain ;
   reg 		ferr ;
   reg 		oerr ;
   reg 		drdy ;
   reg [7:0] 	datain ;

   reg 		start, tmprxd ;
   reg [3:0] 	bitcnt, samplecnt ;
   reg [7:0] 	shtreg ;
   
   always @ (posedge clk or negedge reset)
     if (~reset) begin
	bitcnt <= 0;
	samplecnt <= 0 ;
	drdy <= 0 ;
	ferr <= 0 ;
	oerr <= 0 ;
	shtreg <= 0 ;
	datain   <= 0 ;
     end
     else begin
	if (rd == 1)
	  drdy <= 0 ;      // Data was read

	if (enable == 1) begin
	   if (start == 0) begin
	      if (rxd == 0)  begin // Start bit, l
		 samplecnt <= 1 ;
		 start <= 1 ;
	      end
	   end
	   else begin
	      if (samplecnt == 8) begin // reads the RxD line
		 tmprxd <= rxd;
	      end
	      else if (samplecnt == 15) begin
		 case (bitcnt)
		   0: begin
		      if (tmprxd == 1) // Start Bit
			start <= 0 ;
		      else
			bitcnt <= bitcnt + 1 ;
		   end
		   9: begin
		      ferr <= (tmprxd == 0) ; // stop bit expected
		      oerr <= (drdy == 1) ; // prev data not taken
		      drdy <= 1;
		      datain <= shtreg;
		      bitcnt <= 0;
		      start <= 0;
		   end
		   default: begin
		      bitcnt <= bitcnt + 1 ;
		      shtreg <= {tmprxd, shtreg[7:1]} ;
		   end
		 endcase
	      end // if (samplecnt == 15)
	      samplecnt <= samplecnt + 1 ;
	   end // else: !if(start == 0)
	end // if (enable == 1)
     end // else: !if(~reset)

endmodule
