Skip to content

Commit

Permalink
Fix off-by-one UART bitrate counter value that will make the RX sampling
Browse files Browse the repository at this point in the history
and TX sending drift. The impact gets higher as the baudrate increases and
the bitrate counter value gets smaller.
  • Loading branch information
jthornblad committed Dec 16, 2024
1 parent 66888a3 commit 19beb41
Showing 1 changed file with 73 additions and 56 deletions.
129 changes: 73 additions & 56 deletions hw/application_fpga/core/uart/rtl/uart_core.v
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ module uart_core (
rxd_byte_reg <= 8'h0;
rxd_bit_ctr_reg <= 4'h0;
rxd_bitrate_ctr_reg <= 16'h0;
rxd_syn_reg <= 0;
rxd_syn_reg <= 1'b0;
erx_ctrl_reg <= ERX_IDLE;

txd_reg <= 1'b1;
Expand Down Expand Up @@ -267,11 +267,11 @@ module uart_core (
// serial interface.
//----------------------------------------------------------------
always @* begin : rxd_bitrate_ctr
rxd_bitrate_ctr_new = 16'h0;
rxd_bitrate_ctr_new = 16'h1;
rxd_bitrate_ctr_we = 1'h0;

if (rxd_bitrate_ctr_rst) begin
rxd_bitrate_ctr_new = 16'h0;
rxd_bitrate_ctr_new = 16'h1;
rxd_bitrate_ctr_we = 1'b1;
end

Expand All @@ -282,7 +282,6 @@ module uart_core (
end // rxd_bitrate_ctr



//----------------------------------------------------------------
// txd_bit_ctr
//
Expand Down Expand Up @@ -312,17 +311,17 @@ module uart_core (
// serial interface.
//----------------------------------------------------------------
always @* begin : txd_bitrate_ctr
txd_bitrate_ctr_new = 16'h0;
txd_bitrate_ctr_we = 0;
txd_bitrate_ctr_new = 16'h1;
txd_bitrate_ctr_we = 1'h0;

if (txd_bitrate_ctr_rst) begin
txd_bitrate_ctr_new = 16'h0;
txd_bitrate_ctr_we = 1;
txd_bitrate_ctr_new = 16'h1;
txd_bitrate_ctr_we = 1'h1;
end

else if (txd_bitrate_ctr_inc) begin
txd_bitrate_ctr_new = txd_bitrate_ctr_reg + 1'h1;
txd_bitrate_ctr_we = 1;
txd_bitrate_ctr_we = 1'h1;
end
end // txd_bitrate_ctr

Expand Down Expand Up @@ -350,25 +349,32 @@ module uart_core (
ERX_IDLE: begin
if (!rxd_reg) begin
// Possible start bit detected.
rxd_bitrate_ctr_rst = 1;
rxd_bitrate_ctr_inc = 1;
erx_ctrl_new = ERX_START;
erx_ctrl_we = 1;
end
end


ERX_START: begin
rxd_bitrate_ctr_inc = 1;
if (rxd_reg) begin
// Just a glitch.
rxd_bitrate_ctr_rst = 1;
erx_ctrl_new = ERX_IDLE;
erx_ctrl_we = 1;
end

else begin
if (rxd_bitrate_ctr_reg == half_bit_rate) begin
// start bit assumed. We start sampling data.
rxd_bit_ctr_rst = 1;
if (rxd_bitrate_ctr_reg < half_bit_rate) begin
rxd_bitrate_ctr_inc = 1;
end

else begin
// Start bit assumed.
// We are in the middle of the start bit.
// Start sampling data.
rxd_bitrate_ctr_rst = 1;
rxd_bit_ctr_rst = 1;
erx_ctrl_new = ERX_BITS;
erx_ctrl_we = 1;
end
Expand All @@ -382,24 +388,32 @@ module uart_core (
end

else begin
rxd_byte_we = 1;
rxd_bit_ctr_inc = 1;
rxd_bitrate_ctr_rst = 1;
if (rxd_bit_ctr_reg == (data_bits - 1)) begin
erx_ctrl_new = ERX_STOP;
if (rxd_bit_ctr_reg < data_bits) begin
rxd_bitrate_ctr_rst = 1;
rxd_bit_ctr_inc = 1;
rxd_byte_we = 1; // We are in the middle of a data bit, make a sample
end

else begin
erx_ctrl_new = ERX_STOP; // We are now in the middle of the stop bit
erx_ctrl_we = 1;
end
end
end


ERX_STOP: begin
rxd_bitrate_ctr_inc = 1;
if (rxd_bitrate_ctr_reg == bit_rate * stop_bits) begin
rxd_syn_new = 1;
rxd_syn_we = 1;
erx_ctrl_new = ERX_SYN;
erx_ctrl_we = 1;
// stop_bits can be removed from line below if we are only using one stop bit
if (rxd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
rxd_bitrate_ctr_inc = 1;
end

else begin
rxd_bitrate_ctr_rst = 1;
rxd_syn_new = 1;
rxd_syn_we = 1;
erx_ctrl_new = ERX_SYN;
erx_ctrl_we = 1;
end
end

Expand Down Expand Up @@ -442,39 +456,35 @@ module uart_core (

case (etx_ctrl_reg)
ETX_IDLE: begin
txd_new = 1;
txd_we = 1;
txd_new = 1;
txd_we = 1;
txd_bit_ctr_rst = 1;
if (txd_syn) begin
txd_new = 0;
txd_we = 1;
txd_byte_new = txd_data;
txd_byte_we = 1;
txd_ready_new = 0;
txd_ready_we = 1;
txd_bitrate_ctr_rst = 1;
etx_ctrl_new = ETX_ACK;
etx_ctrl_new = ETX_START;
etx_ctrl_we = 1;
end
end


ETX_ACK: begin
if (!txd_syn) begin
txd_new = 0;
txd_we = 1;
etx_ctrl_new = ETX_START;
etx_ctrl_we = 1;
end
end


ETX_START: begin
if (txd_bitrate_ctr_reg == bit_rate) begin
txd_bit_ctr_rst = 1;
etx_ctrl_new = ETX_BITS;
etx_ctrl_we = 1;
if (txd_bitrate_ctr_reg < bit_rate) begin
txd_bitrate_ctr_inc = 1;
end

else begin
txd_bitrate_ctr_inc = 1;
txd_bitrate_ctr_rst = 1;
txd_bit_ctr_inc = 1;
txd_new = txd_byte_reg[txd_bit_ctr_reg[2 : 0]];
txd_we = 1;
etx_ctrl_new = ETX_BITS;
etx_ctrl_we = 1;
end
end

Expand All @@ -486,29 +496,36 @@ module uart_core (

else begin
txd_bitrate_ctr_rst = 1;
if (txd_bit_ctr_reg == data_bits) begin

if (txd_bit_ctr_reg < data_bits) begin
txd_bit_ctr_inc = 1;
txd_new = txd_byte_reg[txd_bit_ctr_reg[2 : 0]];
txd_we = 1;
end

else begin
txd_new = 1;
txd_we = 1;
etx_ctrl_new = ETX_STOP;
etx_ctrl_we = 1;
end

else begin
txd_new = txd_byte_reg[txd_bit_ctr_reg[2 : 0]];
txd_we = 1;
txd_bit_ctr_inc = 1;
end
end
end


ETX_STOP: begin
txd_bitrate_ctr_inc = 1;
if (txd_bitrate_ctr_reg == bit_rate * stop_bits) begin
txd_ready_new = 1;
txd_ready_we = 1;
etx_ctrl_new = ETX_IDLE;
etx_ctrl_we = 1;
// stop_bits can be removed from line below if we are only using one stop bit
if (txd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
txd_bitrate_ctr_inc = 1;
end

else begin
txd_bitrate_ctr_rst = 1;
txd_bit_ctr_rst = 1;
txd_ready_new = 1;
txd_ready_we = 1;
etx_ctrl_new = ETX_IDLE;
etx_ctrl_we = 1;
end
end

Expand Down

0 comments on commit 19beb41

Please sign in to comment.