module csrFiles (

	//from csr exe
	input [11:0] csrexe_addr,
	input [63:0] op,
	output [63:0] csrexe_res,
	input rw,
	input rs,
	input rc,





	//from privileged
	input isTrap,
	input isXRet,
	input [63:0] mstatus_except_in,
	input [63:0] mtval_except_in,
	input [63:0] mcause_except_in,
	input [63:0] mepc_except_in,

	output [63:0] mstatus_csr_out,
	output [63:0] mip_csr_out,
	output [63:0] mie_csr_out,
	output [63:0] mepc_csr_out,
	output [63:0] mtvec_csr_out,

	//from outside

	input isExternInterrupt,
	input isRTimerInterrupt,
	input isSoftwvInterrupt,

	input CLK,
	input RSTn
);

wire [63:0] mstatus_qout;

wire [31:0] mvendorid;
wire [63:0] marchid;
wire [63:0] mimpid;
wire [63:0] mhartid;
wire [63:0] mstatus;
wire [63:0] misa;
wire [63:0] medeleg;
wire [63:0] mideleg;
wire [63:0] mie;
wire [63:0] mtvec;
wire [63:0] mcounteren;
wire [63:0] mstatush;
wire [63:0] mscratch;
wire [63:0] mepc;
wire [63:0] mcause;
wire [63:0] mtval;
wire [63:0] mip;
wire [63:0] mcycle;
wire [63:0] minstret;
wire [63:0] mhpmcounter3;
wire [63:0] dcsr;
wire [63:0] dpc;
wire [63:0] dscratch0;
wire [63:0] dscratch1;



assign mstatus_csr_out = mstatus;
assign mie_csr_out = mie;
assign mip_csr_out = mip;
assign mepc_csr_out = mepc;
assign mtvec_csr_out = mtvec;



// Machine Information Registers

//0xF11
assign mvendorid = 32'd0;
//0xf12
assign marchid = 64'd0;
//0xf13
assign mimpid = 64'd0;
//0xf14
assign mhartid = 64'd0;


//Machine Trap Setup

//0x300
gen_csrreg #(.CSRADDR(12'h300)) mstatus_csrreg
( .privi_data(mstatus_except_in), .isPrivi(isTrap | isXRet),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mstatus_qout), .CLK(CLK), .RSTn(RSTn)
);

assign mstatus = mstatus_qout | 64'h1800;


//0x301
assign misa = {2'b10,36'b0,26'b00000000000001000100000100};

//0x302
gen_csrreg #(.CSRADDR(12'h302)) medeleg_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(medeleg), .CLK(CLK), .RSTn(RSTn)
);

//0x303
gen_csrreg #(.CSRADDR(12'h303)) mideleg_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mideleg), .CLK(CLK), .RSTn(RSTn)
);

//0x304
gen_csrreg #(.CSRADDR(12'h304)) mie_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mie), .CLK(CLK), .RSTn(RSTn)
);

//0x305
gen_csrreg #(.CSRADDR(12'h305)) mtvec_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mtvec), .CLK(CLK), .RSTn(RSTn)
);

//0x306
gen_csrreg #(.CSRADDR(12'h306)) mcounteren_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mcounteren), .CLK(CLK), .RSTn(RSTn)
);

//0x310
gen_csrreg #(.CSRADDR(12'h310)) mstatush_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mstatush), .CLK(CLK), .RSTn(RSTn)
);

//Machine Trap Handling

//0x340
gen_csrreg #(.CSRADDR(12'h340)) mscratch_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mscratch), .CLK(CLK), .RSTn(RSTn)
);

//0x341
gen_csrreg #(.CSRADDR(12'h341)) mepc_csrreg
( .privi_data(mepc_except_in), .isPrivi(isTrap),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mepc), .CLK(CLK), .RSTn(RSTn)
);

//0x342
gen_csrreg #(.CSRADDR(12'h342)) mcause_csrreg
( .privi_data(mcause_except_in), .isPrivi(isTrap),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mcause), .CLK(CLK), .RSTn(RSTn)
);

//0x343
gen_csrreg #(.CSRADDR(12'h343)) mtval_csrreg
( .privi_data(mtval_except_in), .isPrivi(isTrap),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mtval), .CLK(CLK), .RSTn(RSTn)
);

//0x344
assign mip = isExternInterrupt << 11 | isRTimerInterrupt << 7 | isSoftwvInterrupt << 3;

//Machine Memory Protection

//Machine Counter/Timer

//0xb00
gen_csrreg #(.CSRADDR(12'hb00)) mcycle_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mcycle), .CLK(CLK), .RSTn(RSTn)
);

//0xb02
gen_csrreg #(.CSRADDR(12'hb02)) minstret_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(minstret), .CLK(CLK), .RSTn(RSTn)
);

//0xb03
gen_csrreg #(.CSRADDR(12'hb03)) mhpmcounter3_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(mhpmcounter3), .CLK(CLK), .RSTn(RSTn)
);


//Machine Counter Setup

//Debug/Trace Register

//Debug Mode Register

//0x7b0
gen_csrreg #(.CSRADDR(12'h7b0)) dcsr_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(dcsr), .CLK(CLK), .RSTn(RSTn)
);

//0x7b1
gen_csrreg #(.CSRADDR(12'h7b1)) dpc_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(dpc), .CLK(CLK), .RSTn(RSTn)
);

//0x7b2
gen_csrreg #(.CSRADDR(12'h7b2)) dscratch0_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(dscratch0), .CLK(CLK), .RSTn(RSTn)
);

//0x7b3
gen_csrreg #(.CSRADDR(12'h7b3)) dscratch1_csrreg
( .privi_data(64'b0), .isPrivi(1'b0),
	.csr_op(op), .addr(csrexe_addr), .rw(rw), .rs(rs), .rc(rc),
	.qout(dscratch1), .CLK(CLK), .RSTn(RSTn)
);






assign csrexe_res = ({64{csrexe_addr == 12'hF11}} & {32'b0,mvendorid})
					|
					({64{csrexe_addr == 12'hF12}} & marchid)
					|
					({64{csrexe_addr == 12'hF13}} & mimpid)
					|
					({64{csrexe_addr == 12'hF14}} & mhartid)
					|
					({64{csrexe_addr == 12'h300}} & mstatus)
					|
					({64{csrexe_addr == 12'h301}} & misa)
					|
					({64{csrexe_addr == 12'h304}} & mie)
					|
					({64{csrexe_addr == 12'h340}} & mscratch)
					|
					({64{csrexe_addr == 12'h305}} & mtvec)
					|
					({64{csrexe_addr == 12'h341}} & mepc)
					|
					({64{csrexe_addr == 12'h342}} & mcause)
					|
					({64{csrexe_addr == 12'h343}} & mtval)
					|
					({64{csrexe_addr == 12'h344}} & mip)
					;




endmodule