changeset 6:7db5fd6646df

fpga/sniffer-basic: initial version
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 21 Aug 2023 00:52:00 +0000
parents 07c5aac6e84f
children beeda5368a77
files fpga/sniffer-basic/Makefile fpga/sniffer-basic/clk_edge.v fpga/sniffer-basic/icestick.pcf fpga/sniffer-basic/reset_detect.v fpga/sniffer-basic/sniff_rx.v fpga/sniffer-basic/sync_inputs.v fpga/sniffer-basic/top.v fpga/sniffer-basic/uart_tx.v
diffstat 8 files changed, 285 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/Makefile	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,18 @@
+VSRC=	clk_edge.v reset_detect.v sniff_rx.v sync_inputs.v top.v uart_tx.v
+PCF=	icestick.pcf
+PROJ=	fpga
+
+all:	${PROJ}.bin
+
+${PROJ}.json:	${VSRC}
+	./yosys-wrap top $@ ${VSRC}
+
+${PROJ}.asc:	${PROJ}.json ${PCF}
+	nextpnr-ice40 --hx1k --package tq144 --asc $@ --pcf ${PCF} \
+		--json ${PROJ}.json
+
+${PROJ}.bin:	${PROJ}.asc
+	icepack $< $@
+
+clean:
+	rm -f *.json *.asc *.bin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/clk_edge.v	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,19 @@
+/*
+ * This Verilog module captures the logic that detects rising edges of SIM_CLK
+ * for the purpose of counting them.
+ */
+
+module clk_edge (IntClk, SIM_CLK_sync, SIM_CLK_edge);
+
+input IntClk;
+input SIM_CLK_sync;
+output SIM_CLK_edge;
+
+reg prev_state;
+
+always @(posedge IntClk)
+	prev_state <= SIM_CLK_sync;
+
+assign SIM_CLK_edge = SIM_CLK_sync && !prev_state;
+
+endmodule
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/icestick.pcf	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,28 @@
+# Pin Constraint File for the HK1X FPGA as wired on the Icestick board,
+# adapted for SIMtrace-ice application.
+
+# Board essentials
+set_io	CLK12		21
+set_io	LED1		99
+set_io	LED2		98
+set_io	LED3		97
+set_io	LED4		96
+set_io	LED5		95
+
+# FT2232H UART channel, signal names are from FT2232H DTE perspective,
+# the logic in the FPGA has to act as DCE.
+
+set_io	UART_TxD	9
+set_io	UART_RxD	8
+set_io	UART_RTS	7
+set_io	UART_CTS	4
+set_io	UART_DTR	3
+set_io	UART_DSR	2
+set_io	UART_DCD	1
+
+# SIM sniffing interface, receiving outputs from the level shifter board
+# via J1 header pins
+
+set_io	SIM_RST		112
+set_io	SIM_CLK		113
+set_io	SIM_IO		114
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/reset_detect.v	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,19 @@
+/*
+ * This Verilog module captures the logic that detects SIM_RST transitions
+ * in either direction.
+ */
+
+module reset_detect (IntClk, SIM_RST_sync, SIM_RST_toggle);
+
+input IntClk;
+input SIM_RST_sync;
+output SIM_RST_toggle;
+
+reg prev_state;
+
+always @(posedge IntClk)
+	prev_state <= SIM_RST_sync;
+
+assign SIM_RST_toggle = SIM_RST_sync != prev_state;
+
+endmodule
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/sniff_rx.v	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,62 @@
+/*
+ * This Verilog module captures the ISO 7816-3 character sniffing receiver.
+ */
+
+module sniff_rx (IntClk, SIM_RST_sync, SIM_CLK_sync, SIM_IO_sync,
+		 Rx_strobe, Rx_error, Rx_char, Rx_start_bit, Rx_parity_bit);
+
+input IntClk;
+input SIM_RST_sync, SIM_CLK_sync, SIM_IO_sync;
+output Rx_strobe, Rx_error;
+output [7:0] Rx_char;
+output Rx_start_bit, Rx_parity_bit;
+
+wire SIM_CLK_edge;
+
+clk_edge clk_edge (IntClk, SIM_CLK_sync, SIM_CLK_edge);
+
+wire [9:0] etu_0p5, etu_1p0, etu_1p5;
+
+/* Fi/Di=372 only for now */
+assign etu_0p5 = 10'd185;
+assign etu_1p0 = 10'd371;
+assign etu_1p5 = 10'd557;
+
+reg rx_active;
+reg [9:0] clk_count;
+reg [3:0] bit_count;
+reg [9:0] shift_reg;
+
+always @(posedge IntClk)
+	if (!SIM_RST_sync)
+		rx_active <= 1'b0;
+	else if (!rx_active && !SIM_IO_sync)
+	    begin
+		rx_active <= 1'b1;
+		clk_count <= etu_0p5;
+		bit_count <= 4'd0;
+	    end
+	else if (rx_active && SIM_CLK_edge)
+	    begin
+		if (clk_count != 10'd0)
+			clk_count <= clk_count - 10'd1;
+		else begin
+			shift_reg <= {SIM_IO_sync,shift_reg[9:1]};
+			bit_count <= bit_count + 4'd1;
+			if (bit_count == 4'd9)
+				clk_count <= etu_1p5;
+			else
+				clk_count <= etu_1p0;
+			if (bit_count == 4'd10)
+				rx_active <= 1'b0;
+		end
+	end
+
+assign Rx_strobe = rx_active && SIM_CLK_edge && clk_count == 10'd0 &&
+		   bit_count == 4'd10;
+assign Rx_error = Rx_strobe && !SIO_IO_sync;
+assign Rx_char = shift_reg[8:1];
+assign Rx_start_bit = shift_reg[0];
+assign Rx_parity_bit = shift_reg[9];
+
+endmodule
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/sync_inputs.v	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,35 @@
+/*
+ * This Verilog module captures the input synchronizer logic: passing all 3
+ * SIM sniffer inputs through double-DFF synchronizers to bring them into
+ * our internal clock domain.
+ */
+
+module sync_inputs (IntClk, SIM_RST_in, SIM_RST_sync, SIM_CLK_in, SIM_CLK_sync,
+		    SIM_IO_in, SIM_IO_sync);
+
+input IntClk;
+input SIM_RST_in, SIM_CLK_in, SIM_IO_in;
+output SIM_RST_sync, SIM_CLK_sync, SIM_IO_sync;
+reg SIM_RST_sync, SIM_CLK_sync, SIM_IO_sync;
+
+reg SIM_RST_sync1, SIM_CLK_sync1, SIM_IO_sync1;
+
+always @(posedge IntClk)
+	SIM_RST_sync1 <= SIM_RST_in;
+
+always @(posedge IntClk)
+	SIM_RST_sync <= SIM_RST_sync1;
+
+always @(posedge IntClk)
+	SIM_CLK_sync1 <= SIM_CLK_in;
+
+always @(posedge IntClk)
+	SIM_CLK_sync <= SIM_CLK_sync1;
+
+always @(posedge IntClk)
+	SIM_IO_sync1 <= SIM_IO_in;
+
+always @(posedge IntClk)
+	SIM_IO_sync <= SIM_IO_sync1;
+
+endmodule
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/top.v	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,59 @@
+module top (CLK12, LED1, LED2, LED3, LED4, LED5, UART_TxD, UART_RxD, UART_RTS,
+	    UART_CTS, UART_DTR, UART_DSR, UART_DCD, SIM_RST, SIM_CLK, SIM_IO);
+
+input CLK12;
+output LED1, LED2, LED3, LED4, LED5;
+
+input UART_TxD, UART_RTS, UART_DTR;
+output UART_RxD, UART_CTS, UART_DSR, UART_DCD;
+
+input SIM_RST, SIM_CLK, SIM_IO;
+
+/* input synchronizers */
+
+wire SIM_RST_sync, SIM_CLK_sync, SIM_IO_sync;
+
+sync_inputs sync (CLK12, SIM_RST, SIM_RST_sync, SIM_CLK, SIM_CLK_sync,
+		  SIM_IO, SIM_IO_sync);
+
+/* character receiver */
+
+wire Rx_strobe, Rx_error;
+wire [7:0] Rx_char;
+wire Rx_start_bit, Rx_parity_bit;
+
+sniff_rx sniff_rx (CLK12, SIM_RST_sync, SIM_CLK_sync, SIM_IO_sync,
+		   Rx_strobe, Rx_error, Rx_char, Rx_start_bit, Rx_parity_bit);
+
+/* explicit detection of RST transitions */
+
+wire SIM_RST_toggle;
+
+reset_detect reset_detect (CLK12, SIM_RST_sync, SIM_RST_toggle);
+
+/* output to the host */
+
+wire Tx_trigger;
+wire [15:0] Tx_data;
+
+assign Tx_trigger = Rx_strobe | SIM_RST_toggle;
+assign Tx_data = {SIM_RST_toggle,SIM_RST_sync,3'b000,
+		  Rx_error,Rx_start_bit,Rx_parity_bit,Rx_char};
+
+uart_tx uart_tx (CLK12, Tx_trigger, Tx_data, UART_RxD);
+
+/* UART modem control outputs: unused */
+
+assign UART_CTS = 1'b1;
+assign UART_DSR = 1'b0;
+assign UART_DCD = 1'b0;
+
+/* board LEDs */
+
+assign LED1 = 1'b1;
+assign LED2 = 1'b0;
+assign LED3 = 1'b1;
+assign LED4 = 1'b0;
+assign LED5 = !SIM_RST;
+
+endmodule
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-basic/uart_tx.v	Mon Aug 21 00:52:00 2023 +0000
@@ -0,0 +1,45 @@
+/*
+ * This Verilog module captures the UART output logic.
+ */
+
+module uart_tx (IntClk, Tx_trigger, Tx_data, UART_out);
+
+input IntClk;
+input Tx_trigger;
+input [15:0] Tx_data;
+output UART_out;
+reg UART_out;
+
+reg tx_active;
+reg [1:0] clk_div;
+reg [4:0] bit_count;
+reg [17:0] shift_reg;
+
+initial begin
+	tx_active = 1'b0;
+	UART_out = 1'b1;
+end
+
+always @(posedge IntClk)
+	if (!tx_active && Tx_trigger)
+	    begin
+		tx_active <= 1'b1;
+		UART_out <= 1'b0;
+		clk_div <= 2'd0;
+		shift_reg <= {Tx_data[15:8],2'b01,Tx_data[7:0]};
+		bit_count <= 5'd0;
+	    end
+	else if (tx_active)
+	    begin
+		clk_div <= clk_div + 2'd1;
+		if (clk_div == 2'd3)
+		    begin
+			UART_out <= shift_reg[0];
+			shift_reg <= {1,shift_reg[17:1]};
+			bit_count <= bit_count + 5'd1;
+			if (bit_count == 5'd19)
+				tx_active <= 1'b0;
+		end
+	end
+
+endmodule