`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:14:07 02/09/2015 
// Design Name: 
// Module Name:    top 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//pc¿¡¼­ 5¹ÙÀÌÆ® ¼Û½Å ÈÄ, ¹ÞÀº µ¥ÀÌÅÍ¸¦ Àç¼Û½ÅÇÏ´Â echo test ÇÁ·Î±×·¥ÀÌ´Ù. 
//////////////////////////////////////////////////////////////////////////////////
module top(
	input osc,
	input rxd,
	output txd
    );

					
parameter CLOCKS_PER_BIT =2604;        // baud rate : 19200, Clock : 50MHz, 10ns
parameter CLOCKS_WAIT_FOR_RECEIVE =1302;
parameter MAX_TX_BIT_COUNT =9;
parameter MAX_DATA_BUFFER_INDEX =15;

reg [11:0] tx_clk_count=0;        // clock count
reg [3:0]  tx_bit_count=0;        // bit count [start bit | d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 | stop bit]
reg [3:0]  data_buffer_index=0;
reg [2:0]  data_buffer_base=0;

reg [7:0] data_buffer [0:4];        // tx data buffer
reg [7:0] data_buffer_rx [0:4];        // rx data buffer
reg [7:0] data_tx=0;          // data to transmit

reg [7:0] rx_data=0;
reg [3:0] rx_bit_count=0;
reg [11:0] rx_clk_coun=0;
reg [32:0]sec_cnt =0;
reg state_rx=0;
reg tx_bit=0;
reg [1:0] toggle=0;
reg [22:0]timer_cnt = 0;
reg [11:0] rx_clk_count = 0;

reg [1:0]reset_cnt = 0;
reg reset = 1'b1;
always@(posedge clk_main)
begin
	if(reset==1'b1)
	begin
	reset_cnt <= reset_cnt + 1'b1;
	end 
   if(reset_cnt==2)
	begin
	reset <= 1'b0;
	end
end 
wire clk_main;
wire clk_fb, clk_fb2;
DCM_SP #(
    .CLKIN_PERIOD       (20),
    .CLKFX_DIVIDE	    (2),	
    .CLKFX_MULTIPLY   (2),
    .CLKDV_DIVIDE       (2.0),
    .CLK_FEEDBACK       ("1X")
)
DCM_SP_1 (
    .CLKIN    (osc),
    .CLKFB    (clk_fb),
    .CLK0     (clk_fb),
    .RST      (1'b0),
    .CLKFX    (clk_main),
    .PSEN     (1'b0)
);

// Transmitter Process
// at every rising edge of the clock
always @ (posedge clk_main)
begin
  if(reset == 1)begin
		tx_clk_count = 0;
		tx_bit_count = 0;
		tx_bit = 0;                     // set idle
		data_buffer_index = 4'd0;          // data index
  end
  else 
	begin
	  // transmit data until the index became the same with the base index
	 //  if ( data_buffer_index != data_buffer_base ) begin
			if(timer_cnt == 32'd5000000)
			begin
				if (tx_clk_count == CLOCKS_PER_BIT) 
					begin
						if (tx_bit_count == 0)
							begin
							tx_bit = 1'b1;     // idle bit
							tx_bit_count = 1'b1;
						   data_tx = data_buffer[data_buffer_index];			 
							end
					  else if (tx_bit_count == 1'b1) 
								  begin
										tx_bit = 0;     // start bit
										tx_bit_count = 2;
								  end
					  else if (tx_bit_count <= MAX_TX_BIT_COUNT) 
								  begin
										tx_bit = data_tx[tx_bit_count-2];   // data bits
									//	tx_bit = 1'b1;   // data bits
										tx_bit_count = tx_bit_count + 1'b1;
								  end
					  else 
								  begin
										tx_bit = 1'b1;     // stop bit
										data_buffer_index = data_buffer_index + 1'b1;  // if the index exceeds its maximum, it becomes 0.
										timer_cnt = 32'd0;
										tx_bit_count = 0;
										if(data_buffer_index == 4'd5)
										begin
											data_buffer_index = 4'd0;
										end 
								  end
					  tx_clk_count = 0;   // reset clock count
				 end
				tx_clk_count = tx_clk_count + 1'b1;        // increase clock count
		end
		else timer_cnt =  timer_cnt + 1'b1;
	end
end



  // Receiver Processs
    // at every rising edge of the clock
    always @ (posedge clk_main)
    begin
        if (reset == 1'b1) begin
            rx_clk_count = 0;
            rx_bit_count = 0;
            data_buffer_base = 3'd0;               // base index
         
            state_rx = 0;
        end
        else begin
//		  data_buffer [0]= 8'hff;
            // if not receive mode and start bit is detected
            if (state_rx == 0 && rxd == 0) begin
                state_rx = 1'b1;       // enter receive mode
                rx_bit_count = 0;
                rx_clk_count = 0;
            end
            // if receive mode
            else if (state_rx == 1'b1) begin
                 
                if(rx_bit_count == 0 && rx_clk_count == CLOCKS_WAIT_FOR_RECEIVE)
					 begin
                    rx_bit_count = 1'b1;
                    rx_clk_count = 0;
                end  
                else if(rx_bit_count < 9 && rx_clk_count == CLOCKS_PER_BIT) 
					 begin
                    rx_data[rx_bit_count-1'b1] = rxd;
                    rx_bit_count = rx_bit_count + 1'b1;
                    rx_clk_count = 0;
                end
                // stop receiving
                else if(rx_bit_count == 9 && rx_clk_count == CLOCKS_PER_BIT && rxd == 1'b1)
					 begin
                    state_rx = 0;
                    rx_clk_count = 0;
                    rx_bit_count = 0;
                     
                    // transmit the received data back to the host PC.
                    data_buffer_rx[data_buffer_base] = rx_data;
					
						  data_buffer_base = data_buffer_base + 1'b1;        // if the index exceeds its maximum, it becomes 0.
						  if(data_buffer_base == 4'd5)
						  begin
						  data_buffer_base = 3'd0;
						  end 
				  end
                // if stop bit is not received, clear the received data
                else if(rx_bit_count == 9 && rx_clk_count == CLOCKS_PER_BIT && rxd != 1'b1) 
					 begin
                    state_rx = 0;
                    rx_clk_count = 0;
                    rx_bit_count = 0;
                    rx_data = 8'b00000000;      // invalidate
                end
                rx_clk_count = rx_clk_count + 1'b1;
            end
        end
         
    end
	 always@(*)
	 begin
	 data_buffer[0] = data_buffer_rx[0];
	 data_buffer[1] = data_buffer_rx[1];
	 data_buffer[2] = data_buffer_rx[2];
	 data_buffer[3] = data_buffer_rx[3];
	 data_buffer[4] = data_buffer_rx[4];
	 end 
assign txd = tx_bit;
endmodule
