diff --git a/rtl/lss/taxi_uart.f b/rtl/lss/taxi_uart.f index cffa74e..012469e 100644 --- a/rtl/lss/taxi_uart.f +++ b/rtl/lss/taxi_uart.f @@ -1,4 +1,5 @@ taxi_uart.sv taxi_uart_rx.sv taxi_uart_tx.sv +taxi_uart_brg.sv ../axis/taxi_axis_if.sv diff --git a/rtl/lss/taxi_uart.sv b/rtl/lss/taxi_uart.sv index 32541d0..106a098 100644 --- a/rtl/lss/taxi_uart.sv +++ b/rtl/lss/taxi_uart.sv @@ -51,6 +51,24 @@ module taxi_uart ); +wire baud_clk; + +taxi_uart_brg +uart_brg_inst ( + .clk(clk), + .rst(rst), + + /* + * Baud rate pulse out + */ + .baud_clk(baud_clk), + + /* + * Configuration + */ + .prescale(prescale) +); + taxi_uart_tx uart_tx_inst ( .clk(clk), @@ -72,9 +90,9 @@ uart_tx_inst ( .busy(tx_busy), /* - * Configuration + * Baud rate pulse in */ - .prescale(prescale) + .baud_clk(baud_clk) ); taxi_uart_rx @@ -100,9 +118,9 @@ uart_rx_inst ( .frame_error(rx_frame_error), /* - * Configuration + * Baud rate pulse in */ - .prescale(prescale) + .baud_clk(baud_clk) ); endmodule diff --git a/rtl/lss/taxi_uart_brg.sv b/rtl/lss/taxi_uart_brg.sv new file mode 100644 index 0000000..07e3c8e --- /dev/null +++ b/rtl/lss/taxi_uart_brg.sv @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: CERN-OHL-S-2.0 +/* + +Copyright (c) 2025 FPGA Ninja, LLC + +Authors: +- Alex Forencich + +*/ + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4-Stream UART baud rate generator + */ +module taxi_uart_brg +( + input wire logic clk, + input wire logic rst, + + /* + * Baud rate pulse out + */ + output wire logic baud_clk, + + /* + * Configuration + */ + input wire logic [15:0] prescale +); + +logic [15:0] prescale_reg = 0; +logic baud_clk_reg = 1'b0; + +assign baud_clk = baud_clk_reg; + +always_ff @(posedge clk) begin + baud_clk_reg <= 1'b0; + + if (prescale_reg != 0) begin + prescale_reg <= prescale_reg - 1; + end else begin + prescale_reg <= prescale - 1; + baud_clk_reg <= 1'b1; + end + + if (rst) begin + prescale_reg <= 0; + baud_clk_reg <= 0; + end +end + +endmodule + +`resetall diff --git a/rtl/lss/taxi_uart_rx.sv b/rtl/lss/taxi_uart_rx.sv index 50af224..a5d2679 100644 --- a/rtl/lss/taxi_uart_rx.sv +++ b/rtl/lss/taxi_uart_rx.sv @@ -17,111 +17,120 @@ Authors: */ module taxi_uart_rx ( - input wire logic clk, - input wire logic rst, + input wire logic clk, + input wire logic rst, /* * AXI4-Stream output (source) */ - taxi_axis_if.src m_axis_rx, + taxi_axis_if.src m_axis_rx, /* * UART interface */ - input wire logic rxd, + input wire logic rxd, /* * Status */ - output wire logic busy, - output wire logic overrun_error, - output wire logic frame_error, + output wire logic busy, + output wire logic overrun_error, + output wire logic frame_error, /* - * Configuration + * Baud rate pulse in */ - input wire logic [15:0] prescale + input wire logic baud_clk ); localparam DATA_W = m_axis_rx.DATA_W; logic [DATA_W-1:0] m_axis_tdata_reg = 0; -logic m_axis_tvalid_reg = 0; +logic m_axis_tvalid_reg = 1'b0; -logic rxd_reg = 1; +logic rxd_reg = 1'b1; -logic busy_reg = 0; -logic overrun_error_reg = 0; -logic frame_error_reg = 0; +logic overrun_error_reg = 1'b0; +logic frame_error_reg = 1'b0; logic [DATA_W-1:0] data_reg = 0; -logic [18:0] prescale_reg = 0; -logic [3:0] bit_cnt_reg = 0; +logic [2:0] baud_cnt_reg = 0; +logic run_reg = 1'b0; +logic start_reg = 1'b0; +logic stop_reg = 1'b0; assign m_axis_rx.tdata = m_axis_tdata_reg; assign m_axis_rx.tkeep = 1'b1; assign m_axis_rx.tstrb = m_axis_rx.tkeep; assign m_axis_rx.tvalid = m_axis_tvalid_reg; assign m_axis_rx.tlast = 1'b1; +assign m_axis_rx.tid = '0; +assign m_axis_rx.tdest = '0; +assign m_axis_rx.tuser = '0; -assign busy = busy_reg; +assign busy = run_reg; assign overrun_error = overrun_error_reg; assign frame_error = frame_error_reg; always_ff @(posedge clk) begin rxd_reg <= rxd; - overrun_error_reg <= 0; - frame_error_reg <= 0; + overrun_error_reg <= 1'b0; + frame_error_reg <= 1'b0; if (m_axis_rx.tvalid && m_axis_rx.tready) begin - m_axis_tvalid_reg <= 0; + m_axis_tvalid_reg <= 1'b0; end - if (prescale_reg > 0) begin - prescale_reg <= prescale_reg - 1; - end else if (bit_cnt_reg > 0) begin - if (bit_cnt_reg > DATA_W+1) begin - if (!rxd_reg) begin - bit_cnt_reg <= bit_cnt_reg - 1; - prescale_reg <= {prescale, 3'd0}-1; - end else begin - bit_cnt_reg <= 0; - prescale_reg <= 0; - end - end else if (bit_cnt_reg > 1) begin - bit_cnt_reg <= bit_cnt_reg - 1; - prescale_reg <= {prescale, 3'd0}-1; - data_reg <= {rxd_reg, data_reg[DATA_W-1:1]}; - end else if (bit_cnt_reg == 1) begin - bit_cnt_reg <= bit_cnt_reg - 1; + if (!baud_clk) begin + // wait + end else if (baud_cnt_reg != 0) begin + baud_cnt_reg <= baud_cnt_reg - 1; + end else if (run_reg) begin + start_reg <= 1'b0; + if (start_reg) begin + // wait bit period for start bit + baud_cnt_reg <= '1; if (rxd_reg) begin - m_axis_tdata_reg <= data_reg; - m_axis_tvalid_reg <= 1; - overrun_error_reg <= m_axis_tvalid_reg; + // start bit high, clear run bit + run_reg <= 1'b0; + frame_error_reg <= 1'b1; + end + end else begin + {data_reg, stop_reg} <= {rxd_reg, data_reg}; + if (stop_reg) begin + run_reg <= 1'b0; + if (rxd_reg) begin + // stop bit high, transfer data + m_axis_tdata_reg <= data_reg; + m_axis_tvalid_reg <= 1'b1; + overrun_error_reg <= m_axis_tvalid_reg; + end else begin + // stop bit low + frame_error_reg <= 1'b1; + end end else begin - frame_error_reg <= 1; + baud_cnt_reg <= '1; end end end else begin - busy_reg <= 0; + data_reg <= {1'b1, {DATA_W-1{1'b0}}}; // marker bit + start_reg <= 1'b1; + stop_reg <= 1'b0; if (!rxd_reg) begin - prescale_reg <= {prescale, 2'd0}-2; - bit_cnt_reg <= DATA_W+2; - data_reg <= 0; - busy_reg <= 1; + // falling edge of start bit + // wait half bit period + baud_cnt_reg <= 3'b011; + run_reg <= 1'b1; end end if (rst) begin - m_axis_tdata_reg <= 0; - m_axis_tvalid_reg <= 0; - rxd_reg <= 1; - prescale_reg <= 0; - bit_cnt_reg <= 0; - busy_reg <= 0; - overrun_error_reg <= 0; - frame_error_reg <= 0; + m_axis_tvalid_reg <= 1'b0; + rxd_reg <= 1'b1; + run_reg <= 1'b0; + overrun_error_reg <= 1'b0; + frame_error_reg <= 1'b0; end end diff --git a/rtl/lss/taxi_uart_tx.sv b/rtl/lss/taxi_uart_tx.sv index 7361b67..96528f8 100644 --- a/rtl/lss/taxi_uart_tx.sv +++ b/rtl/lss/taxi_uart_tx.sv @@ -17,40 +17,40 @@ Authors: */ module taxi_uart_tx ( - input wire logic clk, - input wire logic rst, + input wire logic clk, + input wire logic rst, /* * AXI4-Stream input (sink) */ - taxi_axis_if.snk s_axis_tx, + taxi_axis_if.snk s_axis_tx, /* * UART interface */ - output wire logic txd, + output wire logic txd, /* * Status */ - output wire logic busy, + output wire logic busy, /* - * Configuration + * Baud rate pulse in */ - input wire logic [15:0] prescale + input wire logic baud_clk ); localparam DATA_W = s_axis_tx.DATA_W; -logic s_axis_tready_reg = 0; +logic s_axis_tready_reg = 1'b0; -logic txd_reg = 1; +logic txd_reg = 1'b1; -logic busy_reg = 0; +logic busy_reg = 1'b0; logic [DATA_W:0] data_reg = 0; -logic [18:0] prescale_reg = 0; +logic [2:0] baud_cnt_reg = 0; logic [3:0] bit_cnt_reg = 0; assign s_axis_tx.tready = s_axis_tready_reg; @@ -60,39 +60,35 @@ assign txd = txd_reg; assign busy = busy_reg; always_ff @(posedge clk) begin - if (prescale_reg > 0) begin - s_axis_tready_reg <= 0; - prescale_reg <= prescale_reg - 1; + s_axis_tready_reg <= 1'b0; + + if (!baud_clk) begin + // wait + end else if (baud_cnt_reg != 0) begin + baud_cnt_reg <= baud_cnt_reg - 1; end else if (bit_cnt_reg == 0) begin - s_axis_tready_reg <= 1; - busy_reg <= 0; + busy_reg <= 1'b0; if (s_axis_tx.tvalid) begin - s_axis_tready_reg <= !s_axis_tready_reg; - prescale_reg <= {prescale, 3'd0}-1; + s_axis_tready_reg <= 1'b1; + baud_cnt_reg <= '1; bit_cnt_reg <= DATA_W+1; data_reg <= {1'b1, s_axis_tx.tdata}; - txd_reg <= 0; - busy_reg <= 1; + txd_reg <= 1'b0; + busy_reg <= 1'b1; end end else begin - if (bit_cnt_reg > 1) begin - bit_cnt_reg <= bit_cnt_reg - 1; - prescale_reg <= {prescale, 3'd0}-1; - {data_reg, txd_reg} <= {1'b0, data_reg}; - end else if (bit_cnt_reg == 1) begin - bit_cnt_reg <= bit_cnt_reg - 1; - prescale_reg <= {prescale, 3'd0}-1; - txd_reg <= 1; - end + {data_reg, txd_reg} <= {1'b0, data_reg}; + baud_cnt_reg <= '1; + bit_cnt_reg <= bit_cnt_reg - 1; end if (rst) begin - s_axis_tready_reg <= 0; - txd_reg <= 1; - prescale_reg <= 0; + s_axis_tready_reg <= 1'b0; + txd_reg <= 1'b1; + baud_cnt_reg <= 0; bit_cnt_reg <= 0; - busy_reg <= 0; + busy_reg <= 1'b0; end end