Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support hardware flow control in UART #150

Open
jbush001 opened this issue Mar 4, 2018 · 3 comments
Open

Support hardware flow control in UART #150

jbush001 opened this issue Mar 4, 2018 · 3 comments

Comments

@jbush001
Copy link
Owner

jbush001 commented Mar 4, 2018

RTS/CTS are not connected. This doesn't seem to have been a problem so far, since most USB->Serial converts have a large buffer and USB is faster than serial. On the host->device direction, the software download cases read data in a tight loop, so it's not really possible to overrun the FIFO. However, there may be other test cases where this would become a problem.

Alternatively, it might be easier to pull in a proper UART implementation from somewhere else (which may b made easier by #38).

This is an FPGA test harness improvement and is not part of Nyuzi proper.

@jbush001 jbush001 changed the title UART doesn't have flow control Support hardware flow control in UART Mar 5, 2018
@jbush001
Copy link
Owner Author

RTS(RTR) is active low. This is fairly easy to implement, but would require a bit more work to test in simulation:

  1. In uart.sv, when reading STATUS_REG, tx_ready is used to indicate the sender can transmit. This should be && !rts
  2. The CTS output should be connected to rx_fifo_full.

@travisg
Copy link

travisg commented Mar 17, 2018

Also remember that bug that a particular vendor had where it would stop transmitting in the middle of the character if the receiver dropped CTS in the middle of it? IIRC the spec says that you sample the CTS of the other side before starting the character, but then commit to sending it.

@jbush001
Copy link
Owner Author

Haha... yes, I remember that all too well. :) This proposal actually doesn't control transmission, it just sets the status bit to indicate it's not ready. If software ignored that, it could start transmission anyway. But once it has started transmitting a character, it always finishes before checking for the next (controlled by the shift_count variable):

assign transmit_active = shift_count != 0;
assign uart_tx = transmit_active ? tx_shift[0] : 1'b1;
assign tx_ready = !transmit_active;
always_ff @(posedge clk, posedge reset)
begin
if (reset)
begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
next_edge_clocks <= '0;
shift_count <= '0;
tx_shift <= '0;
// End of automatics
end
else
begin
if (transmit_active)
begin
if (next_edge_clocks == 0)
begin
shift_count <= shift_count - 4'd1;
tx_shift <= {1'b0, tx_shift[9:1]};
next_edge_clocks <= clocks_per_bit;
end
else
next_edge_clocks <= next_edge_clocks - DIVISOR_WIDTH'(1);
end
else if (tx_en)
begin
shift_count <= 4'd10;
tx_shift <= {STOP_BIT, tx_char, START_BIT};
next_edge_clocks <= clocks_per_bit;
end
end
end

I'm not especially proud of this implementation; it's pretty quick and dirty. However, I've seen the RTL for some production chips and it's even worse. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants