Update uart tx interrupts

- watermark now only fires when tx dips under the watermark
- overflow changed to tx empty

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/uart/data/uart.hjson b/hw/ip/uart/data/uart.hjson
index 928c34b..8742651 100644
--- a/hw/ip/uart/data/uart.hjson
+++ b/hw/ip/uart/data/uart.hjson
@@ -16,8 +16,8 @@
       desc: "raised if the transmit FIFO is past the high-water mark."}
     { name: "rx_watermark"
       desc: "raised if the receive FIFO is past the high-water mark."}
-    { name: "tx_overflow"
-      desc: "raised if the transmit FIFO has overflowed."}
+    { name: "tx_empty"
+      desc: "raised if the transmit FIFO has emptied."}
     { name: "rx_overflow"
       desc: "raised if the receive FIFO has overflowed."}
     { name: "rx_frame_err"
diff --git a/hw/ip/uart/doc/_index.md b/hw/ip/uart/doc/_index.md
index 0c31632..bf93637 100644
--- a/hw/ip/uart/doc/_index.md
+++ b/hw/ip/uart/doc/_index.md
@@ -19,7 +19,7 @@
 - 32 x 8b RX buffer
 - 32 x 8b TX buffer
 - Programmable baud rate
-- Interrupt for overflow, frame error, parity error, break error, receive
+- Interrupt for transmit empty, receive overflow, frame error, parity error, break error, receive
   timeout
 
 ## Description
@@ -95,8 +95,9 @@
 If TX is not enabled, written DATA into FIFO will be stacked up and sent out
 when TX is enabled.
 
-If the FIFO is full when data is written to {{< regref "WDATA" >}} that data will be discarded
-and a TX FIFO overflow interrupt raised.
+When the FIFO becomes empty as part of transmittion, a TX FIFO empty interrupt will be raised.
+This is separate from the TX FIFO water mark interrupt.
+
 
 ### Reception
 
@@ -201,15 +202,16 @@
 and unexpected event interrupts.
 
 #### tx_watermark / rx_watermark
-If the TX or RX FIFO level becomes greater than or equal to their respective
-high-water mark levels (configurable via {{< regref "FIFO_CTRL.RXILVL" >}} and
-{{< regref "FIFO_CTRL.TXILVL" >}}), interrupts `tx_watermark` or `rx_watermark` are raised to
-inform SW.
+If the TX FIFO level becomes smaller than the TX water mark level (configurable via {{< regref "FIFO_CTRL.RXILVL" >}} and {{< regref "FIFO_CTRL.TXILVL" >}}), the `tx_watermark` interrupt is raised to inform SW.
+If the RX FIFO level becomes greater than or equal to RX water mark level (configurable via {{< regref "FIFO_CTRL.RXILVL" >}} and {{< regref "FIFO_CTRL.TXILVL" >}}), the rx_watermark` interrupt is raised to inform SW.
 
-#### tx_overflow / rx_overflow
-If either FIFO receives an additional write request when its FIFO is full,
-the interrupt `tx_overflow` or `rx_overflow` is asserted and the character
-is dropped.
+#### tx_empty
+If TX FIFO becomes empty as part of transmit, the interrupt `tx_empty` is asserted.
+The transmitted contents may be garbage at this point as old FIFO contents will likely be transmitted.
+
+#### rx_overflow
+If RX FIFO receives an additional write request when its FIFO is full,
+the interrupt `rx_overflow` is asserted and the character is dropped.
 
 #### rx_break_err
 The `rx_break_err` interrupt is triggered if a break condition has
diff --git a/hw/ip/uart/dv/env/seq_lib/uart_intr_vseq.sv b/hw/ip/uart/dv/env/seq_lib/uart_intr_vseq.sv
index 5a3a4fc..d48b5b8 100644
--- a/hw/ip/uart/dv/env/seq_lib/uart_intr_vseq.sv
+++ b/hw/ip/uart/dv/env/seq_lib/uart_intr_vseq.sv
@@ -72,7 +72,9 @@
         check_one_intr(.uart_intr(uart_intr), .exp(en_rx));
       end
 
-      TxOverflow: begin
+      TxEmpty: begin
+        // TODO: The following test needs to be updated, since the interrupt definition
+        // has been updated.
         // when tx is enabled, one extra item is in the data path, total is UART_FIFO_DEPTH + 1
         if (en_tx) begin
           tx_fifo_max_size = UART_FIFO_DEPTH + 1;
diff --git a/hw/ip/uart/dv/env/uart_env_pkg.sv b/hw/ip/uart/dv/env/uart_env_pkg.sv
index 304f550..56229e0 100644
--- a/hw/ip/uart/dv/env/uart_env_pkg.sv
+++ b/hw/ip/uart/dv/env/uart_env_pkg.sv
@@ -26,7 +26,7 @@
   typedef enum int {
     TxWatermark = 0,
     RxWatermark = 1,
-    TxOverflow  = 2,
+    TxEmpty     = 2,
     RxOverflow  = 3,
     RxFrameErr  = 4,
     RxBreakErr  = 5,
diff --git a/hw/ip/uart/dv/env/uart_scoreboard.sv b/hw/ip/uart/dv/env/uart_scoreboard.sv
index 65519c7..c0927ff 100644
--- a/hw/ip/uart/dv/env/uart_scoreboard.sv
+++ b/hw/ip/uart/dv/env/uart_scoreboard.sv
@@ -69,8 +69,13 @@
       if (tx_q.size > 0) tx_processing_item_q.push_back(tx_q.pop_front());
       `uvm_info(`gfn, $sformatf("After drop one item, new tx_q size: %0d", tx_q.size), UVM_HIGH)
       compare(act_item, exp_item, "TX");
+      // after an item is sent, check to see if size dipped below watermark
+      predict_tx_watermark_intr();
 
-      if (tx_q.size() == 0 && tx_processing_item_q.size() == 0) process_objections(1'b0);
+      if (tx_q.size() == 0 && tx_processing_item_q.size() == 0) begin
+        intr_exp[TxEmpty] = 1;
+        process_objections(1'b0);
+      end
     end
   endtask
 
@@ -111,9 +116,7 @@
 
   virtual function void predict_tx_watermark_intr(uint tx_q_size = tx_q.size, bit just_cleared = 0);
     uint watermark = get_watermark_bytes_by_level(ral.fifo_ctrl.txilvl.get_mirrored_value());
-    intr_exp[TxWatermark] |= (tx_q_size >= watermark);
-    // cover the interrupt sticky behavior
-    if (cfg.en_cov) cov.sticky_intr_cov["TxWatermark"].sample(just_cleared & intr_exp[TxWatermark]);
+    intr_exp[TxWatermark] |= (tx_q_size < watermark);
   endfunction
 
   virtual function void predict_rx_watermark_intr(uint rx_q_size = rx_q.size, bit just_cleared = 0);
@@ -188,7 +191,6 @@
             tx_q.push_back(tx_item);
             `uvm_info(`gfn, $sformatf("After push one item, tx_q size: %0d", tx_q.size), UVM_HIGH)
           end else begin
-            intr_exp[TxOverflow] = 1;
             `uvm_info(`gfn, $sformatf(
                 "Drop tx item: %0h, tx_q size: %0d, uart_tx_clk_pulses: %0d",
                 csr.get_mirrored_value(), tx_q.size(), uart_tx_clk_pulses), UVM_MEDIUM)
@@ -335,9 +337,7 @@
             // occur simultaneously
             cfg.clk_rst_vif.wait_clks(1);
             intr_exp &= ~intr_wdata;
-            // recalculate tx/rx watermark, will be set again if fifo size >= watermark
-            predict_tx_watermark_intr(.just_cleared(pre_intr[TxWatermark] &
-                                                    intr_wdata[TxWatermark]));
+            // recalculate rx watermark, will be set again if fifo size >= watermark
             predict_rx_watermark_intr(.just_cleared(pre_intr[RxWatermark] &
                                                     intr_wdata[RxWatermark]));
           end join_none
@@ -354,7 +354,7 @@
               cov.intr_pins_cg.sample(intr, cfg.intr_vif.pins[intr]);
             end
             // don't check it when it's in ignored period
-            if (intr inside {TxWatermark, TxOverflow}) begin // TX interrupts
+            if (intr inside {TxWatermark, TxEmpty}) begin // TX interrupts
               if (is_in_ignored_period(UartTx)) continue;
             end else begin // RX interrupts
               // RxTimeout, RxBreakErr is checked in seq
diff --git a/hw/ip/uart/dv/tb/tb.sv b/hw/ip/uart/dv/tb/tb.sv
index 8a51380..c4a61a9 100644
--- a/hw/ip/uart/dv/tb/tb.sv
+++ b/hw/ip/uart/dv/tb/tb.sv
@@ -18,7 +18,7 @@
   wire devmode;
   wire intr_tx_watermark;
   wire intr_rx_watermark;
-  wire intr_tx_overflow;
+  wire intr_tx_empty;
   wire intr_rx_overflow;
   wire intr_rx_frame_err;
   wire intr_rx_break_err;
@@ -47,7 +47,7 @@
 
     .intr_tx_watermark_o  (intr_tx_watermark ),
     .intr_rx_watermark_o  (intr_rx_watermark ),
-    .intr_tx_overflow_o   (intr_tx_overflow  ),
+    .intr_tx_empty_o      (intr_tx_empty  ),
     .intr_rx_overflow_o   (intr_rx_overflow  ),
     .intr_rx_frame_err_o  (intr_rx_frame_err ),
     .intr_rx_break_err_o  (intr_rx_break_err ),
@@ -57,7 +57,7 @@
 
   assign interrupts[TxWatermark] = intr_tx_watermark;
   assign interrupts[RxWatermark] = intr_rx_watermark;
-  assign interrupts[TxOverflow]  = intr_tx_overflow;
+  assign interrupts[TxEmpty]     = intr_tx_empty;
   assign interrupts[RxOverflow]  = intr_rx_overflow;
   assign interrupts[RxFrameErr]  = intr_rx_frame_err;
   assign interrupts[RxBreakErr]  = intr_rx_break_err;
diff --git a/hw/ip/uart/rtl/uart.sv b/hw/ip/uart/rtl/uart.sv
index 1235af6..fb61002 100644
--- a/hw/ip/uart/rtl/uart.sv
+++ b/hw/ip/uart/rtl/uart.sv
@@ -20,7 +20,7 @@
   // Interrupts
   output logic    intr_tx_watermark_o ,
   output logic    intr_rx_watermark_o ,
-  output logic    intr_tx_overflow_o  ,
+  output logic    intr_tx_empty_o  ,
   output logic    intr_rx_overflow_o  ,
   output logic    intr_rx_frame_err_o ,
   output logic    intr_rx_break_err_o ,
@@ -55,7 +55,7 @@
 
     .intr_tx_watermark_o,
     .intr_rx_watermark_o,
-    .intr_tx_overflow_o,
+    .intr_tx_empty_o,
     .intr_rx_overflow_o,
     .intr_rx_frame_err_o,
     .intr_rx_break_err_o,
@@ -73,7 +73,7 @@
   // Assert Known for interrupts
   `ASSERT_KNOWN(txWatermarkKnown, intr_tx_watermark_o, clk_i, !rst_ni)
   `ASSERT_KNOWN(rxWatermarkKnown, intr_rx_watermark_o, clk_i, !rst_ni)
-  `ASSERT_KNOWN(txOverflowKnown, intr_tx_overflow_o, clk_i, !rst_ni)
+  `ASSERT_KNOWN(txEmptyKnown, intr_tx_empty_o, clk_i, !rst_ni)
   `ASSERT_KNOWN(rxOverflowKnown, intr_rx_overflow_o, clk_i, !rst_ni)
   `ASSERT_KNOWN(rxFrameErrKnown, intr_rx_frame_err_o, clk_i, !rst_ni)
   `ASSERT_KNOWN(rxBreakErrKnown, intr_rx_break_err_o, clk_i, !rst_ni)
diff --git a/hw/ip/uart/rtl/uart_core.sv b/hw/ip/uart/rtl/uart_core.sv
index 8885f89..c76aefe 100644
--- a/hw/ip/uart/rtl/uart_core.sv
+++ b/hw/ip/uart/rtl/uart_core.sv
@@ -17,7 +17,7 @@
 
   output logic           intr_tx_watermark_o,
   output logic           intr_rx_watermark_o,
-  output logic           intr_tx_overflow_o,
+  output logic           intr_tx_empty_o,
   output logic           intr_rx_overflow_o,
   output logic           intr_rx_frame_err_o,
   output logic           intr_rx_break_err_o,
@@ -53,8 +53,10 @@
   logic           break_err;
   logic   [4:0]   allzero_cnt_d, allzero_cnt_q;
   logic           allzero_err, not_allzero_char;
-  logic           event_tx_watermark, event_rx_watermark, event_tx_overflow, event_rx_overflow;
+  logic           event_tx_watermark, event_rx_watermark, event_tx_empty, event_rx_overflow;
   logic           event_rx_frame_err, event_rx_break_err, event_rx_timeout, event_rx_parity_err;
+  logic           tx_watermark_d, tx_watermark_prev_q;
+  logic           tx_empty_d, tx_empty_prev_q;
 
   assign tx_enable        = reg2hw.ctrl.tx.q;
   assign rx_enable        = reg2hw.ctrl.rx.q;
@@ -293,13 +295,21 @@
 
   always_comb begin
     unique case(uart_fifo_txilvl)
-      2'h0:    event_tx_watermark = (tx_fifo_depth >= 6'd1);
-      2'h1:    event_tx_watermark = (tx_fifo_depth >= 6'd4);
-      2'h2:    event_tx_watermark = (tx_fifo_depth >= 6'd8);
-      default: event_tx_watermark = (tx_fifo_depth >= 6'd16);
+      2'h0:    tx_watermark_d = (tx_fifo_depth < 6'd1);
+      2'h1:    tx_watermark_d = (tx_fifo_depth < 6'd4);
+      2'h2:    tx_watermark_d = (tx_fifo_depth < 6'd8);
+      default: tx_watermark_d = (tx_fifo_depth < 6'd16);
     endcase
   end
 
+  assign event_tx_watermark = tx_watermark_d & ~tx_watermark_prev_q;
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      tx_watermark_prev_q   <= 1'd1;
+    end else begin
+      tx_watermark_prev_q   <= tx_watermark_d;
+    end
+  end
 
   always_comb begin
     unique case(uart_fifo_rxilvl)
@@ -339,19 +349,25 @@
 
   assign event_rx_timeout = (rx_timeout_count_q == uart_rxto_val) & uart_rxto_en;
 
+  assign tx_empty_d = tx_fifo_depth == 6'h0;
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       rx_timeout_count_q   <= 24'd0;
       rx_fifo_depth_prev_q <= 6'd0;
+      tx_empty_prev_q      <= 1'd0;
     end else begin
       rx_timeout_count_q    <= rx_timeout_count_d;
       rx_fifo_depth_prev_q  <= rx_fifo_depth;
+      tx_empty_prev_q       <= tx_empty_d;
     end
   end
 
   assign event_rx_overflow  = rx_fifo_wvalid & ~rx_fifo_wready;
-  assign event_tx_overflow  = reg2hw.wdata.qe & ~tx_fifo_wready;
   assign event_rx_break_err = break_err & (break_st_q == BRK_CHK);
+  // this event is really a duplicate of uart_fifo_txilvl=0
+  // however, it is helpful to have both a non-1 entry watermark and an empty indication
+  assign event_tx_empty     = tx_empty_d & ~tx_empty_prev_q;
+
 
   // instantiate interrupt hardware primitives
 
@@ -377,15 +393,15 @@
     .intr_o                 (intr_rx_watermark_o)
   );
 
