//----------------------------------------------------------------------------------
// Company:        hdLab
// Engineer:       K.Date
// 
// Create Date:    06/15/2015 
// Design Name:    NEXYS4_verilog
// Module Name:    uart_rx_ctl 
// Project Name:   NEXYS4
// Target Devices: Artix-7
// Tool versions:  Vivado2014.3
// Description: 
//
// Dependencies: 
//
// Revision: 1.00
// Revision 1.00 - File converted to verilog
// Additional Comments: 
//
//--------------------------------------------------------------------------------
/*
-- -----------------------------------------------------------------------------
--
-- module:    uart_rx_ctl
-- project:   wave_gen
-- company:   Xilinx, Inc.
-- author:    WK, AW
-- 
-- comment:
--   UART receiver  controller
--   Implements the state machines for doing RS232  reception.
--   
-- Based on the detection of the falling edge of the synchronized  rxd
--   input, this module waits 1/2 of a bit period (8 periods of  baud_x16_en)
--   to find the middle of the start bit, and resamples it. If rxd  
--   is still low it accepts it as a valid START bit, and captures the  rest
--   of the character, otherwise it rejects the start bit and returns  to
--    idle.
--   
-- After detecting the START bit, it advances 1 full bit period at a  time
--   (16 periods of baud_x16_en) to end up in the middle of the 8  data
--   bits, where it samples the 8 data bits.  
--   
-- After the last bit is sampled (the MSbit, since the LSbit is  sent
--   first), it waits one additional bit period to check for the STOP  bit.
--   If the rxd line is not high (the value of a STOP bit), a framing  error
--   is signalled. Regardless of the value of the rxd, though, the  module
--   returns to the IDLE state and immediately begins looking for the  
--   start of the next  character.
--   
-- NOTE: The total cycle time through the state machine is 9 1/2  bit
--   periods (not 10) - this allows for a mismatch between the transmit  and
--   receive clock rates by as much as  5%.
--   
-- Multicycle and False  Paths
--   All flip-flops within this module share the same chip enable,  generated
--   by the Baud rate generator. Hence, all paths from FFs to FFs in  this
--   module are multicycle paths.
-- 
-- known issues:
-- status           id     found     description                      by fixed date  by    comment
-- 
-- version history:
--   version    date    author     description
--    11.1-001 20 APR 2009 WK       First version for 11.1          
-- 
-- ---------------------------------------------------------------------------
-- 
-- disclaimer:
--   Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs  are
--   provided to you as is . Xilinx and its licensors make, and  you
--   receive no warranties or conditions, express,  implied,
--   statutory or otherwise, and Xilinx specifically disclaims  any
--   implied warranties of merchantability, non-infringement,  or
--   fitness for a particular purpose. Xilinx does not warrant  that
--   the functions contained in these designs will meet  your
--   requirements, or that the operation of these designs will  be
--   uninterrupted or error free, or that defects in the  Designs
--   will be corrected. Furthermore, Xilinx does not warrant  or
--   make any representations regarding use or the results of  the
--   use of the designs in terms of correctness,  accuracy,
--   reliability, or  otherwise.
--   
-- LIMITATION OF LIABILITY. In no event will Xilinx or  its
--   licensors be liable for any loss of data, lost profits,  cost
--   or procurement of substitute goods or services, or for  any
--   special, incidental, consequential, or indirect  damages
--   arising from the use or operation of the designs  or
--   accompanying documentation, however caused and on any  theory
--   of liability. This limitation will apply even if  Xilinx
--   has been advised of the possibility of such damage.  This
--   limitation shall apply not-withstanding the failure of  the
--   essential purpose of any limited remedies  herein.
--   
-- Copyright © 2002, 2008, 2009 Xilinx,  Inc.
--   All rights reserved
-- 
-- -----------------------------------------------------------------------------
*/

module uart_rx_ctl (
    input        clk_rx,
    input        rst_clk_rx,
    input        baud_x16_en,
    input        rxd_clk_rx,
    output reg [7:0] rx_data,
    output reg       rx_data_rdy,
    output reg       frm_err
    );

    //type legal_rx_states is ( IDLE, START, DATA, STOP );
    parameter IDLE = 2'b00;
    parameter START= 2'b01;
    parameter DATA = 2'b10;
    parameter STOP = 2'b11;

    reg [1:0] state  = IDLE;

