formal mux proof
diff --git a/verilog/rtl/scan_controller/Makefile b/verilog/rtl/scan_controller/Makefile
new file mode 100644
index 0000000..408fcf6
--- /dev/null
+++ b/verilog/rtl/scan_controller/Makefile
@@ -0,0 +1,2 @@
+prove_mux:
+	sby -f scan_mux.sby
diff --git a/verilog/rtl/scan_controller/properties.v b/verilog/rtl/scan_controller/properties.v
new file mode 100644
index 0000000..c104f6a
--- /dev/null
+++ b/verilog/rtl/scan_controller/properties.v
@@ -0,0 +1,23 @@
+always @(*) begin
+    if(driver_sel == 2'b00) begin // external driver
+        assert(outputs[0]    == scan_data_in);
+        assert(scan_clk      == ext_scan_clk);
+        assert(scan_data_out == inputs[1]);
+        assert(scan_select   == inputs[2]);
+        assert(scan_latch_en == inputs[3]);
+    end else
+    if(driver_sel == 2'b10) begin // external driver
+        assert(la_scan_data_out == scan_data_in);
+        assert(scan_clk      == la_scan_clk);
+        assert(scan_data_out == la_scan_data_in);
+        assert(scan_select   == la_scan_select);
+        assert(scan_latch_en == la_scan_latch_en);
+    end else
+    if(driver_sel == 2'b01) begin // internal driver
+        assert(int_scan_data_out == scan_data_out);
+        assert(scan_clk      == int_scan_clk);
+        assert(scan_data_in  == int_scan_data_in);
+        assert(scan_select   == int_scan_select);
+        assert(scan_latch_en == int_scan_latch_en);
+    end
+end
diff --git a/verilog/rtl/scan_controller/scan_controller.v b/verilog/rtl/scan_controller/scan_controller.v
index 60b366b..d9f8f96 100644
--- a/verilog/rtl/scan_controller/scan_controller.v
+++ b/verilog/rtl/scan_controller/scan_controller.v
@@ -11,14 +11,14 @@
     output wire ready,                  // debug output that goes high once per refresh
     output wire slow_clk,               // debug clock divider output
 
-    output wire scan_clk,               // scan chain interface for the tiny designs
+    output wire scan_clk,               // scan chain interface for the tiny designs, from perspective of this module
     output wire scan_data_out,          // see diagrams below for how the scan chain works
     input  wire scan_data_in,           // will be driven by internal driver, external gpio pins, or Caravel logic analyser
     output wire scan_select,            // external scan chain driver muxes with ins/outs, eg microcontroller outside the ASIC
     output wire scan_latch_en,
 
     input  wire la_scan_clk,            // logic analyser scan chain driver, driven by firmware running on Caravel's VexRisc 
-    input  wire la_scan_data_in,
+    input  wire la_scan_data_in,        // signal names from perspective of this module
     output wire la_scan_data_out,
     input  wire la_scan_select,
     input  wire la_scan_latch_en,
@@ -40,18 +40,25 @@
     localparam LATCH = 4;
                     
     // scan chain muxing
-    wire ext_scan_clk;
-    wire ext_scan_data_out;
-    wire ext_scan_data_in;
-    wire ext_scan_select;
-    wire ext_scan_latch_en;
+    // signal names in perspective of this module
+    wire ext_scan_clk       = inputs[0];
+    wire ext_scan_data_in   = inputs[1];
+    wire ext_scan_data_out  = scan_data_in;
+    wire ext_scan_select    = inputs[2];   
+    wire ext_scan_latch_en  = inputs[3];
 
     assign scan_clk         = driver_sel == 2'b00 ? ext_scan_clk      : driver_sel == 2'b01 ? int_scan_clk      : la_scan_clk;
-    assign scan_data_out    = driver_sel == 2'b00 ? ext_scan_data_out : driver_sel == 2'b01 ? int_scan_data_out : la_scan_data_out;
+    assign scan_data_out    = driver_sel == 2'b00 ? ext_scan_data_in  : driver_sel == 2'b01 ? int_scan_data_out : la_scan_data_in;
     assign scan_select      = driver_sel == 2'b00 ? ext_scan_select   : driver_sel == 2'b01 ? int_scan_select   : la_scan_select;
     assign scan_latch_en    = driver_sel == 2'b00 ? ext_scan_latch_en : driver_sel == 2'b01 ? int_scan_latch_en : la_scan_latch_en;
 
-    wire   int_scan_data_in = scan_data_in;
+    wire int_scan_data_in   = scan_data_in;
+    wire la_scan_data_out   = scan_data_in;
+    assign outputs          = driver_sel == 2'b01 ? outputs_r : {7'b0, ext_scan_data_out};
+
+    `ifdef FORMAL
+        `include "properties.v"
+    `endif
 
     // reg
     reg [8:0] current_design;
@@ -65,7 +72,6 @@
     reg [7:0] output_buf;
 
     // wires
-    assign outputs = outputs_r;
     wire [8:0] active_select_rev = NUM_DESIGNS - 1 - active_select;
     assign ready = state == START;
     wire int_scan_latch_en = state == LATCH;
@@ -114,7 +120,7 @@
 
     */
 
-    // FSM
+    // FSM, only run it if driver_sel is set to internal
     always @(posedge clk) begin
         if(reset) begin
             current_design <= 0;
@@ -124,7 +130,7 @@
             scan_clk_r <= 0;
             num_io <= 0;
             output_buf <= 0;
-        end else begin
+        end else if (driver_sel == 2'b01) begin
             case(state)
                 START: begin
                     state <= LOAD;
diff --git a/verilog/rtl/scan_controller/scan_mux.sby b/verilog/rtl/scan_controller/scan_mux.sby
new file mode 100644
index 0000000..57fe264
--- /dev/null
+++ b/verilog/rtl/scan_controller/scan_mux.sby
@@ -0,0 +1,13 @@
+[options]
+mode prove
+
+[engines]
+smtbmc
+
+[script]
+read -formal -DMPRJ_IO_PADS=38 scan_controller.v
+prep -top scan_controller
+
+[files]
+scan_controller.v
+properties.v