// (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 sm_link_inspector_top # (
    parameter core16_func_mode_hwtcl = "Enable",
    parameter core8_func_mode_hwtcl  = "Enable"
) (
    input [5:0]     p0_ltssm_state,
    input [5:0]     p1_ltssm_state,
    
    input           hip_coreclk,
	// From ADME
    input           avmm_write,             
    input  [3:0]    avmm_address,          
    input  [31:0]   avmm_writedata,       
    input           avmm_read,           
    output [31:0]   avmm_readdata,      
    output          avmm_readdatavalid,
    input           avmm_clk,
    input           avmm_reset_n,
    output          avmm_waitrequest,
    
    input           ninit_done
);
  
  localparam LTSSM_COUNTER_WIDTH = 26 ;
  
  logic [LTSSM_COUNTER_WIDTH-1:0] p0_ltssm_counter_value;
  logic [LTSSM_COUNTER_WIDTH-1:0] p1_ltssm_counter_value;
    
  logic [5:0]  p0_captured_ltssm_state;
  logic [5:0]  p1_captured_ltssm_state;
  
  logic [(LTSSM_COUNTER_WIDTH+6)-1:0] p0_ltssm_fifo_q;
  logic [(LTSSM_COUNTER_WIDTH+6)-1:0] p1_ltssm_fifo_q;
 
  logic        p0_state_transition;
  logic        p1_state_transition;
   
  logic        p0_ltssm_fifo_wrreq;
  logic        p1_ltssm_fifo_wrreq;
  		       
  logic        p0_ltssm_fifo_rdreq;
  logic        p1_ltssm_fifo_rdreq;
    
  logic        p0_ltssm_fifo_wrfull;
  logic        p1_ltssm_fifo_wrfull;
  
  logic        p0_ltssm_fifo_rdfull;
  logic        p1_ltssm_fifo_rdfull;
    
  logic        p0_ltssm_fifo_wrempty;
  logic        p1_ltssm_fifo_wrempty;
    
  logic        p0_ltssm_fifo_rdempty;
  logic        p1_ltssm_fifo_rdempty;
  
  logic [9:0]  p0_ltssm_fifo_rdusedw;
  logic [9:0]  p1_ltssm_fifo_rdusedw;
    
  logic        avmm_read_r;
  logic [31:0] avmm_readdata_r;
  
  logic	       readdatavalid_r;  
  logic        readdatavalid_r2;  

