[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)