/*
 -- ============================================================================
 -- FILE NAME	: ex_reg.v
 -- DESCRIPTION : EXXe[WpCvCWX^
 -- ----------------------------------------------------------------------------
 -- Revision  Date		  Coding_by	 Comment
 -- 1.0.0	  2011/06/27  suito		 VKì¬
 -- ============================================================================
*/

/********** ¤Êwb_t@C **********/
`include "nettype.h"
`include "global_config.h"
`include "stddef.h"

/********** ÂÊwb_t@C **********/
`include "isa.h"
`include "cpu.h"

/********** W[ **********/
module ex_reg (
	/********** NbN & Zbg **********/
	input  wire				   clk,			   // NbN
	input  wire				   reset,		   // ñ¯úZbg
	/********** ALUÌoÍ **********/
	input  wire [`WordDataBus] alu_out,		   // ZÊ
	input  wire				   alu_of,		   // I[ot[
	/********** pCvC§äM **********/
	input  wire				   stall,		   // Xg[
	input  wire				   flush,		   // tbV
	input  wire				   int_detect,	   // èÝo
	/********** ID/EXpCvCWX^ **********/
	input  wire [`WordAddrBus] id_pc,		   // vOJE^
	input  wire				   id_en,		   // pCvCf[^ÌLø
	input  wire				   id_br_flag,	   // ªòtO
	input  wire [`MemOpBus]	   id_mem_op,	   // Iy[V
	input  wire [`WordDataBus] id_mem_wr_data, // «Ýf[^
	input  wire [`CtrlOpBus]   id_ctrl_op,	   // §äWX^Iy[V
	input  wire [`RegAddrBus]  id_dst_addr,	   // ÄpWX^«ÝAhX
	input  wire				   id_gpr_we_,	   // ÄpWX^«ÝLø
	input  wire [`IsaExpBus]   id_exp_code,	   // áOR[h
	/********** EX/MEMpCvCWX^ **********/
	output reg	[`WordAddrBus] ex_pc,		   // vOJE^
	output reg				   ex_en,		   // pCvCf[^ÌLø
	output reg				   ex_br_flag,	   // ªòtO
	output reg	[`MemOpBus]	   ex_mem_op,	   // Iy[V
	output reg	[`WordDataBus] ex_mem_wr_data, // «Ýf[^
	output reg	[`CtrlOpBus]   ex_ctrl_op,	   // §äWX^Iy[V
	output reg	[`RegAddrBus]  ex_dst_addr,	   // ÄpWX^«ÝAhX
	output reg				   ex_gpr_we_,	   // ÄpWX^«ÝLø
	output reg	[`IsaExpBus]   ex_exp_code,	   // áOR[h
	output reg	[`WordDataBus] ex_out		   // Ê
);

	/********** pCvCWX^ **********/
	always @(posedge clk or `RESET_EDGE reset) begin
		/* ñ¯úZbg */
		if (reset == `RESET_ENABLE) begin 
			ex_pc		   <= #1 `WORD_ADDR_W'h0;
			ex_en		   <= #1 `DISABLE;
			ex_br_flag	   <= #1 `DISABLE;
			ex_mem_op	   <= #1 `MEM_OP_NOP;
			ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
			ex_ctrl_op	   <= #1 `CTRL_OP_NOP;
			ex_dst_addr	   <= #1 `REG_ADDR_W'd0;
			ex_gpr_we_	   <= #1 `DISABLE_;
			ex_exp_code	   <= #1 `ISA_EXP_NO_EXP;
			ex_out		   <= #1 `WORD_DATA_W'h0;
		end else begin
			/* pCvCWX^ÌXV */
			if (stall == `DISABLE) begin 
				if (flush == `ENABLE) begin				  // tbV
					ex_pc		   <= #1 `WORD_ADDR_W'h0;
					ex_en		   <= #1 `DISABLE;
					ex_br_flag	   <= #1 `DISABLE;
					ex_mem_op	   <= #1 `MEM_OP_NOP;
					ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
					ex_ctrl_op	   <= #1 `CTRL_OP_NOP;
					ex_dst_addr	   <= #1 `REG_ADDR_W'd0;
					ex_gpr_we_	   <= #1 `DISABLE_;
					ex_exp_code	   <= #1 `ISA_EXP_NO_EXP;
					ex_out		   <= #1 `WORD_DATA_W'h0;
				end else if (int_detect == `ENABLE) begin // èÝÌo
					ex_pc		   <= #1 id_pc;
					ex_en		   <= #1 id_en;
					ex_br_flag	   <= #1 id_br_flag;
					ex_mem_op	   <= #1 `MEM_OP_NOP;
					ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
					ex_ctrl_op	   <= #1 `CTRL_OP_NOP;
					ex_dst_addr	   <= #1 `REG_ADDR_W'd0;
					ex_gpr_we_	   <= #1 `DISABLE_;
					ex_exp_code	   <= #1 `ISA_EXP_EXT_INT;
					ex_out		   <= #1 `WORD_DATA_W'h0;
				end else if (alu_of == `ENABLE) begin	  // ZpI[ot[
					ex_pc		   <= #1 id_pc;
					ex_en		   <= #1 id_en;
					ex_br_flag	   <= #1 id_br_flag;
					ex_mem_op	   <= #1 `MEM_OP_NOP;
					ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
					ex_ctrl_op	   <= #1 `CTRL_OP_NOP;
					ex_dst_addr	   <= #1 `REG_ADDR_W'd0;
					ex_gpr_we_	   <= #1 `DISABLE_;
					ex_exp_code	   <= #1 `ISA_EXP_OVERFLOW;
					ex_out		   <= #1 `WORD_DATA_W'h0;
				end else begin							  // Ìf[^
					ex_pc		   <= #1 id_pc;
					ex_en		   <= #1 id_en;
					ex_br_flag	   <= #1 id_br_flag;
					ex_mem_op	   <= #1 id_mem_op;
					ex_mem_wr_data <= #1 id_mem_wr_data;
					ex_ctrl_op	   <= #1 id_ctrl_op;
					ex_dst_addr	   <= #1 id_dst_addr;
					ex_gpr_we_	   <= #1 id_gpr_we_;
					ex_exp_code	   <= #1 id_exp_code;
					ex_out		   <= #1 alu_out;
				end
			end
		end
	end

endmodule
