add sim tests
diff --git a/verilog/rtl/0001-fix-make-targets.patch b/verilog/rtl/0001-fix-make-targets.patch
new file mode 100644
index 0000000..95cd1b8
--- /dev/null
+++ b/verilog/rtl/0001-fix-make-targets.patch
@@ -0,0 +1,162 @@
+From f9f5d6804186bab5b9f44c65bd7986cec5c77840 Mon Sep 17 00:00:00 2001
+From: roman3017 <rbacik@hotmail.com>
+Date: Tue, 20 Dec 2022 20:19:40 -0800
+Subject: [PATCH] fix make targets
+
+make PROJ=soc lint
+make PROJ=soc sim
+make PROJ=soc wave
+make PROJ=soc clean all
+make PROJ=soc prog
+---
+ examples/TinyFPGA-BX/OSS_CAD_Suite/Makefile | 6 +++---
+ examples/common/hdl/sim_tasks.v             | 2 +-
+ examples/common/hdl/usb_rx_tasks.v          | 8 +++++---
+ examples/common/hdl/usb_tasks.v             | 2 +-
+ usb_cdc/sie.v                               | 4 ++--
+ 5 files changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/examples/TinyFPGA-BX/OSS_CAD_Suite/Makefile b/examples/TinyFPGA-BX/OSS_CAD_Suite/Makefile
+index 057b70c..1a31220 100644
+--- a/examples/TinyFPGA-BX/OSS_CAD_Suite/Makefile
++++ b/examples/TinyFPGA-BX/OSS_CAD_Suite/Makefile
+@@ -1,6 +1,6 @@
+ 
+ # override the default with: make all PROJ=loopback
+-PROJ = demo
++PROJ ?= demo
+ 
+ PIN_DEF = pins.pcf
+ DEVICE = lp8k
+@@ -42,7 +42,7 @@ prog: $(OUT_DIR)/$(PROJ).bin
+ 	tinyprog -p $<
+ 
+ lint: $(HDL_FILES)
+-	verilator --lint-only --default-language 1364-2001 -Wall -Wno-UNUSED -Wno-UNDRIVEN -Wno-TIMESCALEMOD -DBLACKBOX -DNO_ICE40_DEFAULT_ASSIGNMENTS --top $(PROJ) $(INC_DIRS) -v $(ICE40_LIB) $^
++	verilator --lint-only --default-language 1364-2001 -Wall -Wno-UNUSED -Wno-UNDRIVEN -Wno-TIMESCALEMOD -DBLACKBOX -DNO_ICE40_DEFAULT_ASSIGNMENTS $(INC_DIRS) -v $(ICE40_LIB) $^
+ 
+ $(OUT_DIR)/cells_sim.v:
+ 	patch $(ICE40_LIB) -o $(OUT_DIR)/cells_sim.v < ../../common/hdl/ice40/cells_sim.v.patch
+@@ -56,7 +56,7 @@ $(OUT_DIR)/%.fst: $(OUT_DIR)/%.vvp
+ sim: $(OUT_DIR)/$(PROJ).fst
+ 
+ $(OUT_DIR)/%.xml: $(HDL_FILES) $(TB_HDL_FILES) | $(OUT_DIR) $(OUT_DIR)/cells_sim.v
+-	verilator -xml-only --bbox-unsup --bbox-sys -Wno-lint -Wno-TIMESCALEMOD -Wno-STMTDLY -Wno-INFINITELOOP -DBLACKBOX -DNO_ICE40_DEFAULT_ASSIGNMENTS --top tb_$(PROJ) $(INC_DIRS) -v $(OUT_DIR)/cells_sim.v $^ --xml-output $@
++	verilator -xml-only --bbox-unsup --bbox-sys -Wno-lint -Wno-TIMESCALEMOD -Wno-STMTDLY -Wno-INFINITELOOP -DBLACKBOX -DNO_ICE40_DEFAULT_ASSIGNMENTS $(INC_DIRS) -v $(OUT_DIR)/cells_sim.v $^ --xml-output $@
+ 
+ $(OUT_DIR)/%.stems: $(OUT_DIR)/%.xml
+ 	xml2stems $< $@
+diff --git a/examples/common/hdl/sim_tasks.v b/examples/common/hdl/sim_tasks.v
+index 6fbcd61..8df33cc 100644
+--- a/examples/common/hdl/sim_tasks.v
++++ b/examples/common/hdl/sim_tasks.v
+@@ -52,6 +52,6 @@
+          if (end_ms > 0) \
+             $write("  (%3d%%)", 100*time_ms/end_ms); \
+          $write("\015"); \
+-         $fflush(32'h8000_0001); // flush STDOUT \
++         $fflush(32'h8000_0001); \
+       end \
+    end
+diff --git a/examples/common/hdl/usb_rx_tasks.v b/examples/common/hdl/usb_rx_tasks.v
+index f3f6db5..ade5c4b 100644
+--- a/examples/common/hdl/usb_rx_tasks.v
++++ b/examples/common/hdl/usb_rx_tasks.v
+@@ -10,6 +10,7 @@ localparam [3:0] PID_OUT = 4'b0001,
+                  PID_NAK = 4'b1010,
+                  PID_STALL = 4'b1110;
+ 
++localparam [4:0] POLY5 = 5'b00101;
+ function automatic [4:0] crc5;
+    input [MAX_BITS-1:0] data;
+    input integer        bits;
+@@ -26,6 +27,7 @@ function automatic [4:0] crc5;
+    end
+ endfunction
+ 
++localparam [15:0] POLY16 = 16'h8005;
+ function automatic [15:0] crc16;
+    input [8*MAX_BYTES-1:0] data;
+    input integer           bytes;
+@@ -44,12 +46,12 @@ function automatic [15:0] crc16;
+    end
+ endfunction
+ 
++localparam real STABLE_RATIO = 0.5; // stable time / bit_time
+ task automatic wait_bit
+   (
+    input time    bit_time,
+    input integer timeout // number of bit_time periods
+    );
+-   localparam real STABLE_RATIO = 0.5; // stable time / bit_time
+    time            start_time;
+    time            wait_time;
+    reg             exit;
+@@ -210,6 +212,8 @@ task automatic raw_packet_rx
+    end
+ endtask
+ 
++localparam [4:0]         POLY5_RESIDUAL = 5'b01100;
++localparam [15:0]        POLY16_RESIDUAL = 16'b1000000000001101;
+ task automatic packet_rx
+   (
+    output [3:0]             pid,
+@@ -221,8 +225,6 @@ task automatic packet_rx
+    input time               bit_time,
+    input integer            timeout // number of bit_time periods
+    );
+-   localparam [4:0]         POLY5_RESIDUAL = 5'b01100;
+-   localparam [15:0]        POLY16_RESIDUAL = 16'b1000000000001101;
+    reg [8*MAX_BYTES-1:0]    raw_data;
+    integer                  raw_bytes;
+    integer                  i;
+diff --git a/examples/common/hdl/usb_tasks.v b/examples/common/hdl/usb_tasks.v
+index 9f35ffc..8488af7 100644
+--- a/examples/common/hdl/usb_tasks.v
++++ b/examples/common/hdl/usb_tasks.v
+@@ -358,6 +358,7 @@ task automatic test_sof_crc_error
+    end
+ endtask
+ 
++localparam              PACKET_TIMEOUT = 6; // TRSPIPD1 (USB2.0 Tab.7-14 pag.188)
+ task automatic test_data_out
+   (
+    input [6:0]             address,
+@@ -370,7 +371,6 @@ task automatic test_data_out
+    input time              wait_time, 
+    inout [15:0]            dataout_toggle
+    );
+-   localparam              PACKET_TIMEOUT = 6; // TRSPIPD1 (USB2.0 Tab.7-14 pag.188)
+    reg                     zlp;
+    reg [3:0]               packet_pid;
+    time                    start_timeout;
+diff --git a/usb_cdc/sie.v b/usb_cdc/sie.v
+index 58390c6..c808882 100644
+--- a/usb_cdc/sie.v
++++ b/usb_cdc/sie.v
+@@ -122,9 +122,9 @@ module sie
+       end
+    endfunction
+ 
++   localparam [4:0] POLY5 = 5'b00101;
+    function [4:0] crc5;
+       input [10:0] data;
+-      localparam [4:0] POLY5 = 5'b00101;
+       reg [3:0]        i;
+       begin
+          crc5 = 5'b11111;
+@@ -147,10 +147,10 @@ module sie
+       end
+    endfunction
+ 
++   localparam [15:0] POLY16 = 16'h8005;
+    function [15:0] crc16;
+       input [7:0] data;
+       input [15:0] crc;
+-      localparam [15:0] POLY16 = 16'h8005;
+       reg [3:0]         i;
+       begin
+          crc16 = crc;
+-- 
+2.34.1
+
diff --git a/verilog/rtl/fpga/Makefile b/verilog/rtl/fpga/Makefile
index e241c45..d71710d 100644
--- a/verilog/rtl/fpga/Makefile
+++ b/verilog/rtl/fpga/Makefile
@@ -27,8 +27,13 @@
 FPGA_TYPE = lp
 FPGA_PACK = cm81
 
