From ebeadee1722a1aad5b3934c2c82af6e0b36cf190 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 11 Mar 2025 23:49:39 -0700 Subject: [PATCH] lss: Implement fractional baud rate generation for UART Signed-off-by: Alex Forencich --- example/Alveo/fpga/rtl/fpga_core.sv | 4 +-- example/Arty/fpga/rtl/fpga_core.sv | 4 +-- example/HTG940/fpga/rtl/fpga_core.sv | 4 +-- example/KC705/fpga/rtl/fpga_core.sv | 4 +-- example/KCU105/fpga/rtl/fpga_core.sv | 4 +-- example/VCU108/fpga/rtl/fpga_core.sv | 4 +-- example/VCU118/fpga/rtl/fpga_core.sv | 4 +-- example/ZCU102/fpga/rtl/fpga_core.sv | 4 +-- example/ZCU106/fpga/rtl/fpga_core.sv | 4 +-- example/ZCU111/fpga/rtl/fpga_core.sv | 4 +-- rtl/lss/taxi_uart.sv | 30 +++++++++-------- rtl/lss/taxi_uart_brg.sv | 33 +++++++++++++------ rtl/xfcp/taxi_xfcp_if_uart.sv | 19 ++++++----- tb/lss/taxi_uart/Makefile | 3 +- tb/lss/taxi_uart/test_taxi_uart.py | 3 +- tb/lss/taxi_uart/test_taxi_uart.sv | 7 ++-- tb/xfcp/taxi_xfcp_if_uart/Makefile | 1 + .../test_taxi_xfcp_if_uart.py | 3 +- .../test_taxi_xfcp_if_uart.sv | 4 ++- 19 files changed, 86 insertions(+), 57 deletions(-) diff --git a/example/Alveo/fpga/rtl/fpga_core.sv b/example/Alveo/fpga/rtl/fpga_core.sv index f9433f1..c65796b 100644 --- a/example/Alveo/fpga/rtl/fpga_core.sv +++ b/example/Alveo/fpga/rtl/fpga_core.sv @@ -78,7 +78,7 @@ for (genvar n = 0; n < UART_CNT; n = n + 1) begin : uart_ch taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart - uut ( + uart_inst ( .clk(clk_125mhz), .rst(rst_125mhz), @@ -109,7 +109,7 @@ for (genvar n = 0; n < UART_CNT; n = n + 1) begin : uart_ch /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); end diff --git a/example/Arty/fpga/rtl/fpga_core.sv b/example/Arty/fpga/rtl/fpga_core.sv index fe27baf..0f0a480 100644 --- a/example/Arty/fpga/rtl/fpga_core.sv +++ b/example/Arty/fpga/rtl/fpga_core.sv @@ -81,7 +81,7 @@ assign phy_reset_n = !rst; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk), .rst(rst), @@ -112,7 +112,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); taxi_axis_if #(.DATA_W(8), .ID_W(8)) axis_eth(); diff --git a/example/HTG940/fpga/rtl/fpga_core.sv b/example/HTG940/fpga/rtl/fpga_core.sv index 7cff99f..07f5223 100644 --- a/example/HTG940/fpga/rtl/fpga_core.sv +++ b/example/HTG940/fpga/rtl/fpga_core.sv @@ -71,7 +71,7 @@ assign uart_rst_n = 1'b1; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk), .rst(rst), @@ -102,7 +102,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // BASE-T PHY diff --git a/example/KC705/fpga/rtl/fpga_core.sv b/example/KC705/fpga/rtl/fpga_core.sv index 5a0080d..7e1d009 100644 --- a/example/KC705/fpga/rtl/fpga_core.sv +++ b/example/KC705/fpga/rtl/fpga_core.sv @@ -111,7 +111,7 @@ assign uart_rts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk), .rst(rst), @@ -142,7 +142,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // BASE-T PHY diff --git a/example/KCU105/fpga/rtl/fpga_core.sv b/example/KCU105/fpga/rtl/fpga_core.sv index 251a77e..506e161 100644 --- a/example/KCU105/fpga/rtl/fpga_core.sv +++ b/example/KCU105/fpga/rtl/fpga_core.sv @@ -109,7 +109,7 @@ assign uart_rts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk), .rst(rst), @@ -140,7 +140,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // BASE-T PHY diff --git a/example/VCU108/fpga/rtl/fpga_core.sv b/example/VCU108/fpga/rtl/fpga_core.sv index 39ac37e..182e343 100644 --- a/example/VCU108/fpga/rtl/fpga_core.sv +++ b/example/VCU108/fpga/rtl/fpga_core.sv @@ -91,7 +91,7 @@ assign uart_rts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk), .rst(rst), @@ -122,7 +122,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // BASE-T PHY diff --git a/example/VCU118/fpga/rtl/fpga_core.sv b/example/VCU118/fpga/rtl/fpga_core.sv index 8d3854d..1d627eb 100644 --- a/example/VCU118/fpga/rtl/fpga_core.sv +++ b/example/VCU118/fpga/rtl/fpga_core.sv @@ -111,7 +111,7 @@ assign uart_rts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk_125mhz), .rst(rst_125mhz), @@ -142,7 +142,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // BASE-T PHY diff --git a/example/ZCU102/fpga/rtl/fpga_core.sv b/example/ZCU102/fpga/rtl/fpga_core.sv index 3fefda1..578136c 100644 --- a/example/ZCU102/fpga/rtl/fpga_core.sv +++ b/example/ZCU102/fpga/rtl/fpga_core.sv @@ -114,7 +114,7 @@ assign uart_cts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk_125mhz), .rst(rst_125mhz), @@ -145,7 +145,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // SFP+ diff --git a/example/ZCU106/fpga/rtl/fpga_core.sv b/example/ZCU106/fpga/rtl/fpga_core.sv index 4158e2a..42d96a5 100644 --- a/example/ZCU106/fpga/rtl/fpga_core.sv +++ b/example/ZCU106/fpga/rtl/fpga_core.sv @@ -94,7 +94,7 @@ assign uart_cts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk_125mhz), .rst(rst_125mhz), @@ -125,7 +125,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // SFP+ diff --git a/example/ZCU111/fpga/rtl/fpga_core.sv b/example/ZCU111/fpga/rtl/fpga_core.sv index 76a340c..156ae54 100644 --- a/example/ZCU111/fpga/rtl/fpga_core.sv +++ b/example/ZCU111/fpga/rtl/fpga_core.sv @@ -72,7 +72,7 @@ assign uart_cts = 0; taxi_axis_if #(.DATA_W(8)) axis_uart(); taxi_uart -uut ( +uart_inst ( .clk(clk_125mhz), .rst(rst_125mhz), @@ -103,7 +103,7 @@ uut ( /* * Configuration */ - .prescale(16'(125000000/115200/8)) + .prescale(16'(125000000/115200)) ); // SFP+ diff --git a/rtl/lss/taxi_uart.sv b/rtl/lss/taxi_uart.sv index 106a098..e6372d2 100644 --- a/rtl/lss/taxi_uart.sv +++ b/rtl/lss/taxi_uart.sv @@ -15,45 +15,49 @@ Authors: /* * AXI4-Stream UART */ -module taxi_uart +module taxi_uart #( + parameter PRE_W = 16 +) ( - 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, /* * AXI4-Stream output (source) */ - taxi_axis_if.src m_axis_rx, + taxi_axis_if.src m_axis_rx, /* * UART interface */ - input wire logic rxd, - output wire logic txd, + input wire logic rxd, + output wire logic txd, /* * Status */ - output wire logic tx_busy, - output wire logic rx_busy, - output wire logic rx_overrun_error, - output wire logic rx_frame_error, + output wire logic tx_busy, + output wire logic rx_busy, + output wire logic rx_overrun_error, + output wire logic rx_frame_error, /* * Configuration */ - input wire logic [15:0] prescale + input wire logic [PRE_W-1:0] prescale ); wire baud_clk; -taxi_uart_brg +taxi_uart_brg #( + .PRE_W(PRE_W) +) uart_brg_inst ( .clk(clk), .rst(rst), diff --git a/rtl/lss/taxi_uart_brg.sv b/rtl/lss/taxi_uart_brg.sv index 07e3c8e..f002565 100644 --- a/rtl/lss/taxi_uart_brg.sv +++ b/rtl/lss/taxi_uart_brg.sv @@ -15,39 +15,52 @@ Authors: /* * AXI4-Stream UART baud rate generator */ -module taxi_uart_brg +module taxi_uart_brg #( + parameter PRE_W = 16 +) ( - input wire logic clk, - input wire logic rst, + input wire logic clk, + input wire logic rst, /* * Baud rate pulse out */ - output wire logic baud_clk, + output wire logic baud_clk, /* * Configuration */ - input wire logic [15:0] prescale + input wire logic [PRE_W-1:0] prescale ); -logic [15:0] prescale_reg = 0; +localparam FRAC_W = 3; +localparam INT_W = PRE_W - FRAC_W; + +logic [INT_W-1:0] prescale_int_reg = 0; +logic [FRAC_W-1:0] prescale_frac_reg = 0; +logic frac_ovf_reg = 1'b0; logic baud_clk_reg = 1'b0; assign baud_clk = baud_clk_reg; always_ff @(posedge clk) begin + frac_ovf_reg <= 1'b0; baud_clk_reg <= 1'b0; - if (prescale_reg != 0) begin - prescale_reg <= prescale_reg - 1; + if (frac_ovf_reg) begin + // delay extra cycle + frac_ovf_reg <= 1'b0; + end else if (prescale_int_reg != 0) begin + prescale_int_reg <= prescale_int_reg - 1; end else begin - prescale_reg <= prescale - 1; + prescale_int_reg <= prescale[FRAC_W +: INT_W] - 1; + {frac_ovf_reg, prescale_frac_reg} <= prescale_frac_reg + prescale[FRAC_W-1:0]; baud_clk_reg <= 1'b1; end if (rst) begin - prescale_reg <= 0; + prescale_int_reg <= 0; + prescale_frac_reg <= 0; baud_clk_reg <= 0; end end diff --git a/rtl/xfcp/taxi_xfcp_if_uart.sv b/rtl/xfcp/taxi_xfcp_if_uart.sv index afefc5d..1d31798 100644 --- a/rtl/xfcp/taxi_xfcp_if_uart.sv +++ b/rtl/xfcp/taxi_xfcp_if_uart.sv @@ -16,35 +16,38 @@ Authors: * XFCP Interface (UART) */ module taxi_xfcp_if_uart #( + parameter PRE_W = 16, parameter TX_FIFO_DEPTH = 512, parameter RX_FIFO_DEPTH = 512 ) ( - input wire logic clk, - input wire logic rst, + input wire logic clk, + input wire logic rst, /* * UART interface */ - input wire logic uart_rxd, - output wire logic uart_txd, + input wire logic uart_rxd, + output wire logic uart_txd, /* * XFCP downstream port */ - taxi_axis_if.src xfcp_dsp_ds, - taxi_axis_if.snk xfcp_dsp_us, + taxi_axis_if.src xfcp_dsp_ds, + taxi_axis_if.snk xfcp_dsp_us, /* * Configuration */ - input wire logic [15:0] prescale + input wire logic [PRE_W-1:0] prescale ); taxi_axis_if #(.DATA_W(8), .LAST_EN(0)) uart_tx(), uart_rx(); taxi_axis_if #(.DATA_W(8), .LAST_EN(1), .USER_EN(1), .USER_W(1)) fifo_tx(), fifo_rx(); -taxi_uart +taxi_uart #( + .PRE_W(PRE_W) +) uart_inst ( .clk(clk), .rst(rst), diff --git a/tb/lss/taxi_uart/Makefile b/tb/lss/taxi_uart/Makefile index 5eec62a..a3cb966 100644 --- a/tb/lss/taxi_uart/Makefile +++ b/tb/lss/taxi_uart/Makefile @@ -28,7 +28,8 @@ uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters -export PARAM_DATA_W ?= 8 +export PARAM_PRE_W := 16 +export PARAM_DATA_W := 8 ifeq ($(SIM), icarus) PLUSARGS += -fst diff --git a/tb/lss/taxi_uart/test_taxi_uart.py b/tb/lss/taxi_uart/test_taxi_uart.py index ca46b95..b255e46 100644 --- a/tb/lss/taxi_uart/test_taxi_uart.py +++ b/tb/lss/taxi_uart/test_taxi_uart.py @@ -39,7 +39,7 @@ class TB: self.axis_source = AxiStreamSource(AxiStreamBus.from_entity(dut.s_axis_tx), dut.clk, dut.rst) self.axis_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_rx), dut.clk, dut.rst) - dut.prescale.setimmediatevalue(int(1/8e-9/baud/8)) + dut.prescale.setimmediatevalue(int(1/8e-9/baud)) async def reset(self): self.dut.rst.setimmediatevalue(0) @@ -168,6 +168,7 @@ def test_taxi_uart(request): parameters = {} + parameters['PRE_W'] = 16 parameters['DATA_W'] = 8 extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} diff --git a/tb/lss/taxi_uart/test_taxi_uart.sv b/tb/lss/taxi_uart/test_taxi_uart.sv index b421131..5b8b454 100644 --- a/tb/lss/taxi_uart/test_taxi_uart.sv +++ b/tb/lss/taxi_uart/test_taxi_uart.sv @@ -18,6 +18,7 @@ Authors: module test_taxi_uart # ( /* verilator lint_off WIDTHTRUNC */ + parameter PRE_W = 16, parameter DATA_W = 8 /* verilator lint_on WIDTHTRUNC */ ) @@ -37,9 +38,11 @@ logic rx_busy; logic rx_overrun_error; logic rx_frame_error; -logic [15:0] prescale; +logic [PRE_W-1:0] prescale; -taxi_uart +taxi_uart #( + .PRE_W(PRE_W) +) uut ( .clk(clk), .rst(rst), diff --git a/tb/xfcp/taxi_xfcp_if_uart/Makefile b/tb/xfcp/taxi_xfcp_if_uart/Makefile index 8d20d39..1978004 100644 --- a/tb/xfcp/taxi_xfcp_if_uart/Makefile +++ b/tb/xfcp/taxi_xfcp_if_uart/Makefile @@ -28,6 +28,7 @@ uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters +export PARAM_PRE_W := 16 export PARAM_TX_FIFO_DEPTH := 512 export PARAM_RX_FIFO_DEPTH := 512 diff --git a/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.py b/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.py index 27a97e8..a29ecc4 100644 --- a/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.py +++ b/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.py @@ -50,7 +50,7 @@ class TB(object): self.dsp_source = AxiStreamSource(AxiStreamBus.from_entity(dut.xfcp_dsp_us), dut.clk, dut.rst) self.dsp_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.xfcp_dsp_ds), dut.clk, dut.rst) - dut.prescale.setimmediatevalue(int(1/8e-9/baud/8)) + dut.prescale.setimmediatevalue(int(1/8e-9/baud)) async def reset(self): self.dut.rst.setimmediatevalue(0) @@ -181,6 +181,7 @@ def test_taxi_xfcp_if_uart(request): parameters = {} + parameters['PRE_W'] = 16 parameters['TX_FIFO_DEPTH'] = 512 parameters['RX_FIFO_DEPTH'] = 512 diff --git a/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.sv b/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.sv index 6dadb70..36c2ba1 100644 --- a/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.sv +++ b/tb/xfcp/taxi_xfcp_if_uart/test_taxi_xfcp_if_uart.sv @@ -18,6 +18,7 @@ Authors: module test_taxi_xfcp_if_uart # ( /* verilator lint_off WIDTHTRUNC */ + parameter PRE_W = 16, parameter TX_FIFO_DEPTH = 512, parameter RX_FIFO_DEPTH = 512 /* verilator lint_on WIDTHTRUNC */ @@ -32,9 +33,10 @@ logic uart_txd; taxi_axis_if #(.DATA_W(8), .LAST_EN(1), .USER_EN(1), .USER_W(1)) xfcp_dsp_ds(), xfcp_dsp_us(); -logic [15:0] prescale; +logic [PRE_W-1:0] prescale; taxi_xfcp_if_uart #( + .PRE_W(PRE_W), .TX_FIFO_DEPTH(TX_FIFO_DEPTH), .RX_FIFO_DEPTH(RX_FIFO_DEPTH) )