-  prim_intr_hw #(.Width(1)) intr_hw_tx_overflow (
-    .event_intr_i           (event_tx_overflow),
-    .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tx_overflow.q),
-    .reg2hw_intr_test_q_i   (reg2hw.intr_test.tx_overflow.q),
-    .reg2hw_intr_test_qe_i  (reg2hw.intr_test.tx_overflow.qe),
-    .reg2hw_intr_state_q_i  (reg2hw.intr_state.tx_overflow.q),
-    .hw2reg_intr_state_de_o (hw2reg.intr_state.tx_overflow.de),
-    .hw2reg_intr_state_d_o  (hw2reg.intr_state.tx_overflow.d),
-    .intr_o                 (intr_tx_overflow_o)
+  prim_intr_hw #(.Width(1)) intr_hw_tx_empty (
+    .event_intr_i           (event_tx_empty),
+    .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tx_empty.q),
+    .reg2hw_intr_test_q_i   (reg2hw.intr_test.tx_empty.q),
+    .reg2hw_intr_test_qe_i  (reg2hw.intr_test.tx_empty.qe),
+    .reg2hw_intr_state_q_i  (reg2hw.intr_state.tx_empty.q),
+    .hw2reg_intr_state_de_o (hw2reg.intr_state.tx_empty.de),
+    .hw2reg_intr_state_d_o  (hw2reg.intr_state.tx_empty.d),
+    .intr_o                 (intr_tx_empty_o)
   );
 
   prim_intr_hw #(.Width(1)) intr_hw_rx_overflow (
