view 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 source

/*
 * 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