//  PCIe HIP port 0 - ADME base address: 0x20_0000
//  PCIe HIP port 1 - ADME base address: 0x40_0000

  assign avmm_readdata = avmm_readdata_r;
  assign avmm_readdatavalid = readdatavalid_r2;
  assign avmm_waitrequest = avmm_read && !readdatavalid_r2;

  always_ff @(posedge avmm_clk) begin
  	avmm_read_r <= avmm_read;
	readdatavalid_r2 <= readdatavalid_r;
  end
  
  always @(posedge avmm_clk) begin
	readdatavalid_r <= avmm_read && !avmm_read_r;
  end
  
  generate
     if (core16_func_mode_hwtcl=="Enable" && core8_func_mode_hwtcl=="Disable") begin : PCIE_P0
        ltssm_monitor # (
	    .LTSSM_COUNTER_WIDTH 	(LTSSM_COUNTER_WIDTH)
	) ltssm_counter_p0_pcie (
            .clk                        (hip_coreclk),
            .ninit_done                 (ninit_done),
	    .ltssm_state_i              (p0_ltssm_state),
            .ltssm_counter_value_o      (p0_ltssm_counter_value),
            .state_transition_o         (p0_state_transition),
            .captured_ltssm_state_o     (p0_captured_ltssm_state)
        );
		  
	assign p0_ltssm_fifo_wrreq = (~p0_ltssm_fifo_wrfull && (p0_state_transition));
	assign p0_ltssm_fifo_rdreq = (!p0_ltssm_fifo_rdempty & (avmm_read & !avmm_read_r) & (avmm_address[3:0] == 4'b0010));
      
	dcfifo ltssm_fifo_p0_pcie (
            .aclr 	(ninit_done),
            .data 	({p0_ltssm_counter_value,p0_captured_ltssm_state}),
            .rdclk 	(avmm_clk),
            .rdreq 	(p0_ltssm_fifo_rdreq),
            .wrclk 	(hip_coreclk),
            .wrreq 	(p0_ltssm_fifo_wrreq),
            .q 		(p0_ltssm_fifo_q),
            .rdempty 	(p0_ltssm_fifo_rdempty),
            .rdfull 	(p0_ltssm_fifo_rdfull), //for FIFO rdfull status
            .rdusedw 	(p0_ltssm_fifo_rdusedw),
            .wrempty 	(p0_ltssm_fifo_wrempty),
            .wrfull 	(p0_ltssm_fifo_wrfull)
	);
   
	defparam
            ltssm_fifo_p0_pcie.intended_device_family  = "Agilex 5",
            ltssm_fifo_p0_pcie.lpm_numwords  = 1024,
            ltssm_fifo_p0_pcie.lpm_showahead  = "OFF",
            ltssm_fifo_p0_pcie.lpm_type  = "dcfifo",
            ltssm_fifo_p0_pcie.lpm_width  = 32,
            ltssm_fifo_p0_pcie.lpm_widthu  = 10,
            ltssm_fifo_p0_pcie.overflow_checking  = "OFF",
            ltssm_fifo_p0_pcie.rdsync_delaypipe  = 4,
            ltssm_fifo_p0_pcie.read_aclr_synch  = "ON",
            ltssm_fifo_p0_pcie.underflow_checking  = "OFF",
            ltssm_fifo_p0_pcie.use_eab  = "ON",
            ltssm_fifo_p0_pcie.write_aclr_synch  = "ON",
            ltssm_fifo_p0_pcie.wrsync_delaypipe  = 4,
	    ltssm_fifo_p0_pcie.lpm_hint = "DISABLE_DCFIFO_EMBEDDED_TIMING_CONSTRAINT=TRUE";    

	always_ff @ (posedge avmm_clk) begin
	    case (avmm_address)
		4'b0010: avmm_readdata_r <= p0_ltssm_fifo_q;
		4'b0011: avmm_readdata_r <= {20'h0, p0_ltssm_fifo_rdempty, p0_ltssm_fifo_rdfull, p0_ltssm_fifo_rdusedw};
		default: avmm_readdata_r <= 32'h0; //outside of 20_0000-9F_FFFF
	    endcase
	end 
		
	assign p1_ltssm_counter_value 	= 0;
        assign p1_state_transition     	= 0;      
        assign p1_captured_ltssm_state	= 0;    		

    end else if (core16_func_mode_hwtcl=="Disable" && core8_func_mode_hwtcl=="Enable") begin : PCIE_P1
        ltssm_monitor # (
	    .LTSSM_COUNTER_WIDTH 	(LTSSM_COUNTER_WIDTH)
	) ltssm_counter_p1_pcie (
            .clk                        (hip_coreclk),
            .ninit_done                 (ninit_done),
	    .ltssm_state_i              (p1_ltssm_state),
            .ltssm_counter_value_o      (p1_ltssm_counter_value),
            .state_transition_o         (p1_state_transition),
            .captured_ltssm_state_o     (p1_captured_ltssm_state)
        );
		  
	assign p1_ltssm_fifo_wrreq = (~p1_ltssm_fifo_wrfull && (p1_state_transition));
	assign p1_ltssm_fifo_rdreq = (!p1_ltssm_fifo_rdempty & (avmm_read & !avmm_read_r) & (avmm_address[3:0] == 4'b0010));
      
	dcfifo ltssm_fifo_p1_pcie (
            .aclr 	(ninit_done),
            .data 	({p1_ltssm_counter_value,p1_captured_ltssm_state}),
            .rdclk 	(avmm_clk),
            .rdreq 	(p1_ltssm_fifo_rdreq),
            .wrclk 	(hip_coreclk),
            .wrreq 	(p1_ltssm_fifo_wrreq),
            .q 		(p1_ltssm_fifo_q),
            .rdempty 	(p1_ltssm_fifo_rdempty),
            .rdfull 	(p1_ltssm_fifo_rdfull), //for FIFO rdfull status
            .rdusedw 	(p1_ltssm_fifo_rdusedw),
            .wrempty 	(p1_ltssm_fifo_wrempty),
            .wrfull 	(p1_ltssm_fifo_wrfull)
	);
   
	defparam
            ltssm_fifo_p1_pcie.intended_device_family  = "Agilex 5",
            ltssm_fifo_p1_pcie.lpm_numwords  = 1024,
            ltssm_fifo_p1_pcie.lpm_showahead  = "OFF",
            ltssm_fifo_p1_pcie.lpm_type  = "dcfifo",
            ltssm_fifo_p1_pcie.lpm_width  = 32,
            ltssm_fifo_p1_pcie.lpm_widthu  = 10,
            ltssm_fifo_p1_pcie.overflow_checking  = "OFF",
            ltssm_fifo_p1_pcie.rdsync_delaypipe  = 4,
            ltssm_fifo_p1_pcie.read_aclr_synch  = "ON",
            ltssm_fifo_p1_pcie.underflow_checking  = "OFF",
            ltssm_fifo_p1_pcie.use_eab  = "ON",
            ltssm_fifo_p1_pcie.write_aclr_synch  = "ON",
	    ltssm_fifo_p1_pcie.lpm_hint = "DISABLE_DCFIFO_EMBEDDED_TIMING_CONSTRAINT=TRUE",
            ltssm_fifo_p1_pcie.wrsync_delaypipe  = 4;		

	always_ff @ (posedge avmm_clk) begin
	    case (avmm_address)
		4'b0010: avmm_readdata_r <= p1_ltssm_fifo_q;
		4'b0011: avmm_readdata_r <= {20'h0, p1_ltssm_fifo_rdempty, p1_ltssm_fifo_rdfull, p1_ltssm_fifo_rdusedw};
		default: avmm_readdata_r <= 32'h0; //outside of 20_0000-9F_FFFF
	    endcase
	end 
		
	assign p0_ltssm_counter_value 	= 0;
        assign p0_state_transition     	= 0;      
        assign p0_captured_ltssm_state	= 0;  
	      
    end else begin : PCIE_P0P1
        ltssm_monitor # (
	    .LTSSM_COUNTER_WIDTH 	   (LTSSM_COUNTER_WIDTH)
	) ltssm_counter_p0_pcie (
            .clk                           (hip_coreclk),
            .ninit_done                    (ninit_done),
	    .ltssm_state_i                 (p0_ltssm_state),
            .ltssm_counter_value_o         (p0_ltssm_counter_value),
            .state_transition_o            (p0_state_transition),
            .captured_ltssm_state_o        (p0_captured_ltssm_state)
        );
      
	assign p0_ltssm_fifo_wrreq = (~p0_ltssm_fifo_wrfull && (p0_state_transition));
	assign p0_ltssm_fifo_rdreq = (!p0_ltssm_fifo_rdempty & (avmm_read & !avmm_read_r) & (avmm_address[3:0] == 4'b0010));
      
	dcfifo  ltssm_fifo_p0_pcie (
            .aclr 	(ninit_done),
            .data 	({p0_ltssm_counter_value,p0_captured_ltssm_state}),
            .rdclk 	(avmm_clk),
            .rdreq 	(p0_ltssm_fifo_rdreq),
            .wrclk 	(hip_coreclk),
            .wrreq 	(p0_ltssm_fifo_wrreq),
            .q 		(p0_ltssm_fifo_q),
            .rdempty 	(p0_ltssm_fifo_rdempty),
            .rdfull 	(p0_ltssm_fifo_rdfull), //for FIFO rdfull status
            .rdusedw 	(p0_ltssm_fifo_rdusedw),
            .wrempty 	(p0_ltssm_fifo_wrempty),
            .wrfull 	(p0_ltssm_fifo_wrfull)
	);
			
	defparam
            ltssm_fifo_p0_pcie.intended_device_family  = "Agilex 5",
            ltssm_fifo_p0_pcie.lpm_numwords  = 1024,
            ltssm_fifo_p0_pcie.lpm_showahead  = "OFF",
            ltssm_fifo_p0_pcie.lpm_type  = "dcfifo",
            ltssm_fifo_p0_pcie.lpm_width  = 32,
            ltssm_fifo_p0_pcie.lpm_widthu  = 10,
            ltssm_fifo_p0_pcie.overflow_checking  = "OFF",
            ltssm_fifo_p0_pcie.rdsync_delaypipe  = 4,
            ltssm_fifo_p0_pcie.read_aclr_synch  = "ON",
            ltssm_fifo_p0_pcie.underflow_checking  = "OFF",
            ltssm_fifo_p0_pcie.use_eab  = "ON",
            ltssm_fifo_p0_pcie.write_aclr_synch  = "ON",
	    ltssm_fifo_p0_pcie.lpm_hint = "DISABLE_DCFIFO_EMBEDDED_TIMING_CONSTRAINT=TRUE",
            ltssm_fifo_p0_pcie.wrsync_delaypipe  = 4;		

        ltssm_monitor # (
   	    .LTSSM_COUNTER_WIDTH 	   (LTSSM_COUNTER_WIDTH)
	) ltssm_counter_p1_pcie (
            .clk                           (hip_coreclk),
            .ninit_done                    (ninit_done),
            .ltssm_state_i                 (p1_ltssm_state),
            .ltssm_counter_value_o         (p1_ltssm_counter_value),
            .state_transition_o            (p1_state_transition),
            .captured_ltssm_state_o        (p1_captured_ltssm_state)
        );
      
	assign p1_ltssm_fifo_wrreq = (~p1_ltssm_fifo_wrfull && (p1_state_transition));
	assign p1_ltssm_fifo_rdreq = (!p1_ltssm_fifo_rdempty & (avmm_read & !avmm_read_r) & (avmm_address[3:0] == 4'b0100));
      
	dcfifo  ltssm_fifo_p1_pcie (
            .aclr 	(ninit_done),
            .data 	({p1_ltssm_counter_value,p1_captured_ltssm_state}),
            .rdclk 	(avmm_clk),
            .rdreq 	(p1_ltssm_fifo_rdreq),
            .wrclk 	(hip_coreclk),
            .wrreq 	(p1_ltssm_fifo_wrreq),
            .q 		(p1_ltssm_fifo_q),
            .rdempty 	(p1_ltssm_fifo_rdempty),
            .rdfull 	(p1_ltssm_fifo_rdfull), //for FIFO rdfull status
            .rdusedw 	(p1_ltssm_fifo_rdusedw),
            .wrempty 	(p1_ltssm_fifo_wrempty),
            .wrfull 	(p1_ltssm_fifo_wrfull)
	);       

	defparam
            ltssm_fifo_p1_pcie.intended_device_family  = "Agilex 5",
            ltssm_fifo_p1_pcie.lpm_numwords  = 1024,
            ltssm_fifo_p1_pcie.lpm_showahead  = "OFF",
            ltssm_fifo_p1_pcie.lpm_type  = "dcfifo",
            ltssm_fifo_p1_pcie.lpm_width  = 32,
            ltssm_fifo_p1_pcie.lpm_widthu  = 10,
            ltssm_fifo_p1_pcie.overflow_checking  = "OFF",
            ltssm_fifo_p1_pcie.rdsync_delaypipe  = 4,
            ltssm_fifo_p1_pcie.read_aclr_synch  = "ON",
            ltssm_fifo_p1_pcie.underflow_checking  = "OFF",
            ltssm_fifo_p1_pcie.use_eab  = "ON",
            ltssm_fifo_p1_pcie.write_aclr_synch  = "ON",
	    ltssm_fifo_p1_pcie.lpm_hint = "DISABLE_DCFIFO_EMBEDDED_TIMING_CONSTRAINT=TRUE",
            ltssm_fifo_p1_pcie.wrsync_delaypipe  = 4;	

	always_ff @ (posedge avmm_clk) begin
	    case (avmm_address)
		4'b0010: avmm_readdata_r <= p0_ltssm_fifo_q;
                4'b0011: avmm_readdata_r <= {20'h0, p0_ltssm_fifo_rdempty, p0_ltssm_fifo_rdfull, p0_ltssm_fifo_rdusedw};
		4'b0100: avmm_readdata_r <= p1_ltssm_fifo_q;
                4'b0111: avmm_readdata_r <= {20'h0, p1_ltssm_fifo_rdempty, p1_ltssm_fifo_rdfull, p1_ltssm_fifo_rdusedw};
		default: avmm_readdata_r <= 32'h0; //outside of 20_0000-9F_FFFF
	    endcase
	end 

    end
  endgenerate

endmodule

`ifdef QUESTA_INTEL_OEM
`pragma questa_oem_00 "PNVV7/bs9iBHIRlA5ZBsyN/GPZ0TXi6qn2Dh2M7pAeu7gJ2ZBA7h3JGkvjXkuC5UIXo/z5gQmp1UZ7sTAaTT/jY49W2SxnQK1Yi3m9AqA7DQvdVNQSIP0StiA6cd/Bmb1xOyX01r0Q1kSbh1Xg00173NRrSBh6I2laKRBqIVNUuwBG6+CnWpVjqQa+TAR5sCjTNP+I8jQLtXq7doP9+lP7YXqXhRmwId5c9JhVEr4Vmb96ScirxIcqsBAXCOxUa/zHA26x5Pla7RIiaHfgJ+zlQ9CRihIACNY4Akm3QU98CqXpXuITAZpdb+M+4lgrYbNg5TQc4w1fAwlBdSh4Gti2rfodp4eW9E4NvRvhtPWWWEwsy0cZp98rk2UKDLhn3hg9hcRNvC5WO7zAbZEg6en8g3qPmfICmZB1HA4A+7WIVFuoqO4X1NeH/i7xt3RYGkKKEd72PcBzx4pd+jASrEWvR+AJBkxZOxMB68wQ4NkF/R2BBEtQRUyJyDpMJod2C1CMZnwhGyyOIc4n7SYqlCz9FvugL/YmXvKR2g/NTNHKJdu+N3TNLB3vXmhWM6ao12z6Bnrk0ubQN8AnUaZL4ITKQpJ5T0zMmYALffnkB+7Q71/5KJQwNWjmoNP+2Qf5Wt8FfyB/3lel9qGAM1V/F80bPXxi9MCzNokazBpKdHOM3khYr+AMfzF/LAlflyggXFpdLl32caja9YmaTIMP5Wdwcg7YkUjH0oEWeUdI16sYMZV3EIIJlUrJmYhOUtrITSrrkRI6IyJQwM161CNjr6fBK3Vh2zbEiBbRKdXQi4al5BVekjpyZDCQKZAFESUqBes6YuZvfzwQO+WV65sHviItPytJ0aw84ozEveIcVkAK7bO9k2HZ+1LStWhTErdr5UxvlOQRmFX5EOfgrsSsgj3Dj/piDAVPc98sz/MpGhKtbz9Z6h5KemTcJV3yRJ48waXMkhzU44GMfyf49RoyvGjvF88pV3h3yPyzIg+16fykX2BLLU+aRSY1K2yippT5XR"
`endif