(* keep = "true" *)    reg [3:0] bit_cnt = 4'b0;           // capture up to 8 bits of data
(* keep = "true" *)    reg       over_sample_cnt_done;     // should now be in the middle of the bit
(* keep = "true" *)    wire      bit_cnt_done;             // indicates that all the data has been collected
(* keep = "true" *)    reg [3:0] over_sample_cnt = 4'd0;    // each bit is sampled 16 times
         

    //attribute keep : string; 
    //attribute keep of bit_cnt: signal is "TRUE";
    //attribute keep of bit_cnt_done: signal is "TRUE";
    //attribute keep of over_sample_cnt_done: signal is "TRUE";

    // compute the next state
    // genNextState: process (clk_rx)
    always @ ( posedge clk_rx ) begin
        if ( rst_clk_rx == 1'b1 )                          // if the reset is asserted
                            state <= IDLE;                 // head back to the IDLE state
        else if ( baud_x16_en == 1'b1 ) begin              // 16 times per bit...
            case (state)                                   // locate the tasks for this state
                IDLE : // stay here until the receiver line drops low, indicating a START bit
                    if ( rxd_clk_rx == 1'b0 )              // is the receive line low?
                            state <= START;                // yes! transition to the START state
                                                           // end of test for receive line low  
                START :// verify this was not a glitch and consume the start bit
                    if ( over_sample_cnt_done == 1'b1 )    // after 1/2 a bit time, then
                        if ( rxd_clk_rx == 1'b0 )          // is the line still low?
                            state <= DATA;                 // really was the start bit, start collecting DATA
                        else                               // line is back high, must have been a glitch
                            state <= IDLE;                 // return to the IDLE state and resume looking for the START bit
                                                           // end of checking if the line is still low
                                                           // end of 1/2 bit time check
                DATA :// collect 8 bits of data
                    if ((over_sample_cnt_done == 1'b1) && (bit_cnt_done == 1'b1)) // if this bit is done ANDall 8 bits are done
                            state <= STOP;                 // transition to testing for the STOP bit
                                                           // end of check to see if all data has been collected
                            
                STOP :// test for the stop bit
                    if (over_sample_cnt_done == 1'b1 )     // have we captured another bit?
                            state <= IDLE;                 // return to looking for the next START bit
                                                           // end test of capturing STOP bit
                
                default :// catchall state - usually optimized out unless explicity kept
                            state <= IDLE;                 // if the state machine broke, recover by jumping to the IDLE state
            endcase                                        // end of case for determining which state
        end;                                               // end of 16 times per bit activities
    end;                                                   // end of synchronous events
    //end process genNextState;
       
    //       Oversample counter
    //       Pre-load to 7 when a start condition is detected (rxd_sync is 0 while in
    //       IDLE) - this will get us to the middle of the first bit.
    //       Pre-load to 15 after the START is confirmed and between all data bits.
    //       oversample_counter: process (clk_rx)
       
    always @ ( posedge clk_rx ) begin                       // when the rising edge of the clock hits, then...
        if ( rst_clk_rx == 1'b1 ) begin                     // if the reset is asserted
            over_sample_cnt <= 4'd7;                        // reset the counter, since the first state is IDLE, preset the count to 1/2 a bit width
            over_sample_cnt_done <= 1'b0;                   // don't tic during reset (initial condition)        
        end else begin                                      // otherwise, do non-reset activities         
        // countdown if 16x baudrate is enabled
            if ( baud_x16_en == 1'b1 ) begin                // 16 times per bit...  
                if (over_sample_cnt != 4'd0) begin          // if the count is not yet complete,
                    over_sample_cnt <= over_sample_cnt - 1; // then decrement the counter
                    if ( over_sample_cnt == 1)              // are we done yet?    !note differ from VHDL
                        over_sample_cnt_done <= 1'b1;       // indicate that this count is complete
                    //else 
                    //    over_sample_cnt_done <= 1'b0;       // indicate that this count is complete
                                                            // end of count check

                      // if the count has completed, should we preset the count?
                end else begin                              // tasks that can be performed between sync pulses - prep for next count
                        over_sample_cnt_done <= 1'b0;       // can only be set above - if here, it must be cleared
                    if ( ( state == IDLE ) && ( rxd_clk_rx == 1'b0 ))  // if getting ready to look at IDLE, then 
                        over_sample_cnt <= 4'd7;            // we need only wait 1/2 a bit width
                    else if (((state == START) && (rxd_clk_rx == 1'b0)) || //  if we're in the start state and the line is low (start bit) or
                               (state == DATA))             // if we're collecting data
                        over_sample_cnt <= 4'd15;           // count the full 16 sample times
                                                            // end of check for times which require 16 counts
                end                                         // end check of completion of count
            end                                             // end of check for over sample enable
        end                                                 // end of non-reset activities
    end                                                     // end of synchronous events
    //          end process oversample_counter;
          
          
       // Track which bit we are about to receive
       // Set to 0 when we confirm the start condition
       // Increment in all DATA states
    //       bitTracker: process (clk_rx)

    always @ ( posedge clk_rx ) begin                       // when the rising edge of the clock hits, then...
        if (rst_clk_rx == 1'b1) begin                       // if the reset is asserted
                   bit_cnt <= 4'b0;                            // reset the bit count
        end else begin                                      // otherwise, do non-reset activities
            if (baud_x16_en == 1'b1) begin                  // 16 times per bit...           
                if (over_sample_cnt_done == 1'b1) begin     // has the count completed          
                    if (state == START)                     // action depends on which state we're in                      
                        bit_cnt <= 4'b0;                      // clear the count as we're now starting
                    else if (state == DATA)                 // collecting data?                        
                        bit_cnt <= bit_cnt + 1;             // one more piece of data gathered               
                                                            // state checks
                end                                         // end of count not completed
            end                                             // end of oversample enabled tasks
        end                                                 // end of non-reset activities         
    end                                                     // end of synchronous events
    //          end process bitTracker;          

    assign  bit_cnt_done =  (bit_cnt == 4'd7) ? 1'b1 : 1'b0;   // this is the last bit when bit_cnt = 7
          
    // Capture the data and generate the rdy signal
    // The rdy signal will be generated as soon as the last bit of data
    // is captured - even though the STOP bit hasn't been confirmed. It will
    // remain asserted for one BIT period (16 baud_x16_en periods)    

    //       outCtrl: process (clk_rx)
    always @ ( posedge clk_rx ) begin                       // when the rising edge of the clock hits, then...
        if ( rst_clk_rx == 1'b1 ) begin                     // if the reset is asserted
                    rx_data     <= 8'h00;                   // drive the output to all zeros
                    rx_data_rdy <= 1'b0;                    // ensure that the data ready signal is inactive   
        end else begin                                      // otherwise, do non-reset activities
            if ((baud_x16_en == 1'b1 ) && (over_sample_cnt_done == 1'b1)) begin     // 16 times per bit... AND time to keep this sample
                    rx_data_rdy <= 1'b0;                    // keep the data ready deasserted                     
                if (state == DATA && bit_cnt < 4'd8) begin     // if we were capturing data, but not the stop bit                   
                    //rx_data[bit_cnt] <= rxd_clk_rx;         // capture this bit and stick it in the right place
                    case(bit_cnt)
                    4'b0000 : rx_data[0] <= rxd_clk_rx;
                    4'b0001 : rx_data[1] <= rxd_clk_rx;
                    4'b0010 : rx_data[2] <= rxd_clk_rx;
                    4'b0011 : rx_data[3] <= rxd_clk_rx;
                    4'b0100 : rx_data[4] <= rxd_clk_rx;
                    4'b0101 : rx_data[5] <= rxd_clk_rx;
                    4'b0110 : rx_data[6] <= rxd_clk_rx;
                    4'b0111 : rx_data[7] <= rxd_clk_rx;
                    default : ;
                    endcase
                end else if (state == STOP && over_sample_cnt_done == 1'b1) begin  // if we're in the stop state and we're done with the counting, then the stop bit has been captured                         
                    rx_data_rdy <= 1'b1;                    // assert the data ready
                end                                         // end of check to see if we were capturing data
            end                                             // end of oversample check
        end                                                 // end of non-reset activities
    end                                                     // end of synchronous events
    //          end process; 

    // Framing error generation
    // Generate for one baud_x16_en period as soon as the framing bit
    // is supposed to be sampled

    //     ferrGen: process (clk_rx)
    always @ ( posedge clk_rx )                         // when the rising edge of the clock hits, then...
        if ( rst_clk_rx == 1'b1 )                       // if the reset is asserted
                         frm_err <= 1'b0;               // ensure that the framing error is disabled
        else                                            // otherwise, do non-reset activities
            if ( baud_x16_en == 1'b1 )                  // 16 times per bit...     
                if ( state == STOP &&                   // if we're in the last state (STOP) and
                     over_sample_cnt_done == 1'b1  &&   // we've finished counting and
                     rxd_clk_rx == 1'b0 )               // the line is low, then 
                         frm_err <= 1'b1;               // no error present
                else                                    // otherwise
                         frm_err <= 1'b0;               // no error present
                                                        // end of check for conditions that would generate a framing error
                                                        // end of oversample check
                                                        // end of non-reset activities
                                                        // end of synchronous events    
endmodule