//-----------------------------------------------------

 // Design Name : uart

 // File Name   : uart.v

 // Function    : Simple UART

 // Coder       : Deepak Kumar Tala

 //-----------------------------------------------------

 module uart (

 reset          ,

 txclk          ,

 ld_tx_data     ,

 tx_data        ,

 tx_enable      ,

 tx_out         ,

 tx_empty       ,

 rxclk          ,

 uld_rx_data    ,

 rx_data        ,

 rx_enable      ,

 rx_in          ,

 rx_empty

 );

 // Port declarations

 input        reset          ;

 input        txclk          ;

 input        ld_tx_data     ;

 input  [7:0] tx_data        ;

 input        tx_enable      ;

 output       tx_out         ;

 output       tx_empty       ;

 input        rxclk          ;

 input        uld_rx_data    ;

 output [7:0] rx_data        ;

 input        rx_enable      ;

 input        rx_in          ;

 output       rx_empty       ;

 

 // Internal Variables

 reg [7:0]    tx_reg         ;

 reg          tx_empty       ;

 reg          tx_over_run    ;

 reg [3:0]    tx_cnt         ;

 reg          tx_out         ;

 reg [7:0]    rx_reg         ;

 reg [7:0]    rx_data        ;

 reg [3:0]    rx_sample_cnt  ;

 reg [3:0]    rx_cnt         ; 

 reg          rx_frame_err   ;

 reg          rx_over_run    ;

 reg          rx_empty       ;

 reg          rx_d1          ;

 reg          rx_d2          ;

 reg          rx_busy        ;

 

 // UART RX Logic

 always @ (posedge rxclk or posedge reset)

 if (reset) begin

   rx_reg        <= 0;

   rx_data       <= 0;

   rx_sample_cnt <= 0;

   rx_cnt        <= 0;

   rx_frame_err  <= 0;

   rx_over_run   <= 0;

   rx_empty      <= 1;

   rx_d1         <= 1;

   rx_d2         <= 1;

   rx_busy       <= 0;

 end else begin

   // Synchronize the asynch signal

   rx_d1 <= rx_in;

   rx_d2 <= rx_d1;

   // Uload the rx data

   if (uld_rx_data) begin

     rx_data  <= rx_reg;

     rx_empty <= 1;

   end

   // Receive data only when rx is enabled

   if (rx_enable) begin

     // Check if just received start of frame

     if ( ! rx_busy &&  ! rx_d2) begin

       rx_busy       <= 1;

       rx_sample_cnt <= 1;

       rx_cnt        <= 0;

     end

     // Start of frame detected, Proceed with rest of data

     if (rx_busy) begin

        rx_sample_cnt <= rx_sample_cnt + 1;

        // Logic to sample at middle of data

        if (rx_sample_cnt == 7) begin

           if ((rx_d2 == 1) && (rx_cnt == 0)) begin

             rx_busy <= 0;

           end else begin

             rx_cnt <= rx_cnt + 1;

             // Start storing the rx data

             if (rx_cnt > 0 && rx_cnt < 9) begin

               rx_reg[rx_cnt - 1] <= rx_d2;

             end

             if (rx_cnt == 9) begin

                rx_busy <= 0;

                // Check if End of frame received correctly

                if (rx_d2 == 0) begin

                  rx_frame_err <= 1;

                end else begin

                  rx_empty     <= 0;

                  rx_frame_err <= 0;

                  // Check if last rx data was not unloaded,

                  rx_over_run  <= (rx_empty) ? 0 : 1;

                end

             end

           end

        end

     end

   end

   if ( ! rx_enable) begin

     rx_busy <= 0;

   end

 end

 

 // UART TX Logic

 always @ (posedge txclk or posedge reset)

 if (reset) begin

   tx_reg        <= 0;

   tx_empty      <= 1;

   tx_over_run   <= 0;

   tx_out        <= 1;

   tx_cnt        <= 0;

 end else begin

    if (ld_tx_data) begin

       if ( ! tx_empty) begin

         tx_over_run <= 0;

       end else begin

         tx_reg   <= tx_data;

         tx_empty <= 0;

       end

    end

    if (tx_enable &&  ! tx_empty) begin

      tx_cnt <= tx_cnt + 1;

      if (tx_cnt == 0) begin

        tx_out <= 0;

      end

      if (tx_cnt > 0 && tx_cnt < 9) begin

         tx_out <= tx_reg[tx_cnt -1];

      end

      if (tx_cnt == 9) begin

        tx_out <= 1;

        tx_cnt <= 0;

        tx_empty <= 1;

      end

    end

    if ( ! tx_enable) begin

      tx_cnt <= 0;

    end

 end

 

 endmodule