// (C) 2001-2025 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Altera Program License Subscription 
// Agreement, Altera IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Altera and sold by 
// Altera or its authorized distributors.  Please refer to the applicable 
// agreement for further details.


module ltssm_monitor # (
	parameter LTSSM_COUNTER_WIDTH = 26
    ) (
	input           					clk,

    input 								ninit_done,  //may change core_pll_lock

    //HIP status
   
    input [5:0]     					ltssm_state_i,
	
	output [LTSSM_COUNTER_WIDTH-1:0]   	ltssm_counter_value_o,
	output          					state_transition_o,
	output [5:0]    					captured_ltssm_state_o
	);
	
	logic [LTSSM_COUNTER_WIDTH-1:0] ltssm_counter_value_r;
	logic [5:0]  saved_ltssm_state;
	logic [5:0]  saved_ltssm_state_r;
	logic [5:0]  saved_ltssm_state_r2;
	logic [1:0]  ltssm_counter_state;
	logic [1:0]  ltssm_counter_nxt_state;
	logic [25:0] ltssm_counter_value_w;
  
        logic        init_done_hip_coreclk_sync;

        altera_std_synchronizer_nocut ninit_done_hip_coreclk_sync_inst (.clk (clk),    .reset_n (~ninit_done), .din (1'b1), .dout (init_done_hip_coreclk_sync) );
    localparam  INITIALIZE     = 2'b00;
	localparam  COUNT          = 2'b01;
	localparam  CHANGE_STATE   = 2'b10;
  
	logic state_transition_r;
	logic [5:0] captured_ltssm_state_r;
	logic [LTSSM_COUNTER_WIDTH-1:0] ltssm_counter_value_r2;
  
	assign state_transition_o = state_transition_r;                               
	assign captured_ltssm_state_o = captured_ltssm_state_r;
	assign ltssm_counter_value_o = ltssm_counter_value_r2;

	always_ff @ (posedge clk) begin
		saved_ltssm_state 		<= ltssm_state_i;
		saved_ltssm_state_r 	<= saved_ltssm_state;
		saved_ltssm_state_r2 	<= saved_ltssm_state_r;
		captured_ltssm_state_r 	<= saved_ltssm_state_r2;
		ltssm_counter_value_r2 	<= ltssm_counter_value_r;
		state_transition_r    	<= ((ltssm_counter_state == CHANGE_STATE) && (saved_ltssm_state_r == saved_ltssm_state) && (ltssm_counter_value_r2 != 'h0)); // to save last state after pin_perst            
	end

	always_ff @ (posedge clk) begin
		if (~init_done_hip_coreclk_sync)
			ltssm_counter_state <= INITIALIZE;
		else 
			ltssm_counter_state <= ltssm_counter_nxt_state;
	end
  
	always_comb begin
		case(ltssm_counter_state)
			INITIALIZE:
				if (~init_done_hip_coreclk_sync)
					ltssm_counter_nxt_state = INITIALIZE;
				else
					ltssm_counter_nxt_state = CHANGE_STATE;
			COUNT:
				if (saved_ltssm_state == saved_ltssm_state_r)
					ltssm_counter_nxt_state = COUNT;
				else
					ltssm_counter_nxt_state = CHANGE_STATE;
			CHANGE_STATE:
				ltssm_counter_nxt_state = COUNT;
			default:
				ltssm_counter_nxt_state = INITIALIZE; 
		endcase
	end

    always_ff @ (posedge clk) begin
	    ltssm_counter_value_r <= ltssm_counter_value_w;
	end
  
    always_comb begin
		if (ltssm_counter_state == INITIALIZE)
			ltssm_counter_value_w = {LTSSM_COUNTER_WIDTH{1'b0}};
		else if (ltssm_counter_state == COUNT)
			ltssm_counter_value_w = ltssm_counter_value_r + 1'h1;
		else //CHANGE_STATE
		  ltssm_counter_value_w = 'b1;
	end
  
endmodule
`ifdef QUESTA_INTEL_OEM
`pragma questa_oem_00 "PNVV7/bs9iBHIRlA5ZBsyN/GPZ0TXi6qn2Dh2M7pAeu7gJ2ZBA7h3JGkvjXkuC5UIXo/z5gQmp1UZ7sTAaTT/jY49W2SxnQK1Yi3m9AqA7DQvdVNQSIP0StiA6cd/Bmb1xOyX01r0Q1kSbh1Xg00173NRrSBh6I2laKRBqIVNUuwBG6+CnWpVjqQa+TAR5sCjTNP+I8jQLtXq7doP9+lP7YXqXhRmwId5c9JhVEr4VkAmSs+c1uG2/wMnzhrWkXvWCcyKCiM0cO82A7cdHDfjiURb9c71Xuh4ldygyedhk+Z3kCyamlWQCxKDo6RaumGEq9cm8DPcynuZ27W96qznJ5pvD1dmt6a28TOzUHGeL/z5G9gCPfUVJJmq0ecom3zhX0ik8U9/9sNNBufZvpD/1wI47nlaMGXdHLjT39ja8zSv/moOxQLQz+HECLIbh6m5Jj95Vko3+X1598bbWKXuJBeejX+/cfVSYxMpK5VLDwAQa0LJccZpTy0bxOStDKG1Y7+Z0a62249tan6m6tjeIgyOOZxNEL9hDIyWMA88JFkx8mXGUleLy+ipoZXcveMkL5VcT9pJsaOr/mWJVz6CWhNWCgrhwpPuTqjPv4rhUfFRRYgCWETM1btBDaClBQ1QkmQ6D7JBPALaJqJM3fMfk9Abgu0TCDaSrRTWIy+P70dtiiY0798UrM6pgEcNqAJX5TvfSGg8msyJzAaB/Jm2OozH2qR921LCT8Qs1XzsFbVnu7ux3Uk1uWR3a4FQxpH0CBDfhDv5SCCSFRm2rUbeuIoNpBmsZEHxuxHq4r+tEmwM4QhGthyJmkutc+S/He/wQpam/sGb1s8hXmMX1E6b/A4jQrtNqenI1/Xlaho/K2W85FfR0gDfiXM8BTTyC5jg6zS0yatU8tfGTF9+JSJRMjLLS7NaDYlskOqG44mL3CTqmmugBAdvlm1eBmWSkcJxxVrgyIa+HaWmBG0Ui8P/WMUxlkKQY738EsbvIffEoNEAz0voB71iMgo+mlO/2gG"
`endif