OpenCores
URL https://opencores.org/ocsvn/rtfsimpleuart/rtfsimpleuart/trunk

Subversion Repositories rtfsimpleuart

[/] [rtfsimpleuart/] [trunk/] [rtl/] [verilog/] [rtfSimpleUartRx.v] - Rev 15

Compare with Previous | Blame | View Log

// ============================================================================
//	(C) 2011,2013,2015  Robert Finch
//  All rights reserved.
//	robfinch@<remove>finitron.ca
//
//	rtfSimpleUartRx.v
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//	Simple UART receiver core
//		Features:
//			false start bit detection
//			framing error detection
//			overrun state detection
//			resynchronization on every character
//			fixed format 1 start - 8 data - 1 stop bits
//			uses 16x clock rate
//			
//		This core may be used as a standalone peripheral
//	on a SoC bus if all that is desired is recieve
//	capability. It requires a 16x baud rate clock.
//	
//   	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|WISHBONE Datasheet
//	|WISHBONE SoC Architecture Specification, Revision B.3
//	|
//	|Description:						Specifications:
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|General Description:				simple serial UART receiver
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|Supported Cycles:					SLAVE,READ
//	|									SLAVE,BLOCK READ
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|Data port, size:					8 bit
//	|Data port, granularity:			8 bit
//	|Data port, maximum operand size:	8 bit
//	|Data transfer ordering:			Undefined
//	|Data transfer sequencing:			Undefined
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|Clock frequency constraints:		none
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|Supported signal list and			Signal Name		WISHBONE equiv.
//	|cross reference to equivalent		ack_o			ACK_O
//	|WISHBONE signals					
//	|									clk_i			CLK_I
//	|                                   rst_i           RST_I
//	|									dat_o(7:0)		DAT_O()
//	|									cyc_i			CYC_I
//	|									stb_i			STB_I
//	|									we_i			WE_I
//	|
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	|Special requirements:
//	+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
//	Ref: Spartan3 -4
//	27 LUTs / 24 slices / 170 MHz
//==============================================================================
 
`define IDLE	0
`define CNT		1
 
module rtfSimpleUartRx(
	// WISHBONE SoC bus interface
	input rst_i,			// reset
	input clk_i,			// clock
	input cyc_i,			// cycle is valid
	input stb_i,			// strobe
	output ack_o,			// data is ready
	input we_i,				// write (this signal is used to qualify reads)
	output [7:0] dat_o,		// data out
	//------------------------
	input cs_i,				// chip select
	input baud16x_ce,		// baud rate clock enable
    input tri0 baud8x,       // switches to mode baudX8
	input clear,			// clear reciever
	input rxd,				// external serial input
	output reg data_present,	// data present in fifo
	output reg frame_err,		// framing error
	output reg overrun			// receiver overrun
);
 
//0 - simple sampling at middle of symbol period
//>0 - sampling of 3 middle ticks of sumbol perion and results as majority
parameter SamplerStyle = 0;
 
// variables
reg [7:0] cnt;			// sample bit rate counter
reg [9:0] rx_data;		// working receive data register
reg state;				// state machine
reg wf;					// buffer write
reg [7:0] dat;
 
wire isX8;
buf(isX8, baud8x);
reg modeX8;
 
assign ack_o = cyc_i & stb_i & cs_i;
assign dat_o = ack_o ? dat : 8'b0;
 
// update data register
always @(posedge clk_i)
	if (wf) dat <= rx_data[8:1];
 
// on a read clear the data present status
// but set the status when the data register
// is updated by the receiver		
always @(posedge clk_i)
    if (rst_i)
        data_present <= 0;
    else if (wf) 
        data_present <= 1;
	else if (ack_o & ~we_i) data_present <= 0;
 
 
// Three stage synchronizer to synchronize incoming data to
// the local clock (avoids metastability).
reg [5:0] rxdd          /* synthesis ramstyle = "logic" */; // synchronizer flops
reg rxdsmp;             // majority samples
reg rdxstart;           // for majority style sample solid 3tik-wide sample
reg [1:0] rxdsum;
always @(posedge clk_i)
if (baud16x_ce) begin
	rxdd <= {rxdd[4:0],rxd};
    if (SamplerStyle == 0) begin
        rxdsmp <= rxdd[3];
        rdxstart <= rxdd[4]&~rxdd[3];
    end
    else begin
        rxdsum[1] <= rxdsum[0];
        rxdsum[0] <= {1'b0,rxdd[3]} + {1'b0,rxdd[4]} + {1'b0,rxdd[5]};
        rxdsmp <= rxdsum[1];
        rdxstart <= (rxdsum[0] == 2'b00) & ((rxdsum[1] == 2'b11));
    end
end
 
 
`define CNT_FRAME  (8'h97)
`define CNT_FINISH (8'h9D)
 
always @(posedge clk_i) begin
	if (rst_i) begin
		state <= `IDLE;
		wf <= 1'b0;
		overrun <= 1'b0;
        frame_err <= 1'b0;
	end
	else begin
 
		// Clear write flag
		wf <= 1'b0;
 
		if (clear) begin
			wf <= 1'b0;
			state <= `IDLE;
			overrun <= 1'b0;
            frame_err <= 1'b0;
		end
 
		else if (baud16x_ce) begin
 
			case (state)
 
			// Sit in the idle state until a start bit is
			// detected.
			`IDLE:
				// look for start bit
				if (rdxstart)
					state <= `CNT;
 
			`CNT:
				begin
					// End of the frame ?
					// - check for framing error
					// - write data to read buffer
					if (cnt==`CNT_FRAME)
						begin	
							frame_err <= ~rxdsmp;
                            overrun <= data_present;
							if (!data_present)
								wf <= 1'b1;
                            state <= `IDLE;
						end
					// Switch back to the idle state a little
					// bit too soon.
					//if (cnt==`CNT_FINISH) begin
					//	state <= `IDLE;
                    //end
 
					// On start bit check make sure the start
					// bit is low, otherwise go back to the
					// idle state because it's a false start.
					if (cnt==8'h07 && rxdsmp)
						state <= `IDLE;
 
					if (cnt[3:0]==4'h7)
						rx_data <= {rxdsmp,rx_data[9:1]};
				end
 
			endcase
		end
	end
end
 
 
// bit rate counter
always @(posedge clk_i)
	if (baud16x_ce) begin
		if (state == `IDLE) begin
			cnt <= modeX8;
            modeX8 <= isX8;
        end
        else begin
            cnt[7:1] <= cnt[7:1] + cnt[0];
            cnt[0] <= ~cnt[0] | (modeX8);
        end
	end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.