diff --git a/hw/ip/uart/rtl/uart_reg_pkg.sv b/hw/ip/uart/rtl/uart_reg_pkg.sv
index 45a372a..6c5c530 100644
--- a/hw/ip/uart/rtl/uart_reg_pkg.sv
+++ b/hw/ip/uart/rtl/uart_reg_pkg.sv
@@ -18,7 +18,7 @@
     } rx_watermark;
     struct packed {
       logic        q;
-    } tx_overflow;
+    } tx_empty;
     struct packed {
       logic        q;
     } rx_overflow;
@@ -45,7 +45,7 @@
     } rx_watermark;
     struct packed {
       logic        q;
-    } tx_overflow;
+    } tx_empty;
     struct packed {
       logic        q;
     } rx_overflow;
@@ -75,7 +75,7 @@
     struct packed {
       logic        q;
       logic        qe;
-    } tx_overflow;
+    } tx_empty;
     struct packed {
       logic        q;
       logic        qe;
@@ -215,7 +215,7 @@
     struct packed {
       logic        d;
       logic        de;
-    } tx_overflow;
+    } tx_empty;
     struct packed {
       logic        d;
       logic        de;
diff --git a/hw/ip/uart/rtl/uart_reg_top.sv b/hw/ip/uart/rtl/uart_reg_top.sv
index fc8edd3..6876701 100644
--- a/hw/ip/uart/rtl/uart_reg_top.sv
+++ b/hw/ip/uart/rtl/uart_reg_top.sv
@@ -75,9 +75,9 @@
   logic intr_state_rx_watermark_qs;
   logic intr_state_rx_watermark_wd;
   logic intr_state_rx_watermark_we;
-  logic intr_state_tx_overflow_qs;
-  logic intr_state_tx_overflow_wd;
-  logic intr_state_tx_overflow_we;
+  logic intr_state_tx_empty_qs;
+  logic intr_state_tx_empty_wd;
+  logic intr_state_tx_empty_we;
   logic intr_state_rx_overflow_qs;
   logic intr_state_rx_overflow_wd;
   logic intr_state_rx_overflow_we;
@@ -99,9 +99,9 @@
   logic intr_enable_rx_watermark_qs;
   logic intr_enable_rx_watermark_wd;
   logic intr_enable_rx_watermark_we;
-  logic intr_enable_tx_overflow_qs;
-  logic intr_enable_tx_overflow_wd;
-  logic intr_enable_tx_overflow_we;
+  logic intr_enable_tx_empty_qs;
+  logic intr_enable_tx_empty_wd;
+  logic intr_enable_tx_empty_we;
   logic intr_enable_rx_overflow_qs;
   logic intr_enable_rx_overflow_wd;
   logic intr_enable_rx_overflow_we;
@@ -121,8 +121,8 @@
   logic intr_test_tx_watermark_we;
   logic intr_test_rx_watermark_wd;
   logic intr_test_rx_watermark_we;
-  logic intr_test_tx_overflow_wd;
-  logic intr_test_tx_overflow_we;
+  logic intr_test_tx_empty_wd;
+  logic intr_test_tx_empty_we;
   logic intr_test_rx_overflow_wd;
   logic intr_test_rx_overflow_we;
   logic intr_test_rx_frame_err_wd;
@@ -260,29 +260,29 @@
   );
 
 
