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

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [XUPV5-LX110T_SoC/] [MIPS32-Pipelined-Hw/] [src/] [UART/] [uart_rx.v] - Rev 2

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
/*
 * File         : uart_rx.v
 * Project      : University of Utah, XUM Project MIPS32 core
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
 *
 * Modification History:
 *   Rev   Date         Initials  Description of Change
 *   1.0   26-May-2010  GEA       Initial design.
 *
 * Standards/Formatting:
 *   Verilog 2001, 4 soft tab, wide column.
 *
 * Description:
 *   Recovers received data from the serial port with 16x clock over-sampling.
 *   'data_ready' is a synchronous pulse indicator. 8N1.
 */
module uart_rx(
    input clock,
    input reset,
    input RxD,
    input uart_tick_16x,
    output reg [7:0] RxD_data = 0,
    output data_ready
    );
 
    /* Synchronize incoming RxD */
    reg [1:0] RxD_sync = 2'b11; //0;
    always @(posedge clock) RxD_sync <= (uart_tick_16x) ? {RxD_sync[0], RxD} : RxD_sync;
 
    /* Filter Input */
    reg [1:0] RxD_cnt = 0;
    reg RxD_bit = 1; //0;
    always @(posedge clock) begin
        if (uart_tick_16x) begin
            case (RxD_sync[1])
                0:  RxD_cnt <= (RxD_cnt == 2'b11) ? RxD_cnt : RxD_cnt + 1;
                1:  RxD_cnt <= (RxD_cnt == 2'b00) ? RxD_cnt : RxD_cnt - 1;
            endcase
            RxD_bit <= (RxD_cnt == 2'b11) ? 0 : ((RxD_cnt == 2'b00) ? 1 : RxD_bit);
        end
        else begin
            RxD_cnt <= RxD_cnt;
            RxD_bit <= RxD_bit;
        end
    end
 
    /* State Definitions */
    localparam [3:0] IDLE=0, BIT_0=1, BIT_1=2, BIT_2=3, BIT_3=4, BIT_4=5, BIT_5=6,
                     BIT_6=7, BIT_7=8, STOP=9;
    reg [3:0] state = IDLE;
 
    /* Next-bit spacing and clock locking */
    reg clock_lock = 0;
    reg [3:0] bit_spacing = 4'b1110;   // Enable quick jumping from IDLE to BIT_0 when line was idle.
    always @(posedge clock) begin
       if (uart_tick_16x) begin
          if (~clock_lock) clock_lock <= ~RxD_bit; // We lock on when we detect a filtered 0 from idle
          else clock_lock <= ((state == IDLE) && (RxD_bit == 1'b1)) ? 0 : clock_lock;
          bit_spacing <= (clock_lock) ? bit_spacing + 1 : 4'b1110;
       end
       else begin
          clock_lock <= clock_lock;
          bit_spacing <= bit_spacing;
       end
    end
    wire next_bit = (bit_spacing == 4'b1111);
 
    /* State Machine */
    always @(posedge clock) begin
        if (reset) state <= IDLE;
        else if (uart_tick_16x) begin
            case (state)
                IDLE:   state <= (next_bit & (RxD_bit == 1'b0)) ? BIT_0 : IDLE;  // Start bit is 0
                BIT_0:  state <= (next_bit) ? BIT_1 : BIT_0;
                BIT_1:  state <= (next_bit) ? BIT_2 : BIT_1;
                BIT_2:  state <= (next_bit) ? BIT_3 : BIT_2;
                BIT_3:  state <= (next_bit) ? BIT_4 : BIT_3;
                BIT_4:  state <= (next_bit) ? BIT_5 : BIT_4;
                BIT_5:  state <= (next_bit) ? BIT_6 : BIT_5;
                BIT_6:  state <= (next_bit) ? BIT_7 : BIT_6;
                BIT_7:  state <= (next_bit) ? STOP  : BIT_7;
                STOP:   state <= (next_bit) ? IDLE  : STOP;
                default: state <= 4'bxxxx;
            endcase
        end
        else state <= state;
    end
 
    /* Shift Register to Collect Rx bits as they come */
    wire capture = (uart_tick_16x & next_bit & (state!=IDLE) & (state!=STOP));
    always @(posedge clock) RxD_data <= (capture) ? {RxD_bit, RxD_data[7:1]} : RxD_data[7:0];
    assign data_ready = (uart_tick_16x & next_bit & (state==STOP));
 
endmodule
 

Go to most recent revision | 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.