blob: bf8e8cea4488bedb0be61906e10a23d5ed0f0560 [file] [log] [blame]
module UART_rx
#(
parameter CLOCK_SCALE_BITS = 16
)(
input wire clk,
input wire rst,
input wire[CLOCK_SCALE_BITS-1:0] cyclesPerBit, // ((CLK_FREQ + BAUD) / BAUD) - 1
input wire rx,
output wire [7:0] dataOut,
output wire dataAvailable
);
localparam STATE_IDLE = 2'b00;
localparam STATE_WAIT_HALF = 2'b01;
localparam STATE_WAIT_FULL = 2'b10;
localparam STATE_WAIT_HIGH = 2'b11;
reg[1:0] state = STATE_IDLE;
reg[CLOCK_SCALE_BITS-1:0] delayCounter = {CLOCK_SCALE_BITS{1'b0}};
wire[CLOCK_SCALE_BITS-1:0] nextDelayCounter = delayCounter + 1;
reg[2:0] bitCounter = 3'b0;
reg[7:0] savedData = 8'b0;
reg newData = 1'b0;
wire[CLOCK_SCALE_BITS-1:0] halfBitCounterValue = { 1'b0, cyclesPerBit[CLOCK_SCALE_BITS-1:1] };
always @(posedge clk) begin
if (rst) begin
state = STATE_IDLE;
delayCounter = {CLOCK_SCALE_BITS{1'b0}};
bitCounter = 3'b0;
savedData = 8'b0;
newData = 1'b0;
end else begin
newData = 1'b0;
/* When a new byte is being received, the input goes low. This is the
start bit. When the beginning of this bit is detected we need to wait
one and a half bit widths before reading in the first data bit. The
half cycle is so that we read in the middle of the bit for the most
accurate result. WAIT_HALF waits this half cycle and WAIT_FULL waits
a full cycle then reads in a bit. After 8 bits are read, the data is
output and the FSM waits for the RX input to go high again to signal
the end of the transmission. The FSM then returns to IDLE ready to
receive the next byte. */
case (state)
STATE_IDLE: begin
bitCounter = 3'b0;
delayCounter = {CLOCK_SCALE_BITS{1'b0}};
if (!rx) state = STATE_WAIT_HALF;
end
STATE_WAIT_HALF: begin
if (nextDelayCounter == halfBitCounterValue) begin
delayCounter = 0;
state = STATE_WAIT_FULL;
end else begin
delayCounter = nextDelayCounter;
end
end
STATE_WAIT_FULL: begin
if (nextDelayCounter == cyclesPerBit) begin
savedData = {rx, savedData[7:1]};
delayCounter = 0;
if (bitCounter == 3'h7) begin
state = STATE_WAIT_HIGH;
newData = 1'b1;
end else bitCounter = bitCounter + 1;
end else begin
delayCounter = nextDelayCounter;
end
end
STATE_WAIT_HIGH: begin
if (rx) state = STATE_IDLE;
end
default: state = STATE_IDLE;
endcase
end
end
assign dataOut = savedData;
assign dataAvailable = newData;
endmodule