-  //   F[tx_overflow]: 2:2
+  //   F[tx_empty]: 2:2
   prim_subreg #(
     .DW      (1),
     .SWACCESS("W1C"),
     .RESVAL  (1'h0)
-  ) u_intr_state_tx_overflow (
+  ) u_intr_state_tx_empty (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
     // from register interface
-    .we     (intr_state_tx_overflow_we),
-    .wd     (intr_state_tx_overflow_wd),
+    .we     (intr_state_tx_empty_we),
+    .wd     (intr_state_tx_empty_wd),
 
     // from internal hardware
-    .de     (hw2reg.intr_state.tx_overflow.de),
-    .d      (hw2reg.intr_state.tx_overflow.d ),
+    .de     (hw2reg.intr_state.tx_empty.de),
+    .d      (hw2reg.intr_state.tx_empty.d ),
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.intr_state.tx_overflow.q ),
+    .q      (reg2hw.intr_state.tx_empty.q ),
 
     // to register interface (read)
-    .qs     (intr_state_tx_overflow_qs)
+    .qs     (intr_state_tx_empty_qs)
   );
 
 
@@ -470,18 +470,18 @@
   );
 
 
-  //   F[tx_overflow]: 2:2
+  //   F[tx_empty]: 2:2
   prim_subreg #(
     .DW      (1),
     .SWACCESS("RW"),
     .RESVAL  (1'h0)
-  ) u_intr_enable_tx_overflow (
+  ) u_intr_enable_tx_empty (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
     // from register interface
-    .we     (intr_enable_tx_overflow_we),
-    .wd     (intr_enable_tx_overflow_wd),
+    .we     (intr_enable_tx_empty_we),
+    .wd     (intr_enable_tx_empty_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -489,10 +489,10 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.intr_enable.tx_overflow.q ),
+    .q      (reg2hw.intr_enable.tx_empty.q ),
 
     // to register interface (read)
-    .qs     (intr_enable_tx_overflow_qs)
+    .qs     (intr_enable_tx_empty_qs)
   );
 
 
