`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// en_rs485gineer: 
// 
// Create Date:    14:25:05 02/09/2015 
// Design Name: 
// Module Name:    top 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependen_rs485cies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Commen_rs485ts: 
//pc에서 5바이트 송신 후, 받은 데이터를 재송신하는 echo test 프로그램이다. 
//////////////////////////////////////////////////////////////////////////////////
module test(
	input osc,
	input rxd_rs485,
	output txd_rs485,
	output en_rs485
    );
wire clk_main;
wire clk_fb, clk_fb2;	 
reg [1:0]reset_cnt = 0;
reg reset = 1'b1;
always@(posedge osc)
begin
	if(reset==1'b1)
	begin
	reset_cnt <= reset_cnt + 1'b1;
	end 
   if(reset_cnt==2)
	begin
	reset <= 1'b0;
	end
end 									
parameter CLOCKS_PER_BIT =2604;        // baud rate : 19200, Clock : 50MHz, 20ns
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 [2: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 [31:0]timer_cnt = 0;
reg [11:0] rx_clk_count = 0;
reg TxFlag = 0;
reg TxFlag_ff = 0;
wire Tick_TxFlag;
wire Tick_RxFlag;
reg [2:0]state_ff = 0;
reg [3:0]state = 0;
reg [31:0]time_cnt2=0;
reg rx_en_rs485 =0;
reg tx_en_rs485 =0;
wire rx_tx_en_rs485;
parameter S0 = 0,S1 = 1,S2 = 2,S3 = 3,S4 = 4;
// Transmitter Process
// at every rising edge of the clock
always @ (posedge osc)
begin
  if(reset == 1)begin
		tx_clk_count = 0;
		tx_bit_count = 0;
		tx_bit = 0;                     // set idle
		data_buffer_index = 3'd0;          // data index
		tx_en_rs485 = 1'b0;
  end
  else 
	begin
	  // transmit data until the index became the same with the base index
	   //if ( data_buffer_index != data_buffer_base ) begin
         if(!rx_en_rs485) tx_en_rs485 = 1'b0; //tx_en_rs485 reset!
		   if(en_rs485 == 1'b1) //송수신 제어 핀
			begin	
					if (tx_clk_count == CLOCKS_PER_BIT) 
						begin
							if (tx_bit_count == 0)
								begin
								tx_bit = 1;     // idle bit
								tx_bit_count = 1;
								data_tx = data_buffer[data_buffer_index];			 
								end
						  else if (tx_bit_count == 1'b1) 
								begin
								tx_bit = 0;     // start bit
//								tx_en_rs485 = 1'b0;  //rx reset!
								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 if (tx_bit_count == MAX_TX_BIT_COUNT + 1'b1)
							    begin	
										tx_bit = 1'b1;     // stop bit
										data_buffer_index = data_buffer_index + 1'b1;  // if the index exceeds its maximum, it becomes 0.
										if(data_buffer_index == 3'd5)
										begin
										timer_cnt = 32'd0;
										data_buffer_index = 3'd0;				
										tx_en_rs485 = 1'b1;
										end 
										tx_bit_count = tx_bit_count + 1'b1;
								 end
							 else if (tx_bit_count <50)//50
								begin
									 tx_bit_count = tx_bit_count + 1'b1;
								end
							else
								begin
								tx_bit_count = 0;
								end
						  tx_clk_count = 0;   // reset clock count
					 end
					tx_clk_count = tx_clk_count + 1'b1;        // increase clock count
		end
	end
end
assign txd_rs485 =tx_bit;
assign en_rs485 = TxFlag; //rs485 rx or tx control
                    // 1'b1 tx mode
						  // 1'b0 rx mode


reg [31:0]timer_cnt_state = 0;
always@(posedge osc)
begin
if(reset == 1'b1)
begin
		TxFlag <= 1'b0;
		timer_cnt_state <= 32'd0;
		state <= S0;	
end
else
begin
	case(state)
	S0:
	begin
		if (rx_en_rs485 == 1'b1)
		begin
			state <= S1;	
			TxFlag <= 1'b1;
		end  
	end 
	S1:
	begin
		if (tx_en_rs485 == 1'b1)
		begin
			state <= S2;	
		end 
	end 
	S2:
	begin
		if(timer_cnt_state == 32'd10000)
		begin
			timer_cnt_state <= 32'd0;
				state <= S3;	
		end 
		else timer_cnt_state <= timer_cnt_state + 1'b1;
	
	end 
	S3:
	begin
			TxFlag <= 1'b0;
			state <= S4;	
	end 
	S4:
	begin
	if (rx_en_rs485 == 1'b0)
		begin
			state <= S0;	
		end  
	end 
	endcase 
end
end 
  // Receiver Processs
    // at every rising edge of the clock
    always @ (posedge osc)
    begin
        if (reset == 1'b1) begin
            rx_clk_count = 0;
            rx_bit_count = 0;
            data_buffer_base = 3'd0;               // base index
            state_rx = 0;
				rx_en_rs485 = 1'b0;
        end

        else 
				begin
             if (state_rx == 0 && rxd_rs485 == 0) 
					begin
						 state_rx = 1'b1;       // en_rs485ter receive mode
						 rx_bit_count = 0;
						 rx_clk_count = 0;
					end

            // if receive mode
            else if (state_rx == 1'b1) 
					begin
                 rx_en_rs485 = 1'b0; //rx reset!
                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_rs485;
							  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_rs485 == 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 == 3'd5)
							  begin
							  data_buffer_base = 3'd0;
							  rx_en_rs485 = 1'b1;
							  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_rs485 != 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] = 8'h01;
	 data_buffer[1] = 8'h02;
	 data_buffer[2] = 8'h03;
	 data_buffer[3] = 8'h04;
	 data_buffer[4] = 8'h05;
	 end

endmodule
