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/core.sv | 2 - hdl/rs232.sv | 109 ++++++++++++++++++++++++++++++++++++---------------- hdl/top.sv | 122 +++++++++++++++++++++++++++++------------------------------ 3 files changed, 135 insertions(+), 98 deletions(-) (limited to 'hdl') diff --git a/hdl/core.sv b/hdl/core.sv index 6827b8e..587ffeb 100644 --- a/hdl/core.sv +++ b/hdl/core.sv @@ -3,8 +3,6 @@ `define DATA_BITS 12 module core - #( JTAG_INSTANCE = 1 - ) ( input bit clk , input bit reset 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 diff --git a/hdl/top.sv b/hdl/top.sv index ffe6656..6512185 100644 --- a/hdl/top.sv +++ b/hdl/top.sv @@ -7,10 +7,14 @@ module top , inout wire [10:1] gpioa , inout wire [28:13] gpiob , inout wire [40:31] gpioc - , output wire clock_out , output wire rs232_tx , input wire rs232_rx + , output wire rs232_rts + , input wire rs232_cts + + , output wire debug_tx + , output wire debug_rx , output bit ram_resetn , output bit ram_csn @@ -20,11 +24,14 @@ module top , inout bit [7:0] ram_data ); + assign debug_tx = rs232_tx; + assign debug_rx = rs232_rx; + bit internal_clock; bit internal_reset; pll - #( .MULTIPLY_BY(3) - , .DIVIDE_BY(5) + #( .MULTIPLY_BY(1) + , .DIVIDE_BY(1) ) fastpll ( .native_clk(clock) , .reset_n(resetn) @@ -32,51 +39,36 @@ module top , .reset(internal_reset) ); - //assign clock_out = internal_clock; - - bit rs232_tx_clock = 0; - bit [17:0] rs232_tx_div = 0; - always @(posedge internal_clock) begin + bit rs232_tx_clock; + bit rs232_tx_reset = 1; + always @(posedge rs232_tx_clock) begin if (internal_reset) begin - rs232_tx_clock = 0; - rs232_tx_div = 0; + rs232_tx_reset = 1; end else begin - if (++rs232_tx_div == 130) begin // (30MHz/2)/115200 - ++rs232_tx_clock; - rs232_tx_div = 0; - end + rs232_tx_reset = 0; end end - assign clock_out = rs232_tx_clock; - - bit rs232_rx_clock = 0; - bit [4:0] rs232_rx_div = 0; - always @(posedge internal_clock) begin - if (internal_reset) begin - rs232_rx_clock = 0; - rs232_rx_div = 0; - end else begin - if (++rs232_rx_div == 16) begin // (30MHz/2)/(115200*8) - ++rs232_rx_clock; - rs232_rx_div = 0; - end - end - end + bit rs232_rx_clock; + assign rs232_rx_clock = internal_clock; bit wire_tx_ready; bit wire_tx_valid; uart_byte_t wire_tx_data; - rs232_tx wiretx + rs232_tx + #( .PARITY(1) + , .STOP_BITS(2) + ) wiretx ( .clock(rs232_tx_clock) - , .reset(internal_reset) + , .reset(rs232_tx_reset) , .out_ready(wire_tx_ready) , .out_valid(wire_tx_valid) , .out_data(wire_tx_data) , .tx(rs232_tx) + , .cts(rs232_cts) ); bit rs232_tx_ready; @@ -88,6 +80,7 @@ module top ) fifotx ( .clock_in(internal_clock) , .clock_out(rs232_tx_clock) + , .reset(internal_reset || rs232_tx_reset) , .in_ready(rs232_tx_ready) , .in_valid(rs232_tx_valid) @@ -103,16 +96,20 @@ module top uart_byte_t wire_rx_data; rs232_rx - #( .OVERSAMPLE(7) + #( .PARITY(1) + , .OVERSAMPLE(433) ) wirerx ( .clock(rs232_rx_clock) , .reset(internal_reset) + , .clock_out(rs232_tx_clock) + , .in_ready(wire_rx_ready) , .in_valid(wire_rx_valid) , .in_data(wire_rx_data) , .rx(rs232_rx) + , .rts(rs232_rts) ); bit rs232_rx_ready; @@ -122,8 +119,9 @@ module top fifo #( .WIDTH_BITS($bits(uart_byte_t)) ) fiforx - ( .clock_in(rs232_clock) + ( .clock_in(rs232_rx_clock) , .clock_out(internal_clock) + , .reset(internal_reset) , .in_ready(wire_rx_ready) , .in_valid(wire_rx_valid) @@ -182,6 +180,7 @@ module top bit [7:0] ram_data_out; assign ram_data = ram_data_oe ? ram_data_out : 8'bZ; +/* alt_jtag_atlantic #( .INSTANCE_ID(0) , .LOG2_RXFIFO_DEPTH(10) @@ -199,6 +198,15 @@ module top , .t_dav(ram_rx_ready) , .t_ena(ram_rx_valid) ); +*/ + + assign ram_tx_ready = rs232_tx_ready; + assign rs232_tx_valid = ram_tx_valid; + assign rs232_tx_data = ram_tx_data; + + assign rs232_rx_ready = ram_rx_ready; + assign ram_rx_valid = rs232_rx_valid; + assign ram_rx_data = rs232_rx_data; echo_arbiter uart0arb ( .clock(internal_clock) @@ -445,9 +453,7 @@ module top bit rx_valid; uart_byte_t rx_data; - core - #( .JTAG_INSTANCE(1+i) - ) cpu + core cpu ( .clk(internal_clock) , .reset(internal_reset) @@ -507,33 +513,23 @@ module top , .led_link(local_led_link[i]) ); - if (i == `NUM_PDPS-1) begin - assign tx_ready = rs232_tx_ready; - assign rs232_tx_valid = tx_valid; - assign rs232_tx_data = tx_data; - - assign rs232_rx_ready = rx_ready; - assign rx_valid = rs232_rx_valid; - assign rx_data = rs232_rx_data; - end else begin - alt_jtag_atlantic - #( .INSTANCE_ID(1+i) - , .LOG2_RXFIFO_DEPTH(10) - , .LOG2_TXFIFO_DEPTH(10) - , .SLD_AUTO_INSTANCE_INDEX("NO") - ) uart - ( .clk(internal_clock) - , .rst_n(!internal_reset) - - , .r_dat(tx_data) - , .r_val(tx_valid) - , .r_ena(tx_ready) - - , .t_dat(rx_data) - , .t_dav(rx_ready) - , .t_ena(rx_valid) - ); - end + alt_jtag_atlantic + #( .INSTANCE_ID(i) + , .LOG2_RXFIFO_DEPTH(10) + , .LOG2_TXFIFO_DEPTH(10) + , .SLD_AUTO_INSTANCE_INDEX("NO") + ) uart + ( .clk(internal_clock) + , .rst_n(!internal_reset) + + , .r_dat(tx_data) + , .r_val(tx_valid) + , .r_ena(tx_ready) + + , .t_dat(rx_data) + , .t_dav(rx_ready) + , .t_ena(rx_valid) + ); end -- cgit v1.2.3