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