add fpga test
diff --git a/verilog/rtl/fpga/Makefile b/verilog/rtl/fpga/Makefile
new file mode 100644
index 0000000..555204e
--- /dev/null
+++ b/verilog/rtl/fpga/Makefile
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: Apache-2.0
+
+# Usage:
+# make clean all
+# make prog
+
+NAME = fpga_top
+DEPS = \
+../usb_cdc/usb_cdc/phy_tx.v \
+../usb_cdc/usb_cdc/phy_rx.v \
+../usb_cdc/usb_cdc/sie.v \
+../usb_cdc/usb_cdc/ctrl_endp.v \
+../usb_cdc/usb_cdc/in_fifo.v \
+../usb_cdc/usb_cdc/out_fifo.v \
+../usb_cdc/usb_cdc/bulk_endp.v \
+../usb_cdc/usb_cdc/usb_cdc.v \
+../usb_cdc/examples/common/hdl/prescaler.v \
+../usb_cdc/examples/common/hdl/fifo_if.v \
+../usb_cdc/examples/TinyFPGA-BX/hdl/soc/app.v
+PIN_DEF = fpga_pins.pcf
+
+# TinyFPGA-BX
+FPGA_SIZE = 8k
+FPGA_TYPE = hx
+FPGA_PACK = cm81
+
+all: sint
+
+sim: $(NAME)_tb.vcd
+ gtkwave $< $(<:.vcd=.gtkw) &
+
+$(NAME)_tb.vcd: $(NAME).v $(DEPS) $(NAME)_tb.v
+
+sint: $(NAME).bin
+
+$(NAME).json: $(NAME).v $(DEPS)
+
+$(NAME).asc: $(NAME).json $(PIN_DEF)
+
+prog: $(NAME).bin
+ tinyprog -p $<
+
+time: $(NAME).rpt
+
+.SUFFIXES: .asc .bin .json .v .vcd .rpt
+
+.asc.rpt:
+ icetime -d $(FPGA_TYPE)$(FPGA_SIZE) -P $(FPGA_PACK) -mtr $@ $^
+
+.v.vcd:
+ iverilog $^ -o $(@:.vcd=.out)
+ ./$(@:.vcd=.out)
+
+.v.json:
+ yosys -p "synth_ice40 -json $@" $^
+
+.json.asc:
+ nextpnr-ice40 --$(FPGA_TYPE)$(FPGA_SIZE) --package $(FPGA_PACK) --pcf-allow-unconstrained --pcf $(PIN_DEF) --json $< --asc $@
+
+.asc.bin:
+ icepack $< $@
+
+clean:
+ rm -f *.bin *.asc *.json *.out *.vcd *.rpt
+
+.PHONY: all sim sint prog clean time
diff --git a/verilog/rtl/fpga/README.md b/verilog/rtl/fpga/README.md
new file mode 100644
index 0000000..a3bb582
--- /dev/null
+++ b/verilog/rtl/fpga/README.md
@@ -0,0 +1,14 @@
+# FPGA tests
+
+Use TinyFPGA to test.
+
+## USB
+
+```sh
+cd ../usb_cdc/examples/TinyFPGA-BX/OSS_CAD_Suite/
+tinyprog -l
+make all PROJ=soc
+make prog PROJ=soc
+minicom -D /dev/ttyACM0
+```
+
diff --git a/verilog/rtl/fpga/fpga_pins.pcf b/verilog/rtl/fpga/fpga_pins.pcf
new file mode 100644
index 0000000..3674bae
--- /dev/null
+++ b/verilog/rtl/fpga/fpga_pins.pcf
@@ -0,0 +1,9 @@
+# ##############################################################################
+# TinyFPGA BX
+# ##############################################################################
+
+set_io usb_pu A3
+set_io usb_n A4
+set_io usb_p B4
+set_io led B3
+set_io clk B2
diff --git a/verilog/rtl/fpga/fpga_top.v b/verilog/rtl/fpga/fpga_top.v
new file mode 100644
index 0000000..67da9e0
--- /dev/null
+++ b/verilog/rtl/fpga/fpga_top.v
@@ -0,0 +1,176 @@
+
+module soc
+ (
+ input clk, // 16MHz Clock
+ output led, // User LED ON=1, OFF=0
+ inout usb_p, // USB+
+ inout usb_n, // USB-
+ output usb_pu // USB 1.5kOhm Pullup EN
+ );
+
+ localparam BIT_SAMPLES = 'd4;
+ localparam [6:0] DIVF = 12*BIT_SAMPLES-1;
+
+ wire clk_pll;
+ wire clk_1mhz;
+ wire clk_2mhz;
+ wire clk_4mhz;
+ wire clk_8mhz;
+ wire lock;
+ wire dp_pu;
+ wire dp_rx;
+ wire dn_rx;
+ wire dp_tx;
+ wire dn_tx;
+ wire tx_en;
+ wire [7:0] out_data;
+ wire out_valid;
+ wire in_ready;
+ wire [7:0] in_data;
+ wire in_valid;
+ wire out_ready;
+
+ // if FEEDBACK_PATH = SIMPLE:
+ // clk_freq = (ref_freq * (DIVF + 1)) / (2**DIVQ * (DIVR + 1));
+ SB_PLL40_CORE #(.DIVR(4'd0),
+ .DIVF(DIVF),
+ .DIVQ(3'd4),
+ .FILTER_RANGE(3'b001),
+ .FEEDBACK_PATH("SIMPLE"),
+ .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"),
+ .FDA_FEEDBACK(4'b0000),
+ .DELAY_ADJUSTMENT_MODE_RELATIVE("FIXED"),
+ .FDA_RELATIVE(4'b0000),
+ .SHIFTREG_DIV_MODE(2'b00),
+ .PLLOUT_SELECT("GENCLK"),
+ .ENABLE_ICEGATE(1'b0))
+ u_pll (.REFERENCECLK(clk), // 16MHz
+ .PLLOUTCORE(),
+ .PLLOUTGLOBAL(clk_pll), // 48MHz
+ .EXTFEEDBACK(1'b0),
+ .DYNAMICDELAY(8'd0),
+ .LOCK(lock),
+ .BYPASS(1'b0),
+ .RESETB(1'b1),
+ .SDI(1'b0),
+ .SDO(),
+ .SCLK(1'b0),
+ .LATCHINPUTVALUE(1'b1));
+
+ prescaler u_prescaler (.clk_i(clk),
+ .rstn_i(lock),
+ .clk_div16_o(clk_1mhz),
+ .clk_div8_o(clk_2mhz),
+ .clk_div4_o(clk_4mhz),
+ .clk_div2_o(clk_8mhz));
+
+ reg [1:0] rstn_sync;
+
+ wire rstn;
+
+ assign rstn = rstn_sync[0];
+
+ always @(posedge clk_1mhz or negedge lock) begin
+ if (~lock) begin
+ rstn_sync <= 2'd0;
+ end else begin
+ rstn_sync <= {1'b1, rstn_sync[1]};
+ end
+ end
+
+ reg [20:0] up_cnt;
+ reg [1:0] sleep_sq;
+
+ wire sleep;
+
+ always @(posedge clk_1mhz or negedge rstn) begin
+ if (~rstn) begin
+ up_cnt <= 'd0;
+ sleep_sq <= 2'b00;
+ end else begin
+ sleep_sq <= {sleep, sleep_sq[1]};
+ if (up_cnt[20] == 1'b0)
+ up_cnt <= up_cnt + 1;
+ else if (~sleep_sq[0])
+ up_cnt <= 21'hE0000;
+ end
+ end
+
+ assign led = ~dp_pu | ~up_cnt[20];
+
+ app u_app (.clk_i(clk_2mhz),
+ .rstn_i(rstn),
+ .sleep_o(sleep),
+ .out_data_i(out_data),
+ .out_valid_i(out_valid),
+ .in_ready_i(in_ready),
+ .out_ready_o(out_ready),
+ .in_data_o(in_data),
+ .in_valid_o(in_valid));
+
+ usb_cdc #(.VENDORID(16'h1D50),
+ .PRODUCTID(16'h6130),
+ .IN_BULK_MAXPACKETSIZE('d8),
+ .OUT_BULK_MAXPACKETSIZE('d8),
+ .BIT_SAMPLES(BIT_SAMPLES),
+ .USE_APP_CLK(1),
+ .APP_CLK_RATIO(BIT_SAMPLES*12/2)) // BIT_SAMPLES * 12MHz / 2MHz
+ u_usb_cdc (.frame_o(),
+ .configured_o(),
+ .app_clk_i(clk_2mhz),
+ .clk_i(clk_pll),
+ .rstn_i(rstn),
+ .out_ready_i(out_ready),
+ .in_data_i(in_data),
+ .in_valid_i(in_valid),
+ .dp_rx_i(dp_rx),
+ .dn_rx_i(dn_rx),
+ .out_data_o(out_data),
+ .out_valid_o(out_valid),
+ .in_ready_o(in_ready),
+ .dp_pu_o(dp_pu),
+ .tx_en_o(tx_en),
+ .dp_tx_o(dp_tx),
+ .dn_tx_o(dn_tx));
+
+ SB_IO #(.PIN_TYPE(6'b101001),
+ .PULLUP(1'b0))
+ u_usb_p (.PACKAGE_PIN(usb_p),
+ .OUTPUT_ENABLE(tx_en),
+ .D_OUT_0(dp_tx),
+ .D_IN_0(dp_rx),
+ .D_OUT_1(1'b0),
+ .D_IN_1(),
+ .CLOCK_ENABLE(1'b0),
+ .LATCH_INPUT_VALUE(1'b0),
+ .INPUT_CLK(1'b0),
+ .OUTPUT_CLK(1'b0));
+
+ SB_IO #(.PIN_TYPE(6'b101001),
+ .PULLUP(1'b0))
+ u_usb_n (.PACKAGE_PIN(usb_n),
+ .OUTPUT_ENABLE(tx_en),
+ .D_OUT_0(dn_tx),
+ .D_IN_0(dn_rx),
+ .D_OUT_1(1'b0),
+ .D_IN_1(),
+ .CLOCK_ENABLE(1'b0),
+ .LATCH_INPUT_VALUE(1'b0),
+ .INPUT_CLK(1'b0),
+ .OUTPUT_CLK(1'b0));
+
+ // drive usb_pu to 3.3V or to high impedance
+ SB_IO #(.PIN_TYPE(6'b101001),
+ .PULLUP(1'b0))
+ u_usb_pu (.PACKAGE_PIN(usb_pu),
+ .OUTPUT_ENABLE(dp_pu),
+ .D_OUT_0(1'b1),
+ .D_IN_0(),
+ .D_OUT_1(1'b0),
+ .D_IN_1(),
+ .CLOCK_ENABLE(1'b0),
+ .LATCH_INPUT_VALUE(1'b0),
+ .INPUT_CLK(1'b0),
+ .OUTPUT_CLK(1'b0));
+
+endmodule