@@ -658,17 +658,17 @@
   );
 
 
-  //   F[tx_overflow]: 2:2
+  //   F[tx_empty]: 2:2
   prim_subreg_ext #(
     .DW    (1)
-  ) u_intr_test_tx_overflow (
+  ) u_intr_test_tx_empty (
     .re     (1'b0),
-    .we     (intr_test_tx_overflow_we),
-    .wd     (intr_test_tx_overflow_wd),
+    .we     (intr_test_tx_empty_we),
+    .wd     (intr_test_tx_empty_wd),
     .d      ('0),
     .qre    (),
-    .qe     (reg2hw.intr_test.tx_overflow.qe),
-    .q      (reg2hw.intr_test.tx_overflow.q ),
+    .qe     (reg2hw.intr_test.tx_empty.qe),
+    .q      (reg2hw.intr_test.tx_empty.q ),
     .qs     ()
   );
 
@@ -1422,8 +1422,8 @@
   assign intr_state_rx_watermark_we = addr_hit[0] & reg_we & ~wr_err;
   assign intr_state_rx_watermark_wd = reg_wdata[1];
 
-  assign intr_state_tx_overflow_we = addr_hit[0] & reg_we & ~wr_err;
-  assign intr_state_tx_overflow_wd = reg_wdata[2];
+  assign intr_state_tx_empty_we = addr_hit[0] & reg_we & ~wr_err;
+  assign intr_state_tx_empty_wd = reg_wdata[2];
 
   assign intr_state_rx_overflow_we = addr_hit[0] & reg_we & ~wr_err;
   assign intr_state_rx_overflow_wd = reg_wdata[3];
@@ -1446,8 +1446,8 @@
   assign intr_enable_rx_watermark_we = addr_hit[1] & reg_we & ~wr_err;
   assign intr_enable_rx_watermark_wd = reg_wdata[1];
 
-  assign intr_enable_tx_overflow_we = addr_hit[1] & reg_we & ~wr_err;
-  assign intr_enable_tx_overflow_wd = reg_wdata[2];
+  assign intr_enable_tx_empty_we = addr_hit[1] & reg_we & ~wr_err;
+  assign intr_enable_tx_empty_wd = reg_wdata[2];
 
   assign intr_enable_rx_overflow_we = addr_hit[1] & reg_we & ~wr_err;
   assign intr_enable_rx_overflow_wd = reg_wdata[3];
@@ -1470,8 +1470,8 @@
   assign intr_test_rx_watermark_we = addr_hit[2] & reg_we & ~wr_err;
   assign intr_test_rx_watermark_wd = reg_wdata[1];
 
-  assign intr_test_tx_overflow_we = addr_hit[2] & reg_we & ~wr_err;
-  assign intr_test_tx_overflow_wd = reg_wdata[2];
+  assign intr_test_tx_empty_we = addr_hit[2] & reg_we & ~wr_err;
+  assign intr_test_tx_empty_wd = reg_wdata[2];
 
   assign intr_test_rx_overflow_we = addr_hit[2] & reg_we & ~wr_err;
   assign intr_test_rx_overflow_wd = reg_wdata[3];
@@ -1569,7 +1569,7 @@
       addr_hit[0]: begin
         reg_rdata_next[0] = intr_state_tx_watermark_qs;
         reg_rdata_next[1] = intr_state_rx_watermark_qs;
-        reg_rdata_next[2] = intr_state_tx_overflow_qs;
+        reg_rdata_next[2] = intr_state_tx_empty_qs;
         reg_rdata_next[3] = intr_state_rx_overflow_qs;
         reg_rdata_next[4] = intr_state_rx_frame_err_qs;
         reg_rdata_next[5] = intr_state_rx_break_err_qs;
@@ -1580,7 +1580,7 @@
       addr_hit[1]: begin
         reg_rdata_next[0] = intr_enable_tx_watermark_qs;
         reg_rdata_next[1] = intr_enable_rx_watermark_qs;
-        reg_rdata_next[2] = intr_enable_tx_overflow_qs;
+        reg_rdata_next[2] = intr_enable_tx_empty_qs;
         reg_rdata_next[3] = intr_enable_rx_overflow_qs;
         reg_rdata_next[4] = intr_enable_rx_frame_err_qs;
         reg_rdata_next[5] = intr_enable_rx_break_err_qs;
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 04ee9b7..0d4913b 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -93,7 +93,7 @@
           type: interrupt
         }
         {
-          name: tx_overflow
+          name: tx_empty
           width: 1
           type: interrupt
         }
@@ -1007,7 +1007,7 @@
       type: interrupt
     }
     {
-      name: uart_tx_overflow
+      name: uart_tx_empty
       width: 1
       type: interrupt
     }
