//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
// uart receive module
|
// uart receive module
|
//
|
//
|
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
|
|
module uart_rx
|
module uart_rx
|
(
|
(
|
clock, reset,
|
clock, reset,
|
ce_16, ser_in,
|
ce_16, ser_in,
|
rx_data, new_rx_data
|
rx_data, new_rx_data
|
);
|
);
|
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
// modules inputs and outputs
|
// modules inputs and outputs
|
input clock; // global clock input
|
input clock; // global clock input
|
input reset; // global reset input
|
input reset; // global reset input
|
input ce_16; // baud rate multiplyed by 16 - generated by baud module
|
input ce_16; // baud rate multiplyed by 16 - generated by baud module
|
input ser_in; // serial data input
|
input ser_in; // serial data input
|
output [7:0] rx_data; // data byte received
|
output [7:0] rx_data; // data byte received
|
output new_rx_data; // signs that a new byte was received
|
output new_rx_data; // signs that a new byte was received
|
|
|
// internal wires
|
// internal wires
|
wire ce_1; // clock enable at bit rate
|
wire ce_1; // clock enable at bit rate
|
wire ce_1_mid; // clock enable at the middle of each bit - used to sample data
|
wire ce_1_mid; // clock enable at the middle of each bit - used to sample data
|
|
|
// internal registers
|
// internal registers
|
reg [7:0] rx_data;
|
reg [7:0] rx_data;
|
reg new_rx_data;
|
reg new_rx_data;
|
reg [1:0] in_sync;
|
reg [1:0] in_sync;
|
reg rx_busy;
|
reg rx_busy;
|
reg [3:0] count16;
|
reg [3:0] count16;
|
reg [3:0] bit_count;
|
reg [3:0] bit_count;
|
reg [7:0] data_buf;
|
reg [7:0] data_buf;
|
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
// module implementation
|
// module implementation
|
// input async input is sampled twice
|
// input async input is sampled twice
|
always @ (posedge clock or posedge reset)
|
always @ (posedge clock or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
in_sync <= 2'b11;
|
in_sync <= 2'b11;
|
else
|
else
|
in_sync <= {in_sync[0], ser_in};
|
in_sync <= {in_sync[0], ser_in};
|
end
|
end
|
|
|
// a counter to count 16 pulses of ce_16 to generate the ce_1 and ce_1_mid pulses.
|
// a counter to count 16 pulses of ce_16 to generate the ce_1 and ce_1_mid pulses.
|
// this counter is used to detect the start bit while the receiver is not receiving and
|
// this counter is used to detect the start bit while the receiver is not receiving and
|
// signs the sampling cycle during reception.
|
// signs the sampling cycle during reception.
|
always @ (posedge clock or posedge reset)
|
always @ (posedge clock or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
count16 <= 4'b0;
|
count16 <= 4'b0;
|
else if (ce_16)
|
else if (ce_16)
|
begin
|
begin
|
if (rx_busy | (in_sync[1] == 1'b0))
|
if (rx_busy | (in_sync[1] == 1'b0))
|
count16 <= count16 + 4'b1;
|
count16 <= count16 + 4'b1;
|
else
|
else
|
count16 <= 4'b0;
|
count16 <= 4'b0;
|
end
|
end
|
end
|
end
|
|
|
// ce_1 pulse indicating expected end of current bit
|
// ce_1 pulse indicating expected end of current bit
|
assign ce_1 = (count16 == 4'b1111) & ce_16;
|
assign ce_1 = (count16 == 4'b1111) & ce_16;
|
// ce_1_mid pulse indication the sampling clock cycle of the current data bit
|
// ce_1_mid pulse indication the sampling clock cycle of the current data bit
|
assign ce_1_mid = (count16 == 4'b0111) & ce_16;
|
assign ce_1_mid = (count16 == 4'b0111) & ce_16;
|
|
|
// receiving busy flag
|
// receiving busy flag
|
always @ (posedge clock or posedge reset)
|
always @ (posedge clock or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
rx_busy <= 1'b0;
|
rx_busy <= 1'b0;
|
else if (~rx_busy & ce_1_mid)
|
else if (~rx_busy & ce_1_mid)
|
rx_busy <= 1'b1;
|
rx_busy <= 1'b1;
|
else if (rx_busy & (bit_count == 4'h9) & ce_1)
|
else if (rx_busy & (bit_count == 4'h8) & ce_1_mid)
|
rx_busy <= 1'b0;
|
rx_busy <= 1'b0;
|
end
|
end
|
|
|
// bit counter
|
// bit counter
|
always @ (posedge clock or posedge reset)
|
always @ (posedge clock or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
bit_count <= 4'h0;
|
bit_count <= 4'h0;
|
else if (~rx_busy)
|
else if (~rx_busy)
|
bit_count <= 4'h0;
|
bit_count <= 4'h0;
|
else if (rx_busy & ce_1_mid)
|
else if (rx_busy & ce_1_mid)
|
bit_count <= bit_count + 4'h1;
|
bit_count <= bit_count + 4'h1;
|
end
|
end
|
|
|
// data buffer shift register
|
// data buffer shift register
|
always @ (posedge clock or posedge reset)
|
always @ (posedge clock or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
data_buf <= 8'h0;
|
data_buf <= 8'h0;
|
else if (rx_busy & ce_1_mid)
|
else if (rx_busy & ce_1_mid)
|
data_buf <= {in_sync[1], data_buf[7:1]};
|
data_buf <= {in_sync[1], data_buf[7:1]};
|
end
|
end
|
|
|
// data output and flag
|
// data output and flag
|
always @ (posedge clock or posedge reset)
|
always @ (posedge clock or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
rx_data <= 8'h0;
|
rx_data <= 8'h0;
|
new_rx_data <= 1'b0;
|
new_rx_data <= 1'b0;
|
end
|
end
|
else if (rx_busy & (bit_count == 4'h8) & ce_1)
|
else if (rx_busy & (bit_count == 4'h8) & ce_1)
|
begin
|
begin
|
rx_data <= data_buf;
|
rx_data <= data_buf;
|
new_rx_data <= 1'b1;
|
new_rx_data <= 1'b1;
|
end
|
end
|
else
|
else
|
new_rx_data <= 1'b0;
|
new_rx_data <= 1'b0;
|
end
|
end
|
|
|
endmodule
|
endmodule
|
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
// Th.. Th.. Th.. Thats all folks !!!
|
// Th.. Th.. Th.. Thats all folks !!!
|
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
|
|