module or1200_if_cm4(
		clk_i_cml_1,
		clk_i_cml_2,
		clk_i_cml_3,
		
	// Clock and reset
	clk, rst,

	// External i/f to IC
	icpu_dat_i, icpu_ack_i, icpu_err_i, icpu_adr_i, icpu_tag_i,

	// Internal i/f
	if_freeze, if_insn, if_pc, flushpipe,
	if_stall, no_more_dslot, genpc_refetch, rfe,
	except_itlbmiss, except_immufault, except_ibuserr
);


input clk_i_cml_1;
input clk_i_cml_2;
input clk_i_cml_3;
reg  icpu_ack_i_cml_3;
reg  icpu_ack_i_cml_2;
reg  icpu_err_i_cml_3;
reg [ 31 : 0 ] icpu_adr_i_cml_3;
reg [ 31 : 0 ] icpu_adr_i_cml_2;
reg [ 31 : 0 ] icpu_adr_i_cml_1;
reg  no_more_dslot_cml_3;
reg  no_more_dslot_cml_2;
reg [ 31 : 0 ] insn_saved_cml_3;
reg [ 31 : 0 ] insn_saved_cml_2;
reg [ 31 : 0 ] insn_saved_cml_1;
reg [ 31 : 0 ] addr_saved_cml_3;
reg [ 31 : 0 ] addr_saved_cml_2;
reg [ 31 : 0 ] addr_saved_cml_1;
reg  saved_cml_3;
reg  saved_cml_2;
reg  saved_cml_1;



//
// I/O
//

//
// Clock and reset
//
input				clk;
input				rst;

//
// External i/f to IC
//
input	[31:0]			icpu_dat_i;
input				icpu_ack_i;
input				icpu_err_i;
input	[31:0]			icpu_adr_i;
input	[3:0]			icpu_tag_i;

//
// Internal i/f
//
input				if_freeze;
output	[31:0]			if_insn;
output	[31:0]			if_pc;
input				flushpipe;
output				if_stall;
input				no_more_dslot;
output				genpc_refetch;
input				rfe;
output				except_itlbmiss;
output				except_immufault;
output				except_ibuserr;

//
// Internal wires and regs
//
reg	[31:0]			insn_saved;
reg	[31:0]			addr_saved;
reg				saved;

//
// IF stage insn
//

// SynEDA CoreMultiplier
// assignment(s): if_insn
// replace(s): icpu_ack_i, icpu_err_i, no_more_dslot, insn_saved, saved
assign if_insn = icpu_err_i_cml_3 | no_more_dslot_cml_3 | rfe ? {`OR1200_OR32_NOP, 26'h041_0000} : saved_cml_3 ? insn_saved_cml_3 : icpu_ack_i_cml_3 ? icpu_dat_i : {`OR1200_OR32_NOP, 26'h061_0000};

// SynEDA CoreMultiplier
// assignment(s): if_pc
// replace(s): icpu_adr_i, addr_saved, saved
assign if_pc = saved_cml_3 ? addr_saved_cml_3 : icpu_adr_i_cml_3;
// assign if_stall = !icpu_err_i & !icpu_ack_i & !saved & !no_more_dslot;

// SynEDA CoreMultiplier
// assignment(s): if_stall
// replace(s): icpu_ack_i, saved
assign if_stall = !icpu_err_i & !icpu_ack_i_cml_2 & !saved_cml_2;

// SynEDA CoreMultiplier
// assignment(s): genpc_refetch
// replace(s): saved
assign genpc_refetch = saved_cml_1 & icpu_ack_i;

// SynEDA CoreMultiplier
// assignment(s): except_itlbmiss
// replace(s): icpu_err_i, no_more_dslot
assign except_itlbmiss = icpu_err_i_cml_3 & (icpu_tag_i == `OR1200_ITAG_TE) & !no_more_dslot_cml_3;

// SynEDA CoreMultiplier
// assignment(s): except_immufault
// replace(s): icpu_err_i, no_more_dslot
assign except_immufault = icpu_err_i_cml_3 & (icpu_tag_i == `OR1200_ITAG_PE) & !no_more_dslot_cml_3;

// SynEDA CoreMultiplier
// assignment(s): except_ibuserr
// replace(s): icpu_err_i, no_more_dslot
assign except_ibuserr = icpu_err_i_cml_3 & (icpu_tag_i == `OR1200_ITAG_BE) & !no_more_dslot_cml_3;

//
// Flag for saved insn/address
//

// SynEDA CoreMultiplier
// assignment(s): saved
// replace(s): icpu_ack_i, saved
always @(posedge clk or posedge rst)
	if (rst)
		saved <= #1 1'b0;
	else begin  saved <= saved_cml_3; if (flushpipe)
		saved <= #1 1'b0;
	else if (icpu_ack_i_cml_3 & if_freeze & !saved_cml_3)
		saved <= #1 1'b1;
	else if (!if_freeze)
		saved <= #1 1'b0; end

//
// Store fetched instruction
//

// SynEDA CoreMultiplier
// assignment(s): insn_saved
// replace(s): icpu_ack_i, insn_saved, saved
always @(posedge clk or posedge rst)
	if (rst)
		insn_saved <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
	else begin  insn_saved <= insn_saved_cml_3; if (flushpipe)
		insn_saved <= #1 {`OR1200_OR32_NOP, 26'h041_0000};
	else if (icpu_ack_i_cml_3 & if_freeze & !saved_cml_3)
		insn_saved <= #1 icpu_dat_i;
	else if (!if_freeze)
		insn_saved <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; end

//
// Store fetched instruction's address
//

// SynEDA CoreMultiplier
// assignment(s): addr_saved
// replace(s): icpu_ack_i, icpu_adr_i, addr_saved, saved
always @(posedge clk or posedge rst)
	if (rst)
		addr_saved <= #1 32'h00000000;
	else begin  addr_saved <= addr_saved_cml_3; if (flushpipe)
		addr_saved <= #1 32'h00000000;
	else if (icpu_ack_i_cml_3 & if_freeze & !saved_cml_3)
		addr_saved <= #1 icpu_adr_i_cml_3;
	else if (!if_freeze)
		addr_saved <= #1 icpu_adr_i_cml_3; end


always @ (posedge clk_i_cml_1) begin
icpu_adr_i_cml_1 <= icpu_adr_i;
insn_saved_cml_1 <= insn_saved;
addr_saved_cml_1 <= addr_saved;
saved_cml_1 <= saved;
end
always @ (posedge clk_i_cml_2) begin
icpu_ack_i_cml_2 <= icpu_ack_i;
icpu_adr_i_cml_2 <= icpu_adr_i_cml_1;
no_more_dslot_cml_2 <= no_more_dslot;
insn_saved_cml_2 <= insn_saved_cml_1;
addr_saved_cml_2 <= addr_saved_cml_1;
saved_cml_2 <= saved_cml_1;
end
always @ (posedge clk_i_cml_3) begin
icpu_ack_i_cml_3 <= icpu_ack_i_cml_2;
icpu_err_i_cml_3 <= icpu_err_i;
icpu_adr_i_cml_3 <= icpu_adr_i_cml_2;
no_more_dslot_cml_3 <= no_more_dslot_cml_2;
insn_saved_cml_3 <= insn_saved_cml_2;
addr_saved_cml_3 <= addr_saved_cml_2;
saved_cml_3 <= saved_cml_2;
end
endmodule