From 38c5ae5b60eae9562b97da42f47af3861847f8e5 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 8 May 2022 15:51:35 -0700 Subject: *Proper* serial port for memory downloads. 115200 8O2 RS232 with CRTRTS. --- hdl/rs232.sv | 109 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 33 deletions(-) (limited to 'hdl/rs232.sv') diff --git a/hdl/rs232.sv b/hdl/rs232.sv index 31beb1e..ef53f12 100644 --- a/hdl/rs232.sv +++ b/hdl/rs232.sv @@ -1,6 +1,9 @@ `include "defs.svh" module rs232_tx + #( PARITY = 0 + , STOP_BITS = 2 + ) ( input bit clock , input bit reset @@ -9,6 +12,7 @@ module rs232_tx , input uart_byte_t out_data , output bit tx + , input bit cts ); bit hold_valid; @@ -18,40 +22,45 @@ module rs232_tx (* syn_encoding = "one-hot" *) enum int unsigned { START , DATA - , PARITY - , STOP1 - , STOP2 + , PARITY_BIT + , STOP } state; - bit [$clog2(`UART_BYTE_BITS):0] data_bits; + bit [$clog2($bits(uart_byte_t)):0] data_bits; + bit [$clog2(STOP_BITS):0] stop_bits; always @(posedge clock, posedge reset) begin if (reset) begin out_ready = 0; tx = 1; hold_valid = 0; - parity = 0; + parity = PARITY; state = state.first; data_bits = 0; + stop_bits = 0; end else begin if (out_ready && out_valid) begin hold_valid = 1; hold = out_data; - parity = 0; + parity = PARITY; state = state.first; data_bits = 0; + stop_bits = 0; end if (hold_valid) begin case (state) START: begin - tx = 0; - state = state.next; + if (!cts) begin + tx = 0; + state = state.next; + end end DATA: begin - tx = hold[data_bits]; + tx = hold[0]; + hold = hold >> 1; parity = parity ^ tx; if (data_bits == `UART_BYTE_BITS-1) state = state.next; @@ -59,20 +68,19 @@ module rs232_tx ++data_bits; end - PARITY: begin + PARITY_BIT: begin tx = parity; state = state.next; end - STOP1: begin - tx = 1; - state = state.next; - end - - STOP2: begin - hold_valid = 0; + STOP: begin tx = 1; - state = state.next; + if (stop_bits == STOP_BITS-1) begin + hold_valid = 0; + state = state.next; + end else begin + ++stop_bits; + end end endcase @@ -87,69 +95,94 @@ module rs232_tx endmodule module rs232_rx - #( OVERSAMPLE = 0 + #( PARITY = 0 + , OVERSAMPLE = 0 ) ( input bit clock , input bit reset + , output bit clock_out + , input bit in_ready , output bit in_valid , output uart_byte_t in_data , input bit rx + , output bit rts ); (* syn_encoding = "one-hot" *) enum int unsigned { START + , ALIGN , DATA - , PARITY + , PARITY_BIT , STOP + , REALSTOP } state; uart_byte_t buffer; bit [$clog2(`UART_BYTE_BITS):0] data_bits; bit parity; - bit [$clog2(OVERSAMPLE+1):0] sample; + bit [$clog2(OVERSAMPLE+1)+2:0] sample; + bit [$clog2(OVERSAMPLE+1):0] clock_counter; always @(posedge clock, posedge reset) begin if (reset) begin + clock_out = 0; in_valid = 0; + rts = 1; state = state.first; buffer = 0; data_bits = 0; - parity = 0; + parity = PARITY; sample = 0; + clock_counter = 0; end else begin automatic bit ok = 0; if (in_ready && in_valid) in_valid = 0; - if (state == state.first) begin + if (state == state.first || state == state.last) begin + sample = 0; ok = 1; end else begin ++sample; - if (sample == OVERSAMPLE+1) begin + if (sample > OVERSAMPLE) begin sample = 0; ok = 1; end end + ++clock_counter; + if (clock_counter > OVERSAMPLE) begin + clock_out = 1; + clock_counter = 0; + end else begin + clock_out = 0; + end + if (ok) begin case (state) START: begin if (rx == 0) begin state = state.next; + if (OVERSAMPLE == 0) + state = state.next; + sample = (OVERSAMPLE+1) / 2; buffer = 0; data_bits = 0; - parity = 0; + parity = PARITY; end end + ALIGN: state = state.next; + DATA: begin - buffer[data_bits] = rx; + buffer = buffer >> 1; + buffer[`UART_BYTE_BITS-1] = rx; parity = parity ^ rx; if (data_bits == `UART_BYTE_BITS-1) state = state.next; @@ -157,24 +190,34 @@ module rs232_rx ++data_bits; end - PARITY: begin + PARITY_BIT: begin parity = parity ^ rx; - if (parity == 0) - state = state.next; - else - state = state.first; + state = state.next; end STOP: begin - if (!in_valid && rx == 1) begin + if (!in_valid && rx == 1 && parity == 0) begin in_valid = 1; in_data = buffer; end - state = state.next; + if (rx == 1 && parity == 0) begin + clock_counter = (OVERSAMPLE+1)/2; + end + if (rx == 1) + state = state.first; + else + state = state.next; + end + + REALSTOP: begin + if (rx == 1) + state = state.first; end endcase end + + rts = !(state == state.first && !in_valid); end end -- cgit v1.2.3