+CLK_MHZ = 48
+
 all: sint time
 
+pll.v:
+	icepll -i 16 -o $(CLK_MHZ) -m -f $@
+
 sim: $(NAME)_tb.vcd
 	gtkwave $< $(<:.vcd=.gtkw) &
 
@@ -58,7 +63,7 @@
 	yosys -p "$(foreach file,$^,read_verilog $(file);)" -p "synth_ice40 -json $@" $^
 
 .json.asc:
-	nextpnr-ice40 --$(FPGA_TYPE)$(FPGA_SIZE) --package $(FPGA_PACK) --pcf-allow-unconstrained --pcf $(PIN_DEF) --json $< --asc $@
+	nextpnr-ice40 --$(FPGA_TYPE)$(FPGA_SIZE) --freq $(CLK_MHZ) --package $(FPGA_PACK) --pcf-allow-unconstrained --pcf $(PIN_DEF) --json $< --asc $@
 
 .asc.bin:
 	icepack $< $@
diff --git a/verilog/rtl/fpga/README.md b/verilog/rtl/fpga/README.md
index 3fc86c5..32fd384 100644
--- a/verilog/rtl/fpga/README.md
+++ b/verilog/rtl/fpga/README.md
@@ -1,6 +1,29 @@
+# Similation tests
+
+## UART
+
+```sh
+cd verilog/rtl/
+iverilog test_uart.v verilog-uart/rtl/uart.v verilog-uart/rtl/uart_rx.v verilog-uart/rtl/uart_tx.v -o test_uart.out
+
+./test_uart.out
+gtkwave test_uart.vcd
+```
+
+## USB
+
+```sh
+cd verilog/rtl/usb_cdc/
+git apply ../0001-fix-make-targets.patch
+
+cd examples/TinyFPGA-BX/OSS_CAD_Suite/
+make PROJ=soc clean sim
+make PROJ=soc wave
+```
+
 # FPGA tests
 