diff --git a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_main_bind.sv b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_main_bind.sv
index 9b89826..e69de29 100644
--- a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_main_bind.sv
+++ b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_main_bind.sv
@@ -1,102 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-//
-// xbar_main_bind module generated by `tlgen.py` tool for assertions
-module xbar_main_bind;
-
-  // Host interfaces
-  bind xbar_main tlul_assert #(.EndpointType("Device")) tlul_assert_host_corei (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_corei_i),
-    .d2h    (tl_corei_o)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Device")) tlul_assert_host_cored (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_cored_i),
-    .d2h    (tl_cored_o)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Device")) tlul_assert_host_dm_sba (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_dm_sba_i),
-    .d2h    (tl_dm_sba_o)
-  );
-
-  // Device interfaces
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_rom (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_rom_o),
-    .d2h    (tl_rom_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_debug_mem (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_debug_mem_o),
-    .d2h    (tl_debug_mem_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_ram_main (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_ram_main_o),
-    .d2h    (tl_ram_main_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_eflash (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_eflash_o),
-    .d2h    (tl_eflash_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_peri (
-    .clk_i  (clk_fixed_i),
-    .rst_ni (rst_fixed_ni),
-    .h2d    (tl_peri_o),
-    .d2h    (tl_peri_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_flash_ctrl (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_flash_ctrl_o),
-    .d2h    (tl_flash_ctrl_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_hmac (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_hmac_o),
-    .d2h    (tl_hmac_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_aes (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_aes_o),
-    .d2h    (tl_aes_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_rv_plic (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_rv_plic_o),
-    .d2h    (tl_rv_plic_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_pinmux (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_fixed_ni),
-    .h2d    (tl_pinmux_o),
-    .d2h    (tl_pinmux_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_alert_handler (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_alert_handler_o),
-    .d2h    (tl_alert_handler_i)
-  );
-  bind xbar_main tlul_assert #(.EndpointType("Host")) tlul_assert_device_nmi_gen (
-    .clk_i  (clk_main_i),
-    .rst_ni (rst_main_ni),
-    .h2d    (tl_nmi_gen_o),
-    .d2h    (tl_nmi_gen_i)
-  );
-
-endmodule
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 640968c..73d19d4 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -143,7 +143,7 @@
   // Interrupt source list
   logic intr_uart_tx_watermark;
   logic intr_uart_rx_watermark;
-  logic intr_uart_tx_overflow;
+  logic intr_uart_tx_empty;
   logic intr_uart_rx_overflow;
   logic intr_uart_rx_frame_err;
   logic intr_uart_rx_break_err;
@@ -439,7 +439,7 @@
       // Interrupt
       .intr_tx_watermark_o  (intr_uart_tx_watermark),
       .intr_rx_watermark_o  (intr_uart_rx_watermark),
-      .intr_tx_overflow_o   (intr_uart_tx_overflow),
+      .intr_tx_empty_o      (intr_uart_tx_empty),
       .intr_rx_overflow_o   (intr_uart_rx_overflow),
       .intr_rx_frame_err_o  (intr_uart_rx_frame_err),
       .intr_rx_break_err_o  (intr_uart_rx_break_err),
@@ -649,7 +649,7 @@
       intr_uart_rx_break_err,
       intr_uart_rx_frame_err,
       intr_uart_rx_overflow,
-      intr_uart_tx_overflow,
+      intr_uart_tx_empty,
       intr_uart_rx_watermark,
       intr_uart_tx_watermark,
       intr_gpio_gpio