[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[oc] [PATCH] UART receiver bugs
The attached patch fixes three 16550 UART bugs that, while independent,
all have a similar underlying cause. These problems are exhibited when
a microprocessor consumes a character from the UART's
receiver FIFO during the same clock cycle that a newly received
character is pushed into the FIFO.
The more characters received and the higher the baud rate of operation,
the more likely these conditions are to arise. (I stumbled across one
of these issues when performing high-speed file transfers over a serial
line and the others I found by inspection while dealing with the first
problem.)
1) When there is exactly one character in the receiver FIFO *and* it is
consumed by the CPU in the same cycle that an additional character is
received, the LSR (line status register) would forever afterwards
incorrectly indicate that no characters were in the UART's receive
FIFO. From the viewpoint of SW, it appeared as if the UART receiver
was simply shut off (even though characters *were* flowing into the
FIFO, eventually overflowing it.)
2) The condition bits (framing error, parity error, break) were always
cleared for an incoming character that arrived in the same cycle as
a processor read from the FIFO.
3) In the case of a full FIFO (16 characters in the receive FIFO), the
overflow status bit was incorrectly set when a character is added
in the same cycle that one is received.
I have CVS write access to OpenCores, so I can check this patch in if
it's deemed acceptable.
-Scott
Index: uart_rfifo.v
===================================================================
RCS file: /export/CVS/dave/lisa/hw/rcc100x/rtl/verilog/uart16550/uart_rfifo.v,v
retrieving revision 1.1
diff -c -r1.1 uart_rfifo.v
*** uart_rfifo.v 16 Apr 2003 17:50:50 -0000 1.1
--- uart_rfifo.v 10 Jun 2003 03:39:41 -0000
***************
*** 233,239 ****
count <= #1 count - 1'b1;
end
2'b11 : begin
- fifo[bottom] <= #1 0;
bottom <= #1 bottom + 1'b1;
top <= #1 top_plus_1;
fifo[top] <= #1 data_in[2:0];
--- 233,238 ----
***************
*** 251,257 ****
if(fifo_reset | reset_status)
overrun <= #1 1'b0;
else
! if(push & (count==fifo_depth))
overrun <= #1 1'b1;
end // always
--- 250,256 ----
if(fifo_reset | reset_status)
overrun <= #1 1'b0;
else
! if(push & ~pop & (count==fifo_depth))
overrun <= #1 1'b1;
end // always
Index: uart_regs.v
===================================================================
RCS file: /export/CVS/dave/lisa/hw/rcc100x/rtl/verilog/uart16550/uart_regs.v,v
retrieving revision 1.1
diff -c -r1.1 uart_regs.v
*** uart_regs.v 16 Apr 2003 17:50:50 -0000 1.1
--- uart_regs.v 10 Jun 2003 03:42:47 -0000
***************
*** 591,597 ****
always @(posedge clk or posedge wb_rst_i)
if (wb_rst_i) lsr0r <= #1 0;
! else lsr0r <= #1 (rf_count==1 && fifo_read || rx_reset) ? 0 : // deassert condition
lsr0r || (lsr0 && ~lsr0_d); // set on rise of lsr0 and keep asserted until deasserted
// lsr bit 1 (receiver overrun)
--- 591,597 ----
always @(posedge clk or posedge wb_rst_i)
if (wb_rst_i) lsr0r <= #1 0;
! else lsr0r <= #1 (rf_count==1 && rf_pop && !rf_push_pulse || rx_reset) ? 0 : // deassert condition
lsr0r || (lsr0 && ~lsr0_d); // set on rise of lsr0 and keep asserted until deasserted
// lsr bit 1 (receiver overrun)