-Use TinyFPGA to test.
+Use TinyFPGA_BX to test.
 
 ## USB
 
@@ -16,9 +39,9 @@
 minicom -D /dev/ttyACM0
 ```
 
-## USB2TTL
+## USB2UART
 
-Attach another USB2TTL to pins 4,5 and see characters being passed between.
+Attach another USB2UART to the first three pins on TinyFPGA_BX: GND, 1(RX), and 2(TX). One should see characters being passed between.
 
 ```sh
 tinyprog -l
diff --git a/verilog/rtl/test_uart.v b/verilog/rtl/test_uart.v
new file mode 100644
index 0000000..1b54548
--- /dev/null
+++ b/verilog/rtl/test_uart.v
@@ -0,0 +1,161 @@
+/*
+ * Usage:
+ * iverilog test_uart.v ../rtl/uart.v ../rtl/uart_rx.v ../rtl/uart_tx.v -o test_uart.out
+ * ./test_uart.out
+ * gtkwave test_uart.vcd [test_uart.gtkw]
+ */
+
+`timescale 1 ns / 1 ps
+
+module test_uart;
+
+// Testbench uses a 48 MHz clock
+// Want to interface to 115200 baud UART
+// 10000000 / 115200 = 87 Clocks Per Bit.
+parameter c_CLOCK_MHZ       = 48;
+parameter c_UART_SPEED      = 115200;
+
+parameter c_CLOCK_PERIOD_NS = 1000/c_CLOCK_MHZ;
+parameter c_CLKS_PER_BIT    = c_CLOCK_MHZ*1000000/c_UART_SPEED;
+parameter c_CLKS_PER_BYTE   = (c_CLKS_PER_BIT+7)/8;
+parameter c_BIT_PERIOD      = c_CLKS_PER_BIT*c_CLOCK_PERIOD_NS;
+
+integer i;
+integer j;
+
+reg [15:0] prescale = c_CLKS_PER_BYTE;
+reg clk = 0;
+reg rst = 0;
+
+// Inputs
+reg m_axis_tready = 0;
+reg rxd = 1;
+// Outputs
+wire [7:0] m_axis_tdata;
+wire m_axis_tvalid;
+wire rx_busy;
+wire rx_overrun_error;
+wire rx_frame_error;
+
+// Inputs
+reg [7:0] s_axis_tdata = 8'd0;
+reg s_axis_tvalid = 1'b0;
+reg [9:0] r_Tx_Data = 0;
+// Outputs
+wire s_axis_tready;
+wire txd;
+wire tx_busy;
+
+// Write a byte to RX pin
+task UART_WRITE_RX_AND_RCV;
+    input [7:0] i_Data;
+    integer     ii;
+begin
+    m_axis_tready <= 1;
+
+    // Write Start Bit
+    #(c_BIT_PERIOD) rxd <= 1'b0;
+
+    // Write Data
+    for (ii=0; ii<8; ii=ii+1)
+    begin
+        #(c_BIT_PERIOD) rxd <= i_Data[ii];
+    end
+
+    // Write Stop Bit
+    #(c_BIT_PERIOD) rxd <= 1'b1;
+
+    @(posedge m_axis_tvalid);
+end
+endtask
+
+// Send a byte and read back data from TX pin
+task UART_SEND_AND_READ_TX;
+    output [9:0] o_Data;
+    integer      ii;
+begin
+    // Send byte
+    @(posedge clk);
+    s_axis_tvalid <= 1'b1;
+    @(posedge clk);
+    s_axis_tvalid <= 1'b0;
+
+    @(posedge tx_busy);
+
+    // Read Data
+    for (ii=0; ii<10; ii=ii+1)
+    begin
+        #(c_BIT_PERIOD) o_Data[ii] <= txd;
+    end
+
+    @(posedge s_axis_tready);
+end
+endtask
+
+always
+#(c_CLOCK_PERIOD_NS/2) clk <= !clk;
+
+initial begin
+    $dumpfile("test_uart.vcd");
+    $dumpvars(0, test_uart);
+
+    // Exercise Rx
+    j=0;
+    for (i=0; i<256; i=i+1)
+    begin
+        UART_WRITE_RX_AND_RCV(i);
+        if (m_axis_tdata == i)
+            j=j+1;
+        else
+            $display("RX Test Failed - Incorrect Byte Received");
+    end
+    if (j == 256)
+        $display("RX Test Passed - Correct Bytes Received");
+
+    // Exercise Tx
+    j=0;
+    for (i=0; i<256; i=i+1)
+    begin
+        s_axis_tdata <= i;
+        UART_SEND_AND_READ_TX(r_Tx_Data);
+        // Check that the correct byte was sent
+        if (r_Tx_Data[8:1] == i)
+            j=j+1;
+        else
+            $display("TX Test Failed - Incorrect Byte Sent");
+    end
+    if (j == 256)
+        $display("TX Test Passed - Correct Bytes Sent");
+
+    $finish;
+end
+
+uart #(
+    .DATA_WIDTH(8)
+)
+UUT (
+    .clk(clk),
+    .rst(rst),
+    // axi output
+    .m_axis_tdata(m_axis_tdata),
+    .m_axis_tvalid(m_axis_tvalid),
+    .m_axis_tready(m_axis_tready),
+    // input
+    .rxd(rxd),
+    // status
+    .rx_busy(rx_busy),
+    .rx_overrun_error(rx_overrun_error),
+    .rx_frame_error(rx_frame_error),
+    // axi input
+    .s_axis_tdata(s_axis_tdata),
+    .s_axis_tvalid(s_axis_tvalid),
+    .s_axis_tready(s_axis_tready),
+    // output
+    .txd(txd),
+    // status
+    .tx_busy(tx_busy),
+    // configuration
+    .prescale(prescale)
+);
+
+endmodule