diff fpga/sniffer-pps/pps_catcher.v @ 28:0f74428c177c

fpga/sniffer-pps: first version
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 29 Aug 2023 20:05:23 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fpga/sniffer-pps/pps_catcher.v	Tue Aug 29 20:05:23 2023 +0000
@@ -0,0 +1,165 @@
+/*
+ * This Verilog module is our PPS catcher.  It is a state machine that analyzes
+ * the stream of Rx characters from the primary sniffer and detects the
+ * positions of these two special chars:
+ *
+ * - the PPS1 byte of the card's PPS response;
+ * - the PCK byte concluding that PPS response *if* PPS1 indicated a speed
+ *   enhancement mode which we support.
+ */
+
+module pps_catcher (IntClk, SIM_RST_sync, Rx_strobe, Rx_char,
+		    pos_PPS_resp_PPS1, pos_PPS_resp_PCK);
+
+input IntClk;
+input SIM_RST_sync;
+input Rx_strobe;
+input [7:0] Rx_char;
+
+output pos_PPS_resp_PPS1, pos_PPS_resp_PCK;
+
+/* state machine */
+
+localparam
+	INITIAL		= 5'h00,
+	ATR_T0		= 5'h01,
+	ATR_TAn		= 5'h02,
+	ATR_TBn		= 5'h03,
+	ATR_TCn		= 5'h04,
+	ATR_TDn		= 5'h05,
+	ATR_HIST	= 5'h06,
+	ATR_TCK		= 5'h07,
+	READY_FOR_PPS	= 5'h08,
+	REQ_PPS0	= 5'h09,
+	REQ_PPS1	= 5'h0A,
+	REQ_PPS2	= 5'h0B,
+	REQ_PPS3	= 5'h0C,
+	REQ_PCK		= 5'h0F,
+	READY_FOR_RESP	= 5'h10,
+	RESP_PPS0	= 5'h11,
+	RESP_PPS1	= 5'h12,
+	RESP_PPS2	= 5'h13,
+	RESP_PPS3	= 5'h14,
+	RESP_PCK	= 5'h17,
+	DONE		= 5'h1F
+	;
+
+reg [4:0] state;
+reg [3:0] Y, K;
+reg have_TCK;
+
+always @(posedge IntClk)
+	if (!SIM_RST_sync)
+	    begin
+		state <= INITIAL;
+		have_TCK <= 1'b0;
+	    end
+	else case (state)
+		INITIAL:
+			if (Rx_strobe)
+			begin
+				if (Rx_char == 8'h3B)
+					state <= ATR_T0;
+				else
+					state <= DONE;
+			end
+		ATR_T0:
+			if (Rx_strobe)
+			begin
+				Y <= Rx_char[7:4];
+				K <= Rx_char[3:0];
+				state <= ATR_TAn;
+			end
+		ATR_TAn:
+			if (!Y[0] || Rx_strobe)
+				state <= ATR_TBn;
+		ATR_TBn:
+			if (!Y[1] || Rx_strobe)
+				state <= ATR_TCn;
+		ATR_TCn:
+			if (!Y[2] || Rx_strobe)
+				state <= ATR_TDn;
+		ATR_TDn:
+			if (!Y[3])
+				state <= ATR_HIST;
+			else if (Rx_strobe)
+			begin
+				Y <= Rx_char[7:4];
+				if (Rx_char[3:0] != 4'h0)
+					have_TCK <= 1'b1;
+				state <= ATR_TAn;
+			end
+		ATR_HIST:
+			if (K == 4'd0)
+				state <= ATR_TCK;
+			else if (Rx_strobe)
+				K <= K - 4'd1;
+		ATR_TCK:
+			if (!have_TCK || Rx_strobe)
+				state <= READY_FOR_PPS;
+		READY_FOR_PPS:
+			if (Rx_strobe)
+			begin
+				if (Rx_char == 8'hFF)
+					state <= REQ_PPS0;
+				else
+					state <= DONE;
+			end
+		REQ_PPS0:
+			if (Rx_strobe)
+			begin
+				Y <= Rx_char[7:4];
+				state <= REQ_PPS1;
+			end
+		REQ_PPS1:
+			if (!Y[0] || Rx_strobe)
+				state <= REQ_PPS2;
+		REQ_PPS2:
+			if (!Y[1] || Rx_strobe)
+				state <= REQ_PPS3;
+		REQ_PPS3:
+			if (!Y[2] || Rx_strobe)
+				state <= REQ_PCK;
+		REQ_PCK:
+			if (Rx_strobe)
+				state <= READY_FOR_RESP;
+		READY_FOR_RESP:
+			if (Rx_strobe)
+			begin
+				if (Rx_char == 8'hFF)
+					state <= RESP_PPS0;
+				else
+					state <= DONE;
+			end
+		RESP_PPS0:
+			if (Rx_strobe)
+			begin
+				Y <= Rx_char[7:4];
+				if (Rx_char[4])
+					state <= RESP_PPS1;
+				else
+					state <= DONE;
+			end
+		RESP_PPS1:
+			if (Rx_strobe)
+			begin
+				if (Rx_char[7:2] == 6'b100101)
+					state <= RESP_PPS2;
+				else
+					state <= DONE;
+			end
+		RESP_PPS2:
+			if (!Y[1] || Rx_strobe)
+				state <= RESP_PPS3;
+		RESP_PPS3:
+			if (!Y[2] || Rx_strobe)
+				state <= RESP_PCK;
+		RESP_PCK:
+			if (Rx_strobe)
+				state <= DONE;
+	endcase
+
+assign pos_PPS_resp_PPS1 = (state == RESP_PPS1);
+assign pos_PPS_resp_PCK = (state == RESP_PCK);
+
+endmodule