module csr_indexed_read_only_reg #(
	parameter groups = 2,
	parameter grp_size = 1,
	parameter sel_size = 1,
	parameter sync_stages = 2
)
(
	input  wire clk,
	input  tri0 [sel_size-1:0]			sel,
	output wire [grp_size-1:0]			out_narrow, // for read back to mgmt interface
	input  wire [groups*grp_size-1:0]	async_in_wide	// full-width async status inputs
);
  localparam sync_stages_str  = sync_stages[7:0] + 8'd48; // number of sync stages specified as string (for timing constraints)
  localparam SYNC_SREG_CONSTRAINT = {"-name SDC_STATEMENT \"set regs [get_registers -nowarn *csr_indexed_read_only_reg*sreg[",sync_stages_str,"]*]; if {[llength [query_collection -report -all $regs]] > 0} {set_false_path -to $regs}\""};
  localparam SDC_CONSTRAINTS = {SYNC_SREG_CONSTRAINT};

	// read-only status registers are synchronized forms of async status signals
	// async inputs go to sreg [sync_stages], and come out synchronized at sreg [1]
  // Apply false path timing constraints to synchronization registers.
  (* altera_attribute = SDC_CONSTRAINTS *)
	reg  [groups*grp_size-1:0]	sreg [sync_stages:1];
	integer stage;
	always @(posedge clk) begin
		sreg[sync_stages] <= async_in_wide;
		for (stage=2; stage <= sync_stages; stage = stage + 1) begin
			// additional sync stages
			sreg[stage-1] <= sreg[stage];
		end
	end

	// generate out_narrow as ordinary mux of out_wide
	csr_mux #(.groups(groups), .grp_size(grp_size), .sel_size(sel_size))
		o_narrow(.in_wide(sreg[1]), .sel(sel), .out_narrow(out_narrow));

endmodule