Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module RS232(
- input CLOCK_50, RESET, RX, SEND_DATA, DATA_READ,
- input [7:0] DATA_IN,
- output TX, DATA_READY, DATA_SENT, SAMPLE,
- output [7:0] DATA_OUT
- );
- // This module is a basic RS-232 transmitter and receiver. The TX and RX functions are completely separte and do not communicate.
- //
- // Parameters:
- // Baud = 3000000
- // One start bit
- // One stop bit
- // Inverted
- //
- // Operation:
- // RX
- // This module will watch the RX line for the start bit. If it receives a start bit it will record the data and push it on a FIFO
- // When data is ready it will assert the DATA_READY output. It will hold this high until the DATA_READ input is asserted. Nothing
- // here is guaranteed to happen in one cycle. The reading of data takes precedence over handshaking output data. Data will be held
- // until new data over writes it.
- // Define internal registers
- reg[3:0] data_count, data_count_next, state, state_next;
- reg tx_int, tx_int_next, flag, flag_next, data_ready_int, data_ready_int_next, data_sent_int, data_sent_int_next, sample_int, sample_int_next;
- reg[5:0] counter, counter_next, read_counter, read_counter_next;
- reg[7:0] data_out_int, data_out_int_next;
- // Define connections
- //assign TX = tx_int_next;
- assign DATA_READY = data_ready_int;
- assign DATA_SENT = data_sent_int;
- assign DATA_OUT = data_out_int;
- assign SAMPLE = sample_int;
- // Define states
- localparam [3:0]
- Init = 0,
- Idle = 1,
- Start_Bit = 2,
- Read = 3,
- Stop_Bit = 4,
- Wait = 5;
- // Define sequential logic
- always @(posedge CLOCK_50)
- begin
- if(!RESET)
- begin
- data_count <= 0;
- state <= Init;
- tx_int <= 0; // Check
- flag <= 0;
- data_ready_int <= 0;
- data_sent_int <= 0;
- counter <= 0;
- data_out_int <= 0;
- read_counter <= 0;
- sample_int <= 0;
- end
- else
- begin
- data_count <= data_count_next;
- state <= state_next;
- tx_int <= tx_int_next;
- flag <= flag_next;
- data_ready_int <= data_ready_int_next;
- data_sent_int <= data_sent_int_next;
- counter <= counter_next;
- data_out_int <= data_out_int_next;
- read_counter <= read_counter_next;
- sample_int <= sample_int_next;
- end
- end
- // Define combintation logic
- always @*
- begin
- // Define default transitions
- data_count_next = data_count;
- data_out_int_next = data_out_int;
- state_next = state;
- tx_int_next = tx_int;
- flag_next = flag;
- data_ready_int_next = data_ready_int;
- data_sent_int_next = data_sent_int;
- counter_next = counter;
- read_counter_next = read_counter;
- sample_int_next = sample_int;
- // Define state machine
- case(state)
- Init: // Intialize all registers
- begin
- data_count_next = 0;
- data_out_int_next = 0;
- tx_int_next = 0; // Check
- flag_next = 0;
- data_ready_int_next = 0;
- data_sent_int_next = 0;
- counter_next = 0;
- read_counter_next = 0;
- sample_int_next = 0;
- state_next = Idle;
- end
- Idle: // Main Idle process. Each cycle in the Idle process the RX line is checked first for the start bit.
- begin
- data_out_int_next = data_out_int; // Hold the previous data.
- sample_int_next = 1;
- if(!RX) // Check if the start bit has come(low)
- begin
- counter_next = 0;
- state_next = Start_Bit;
- end
- else // If the start bit is not here continue
- begin
- if(data_count == 0) // If data count is zero, then no data is available, stay in idle and keep data_ready low
- begin
- data_ready_int_next = 0;
- state_next = Idle;
- end
- else // If data count is not zero, then data needs to be given to controller
- begin
- if(flag) // The purpose of this flag is to determine if the data has been read already by the controller.
- begin // If flag is high, then the data has been read by the controller. If so, we pull data ready low, then wait for DATA_READ to go low. Finishing the hand shake
- if(DATA_READ) // Wait for DATA_READ to go low
- begin
- state_next = Idle;
- end
- else // Read complete, reset
- begin
- data_count_next = data_count - 1;
- flag_next = 0;
- data_ready_int_next = 0;
- state_next = Idle;
- end
- end
- else // If flag is low, then data has not been read. Assert DATA_READY then wait for DATA_READ to go high.
- begin
- if(DATA_READ) // If DATA_READ goes high, then assert flag and pull low DATA_READY
- begin
- flag_next = 1;
- data_ready_int_next = 0;
- state_next = Idle;
- end
- else // Wait for DATA_READ to go high.
- begin
- flag_next = 0;
- data_ready_int_next = 1;
- state_next = Idle;
- end
- end
- end
- end
- end
- Start_Bit: // Wait 20 cycles to get past start bit
- begin
- sample_int_next = 0;
- counter_next = counter + 1;
- if(counter == 20)
- begin
- counter_next = 16; // This is needed for convenience, tells it to read immediately in the next state.
- read_counter_next = 0;
- state_next = Read;
- end
- else
- begin
- state_next = Start_Bit;
- end
- end
- Read: // Read 8 bits of data.
- begin
- counter_next = counter + 1;
- sample_int_next = 0;
- if(read_counter == 8) // Count 8 reads, then go to wait state to avoid stop bit.
- begin
- sample_int_next = 0;
- data_count_next = data_count + 1;
- read_counter_next = 0;
- counter_next = 0;
- state_next = Wait;
- end
- else
- begin
- if(counter == 16) // Wait 16 cycles between reads.
- begin
- data_out_int_next = {RX, data_out_int[7:1]}; // Shift data in.
- counter_next = 0;
- read_counter_next = read_counter + 1;
- sample_int_next = 1;
- state_next = Read;
- end
- else
- begin
- state_next = Read;
- end
- end
- end
- Wait: // Wait for stop bit to pass before entering Idle state again.
- begin
- sample_int_next = 0;
- if(RX)
- begin
- sample_int_next = 0;
- state_next = Idle;
- end
- else
- begin
- state_next = Wait;
- end
- end
- default: state_next = Init;
- endcase
- end
- endmodule
Add Comment
Please, Sign In to add comment