dakies/OSS_Verilog huggingface dataset:
module issue_buffer #
(
	parameter DW = 100,
	parameter DP = 8
)


(

	input [ DW - 1 : 0] dispat_info,
	input buffer_push,
	output buffer_full,


	input buffer_pop,
	input [$clog2(DP)-1:0] pop_index,
	output [ DW*DP - 1 : 0] issue_info_qout,
	output [DP - 1 : 0] buffer_malloc_qout,
	
	input flush,
	input CLK,
	input RSTn
	
);



	wire [ DW*DP - 1 : 0] issue_info_dnxt;
	wire [$clog2(DP)-1:0] issue_push_index_pre;
	wire [$clog2(DP)-1:0] issue_push_index = (buffer_pop & buffer_push) ? pop_index : issue_push_index_pre;
	wire [DP-1:0] buffer_valid_dnxt;
	wire [DP-1:0] buffer_valid_qout;
	assign buffer_malloc_qout = buffer_valid_qout;

	generate
		for ( genvar dp = 0; dp < DP; dp = dp + 1 ) begin

			assign issue_info_dnxt[DW*dp +: DW] = buffer_push & ( dp == issue_push_index )
												? dispat_info
												: issue_info_qout[DW*dp +: DW];

			gen_dffr #(.DW(DW)) issue_info ( .dnxt(issue_info_dnxt[DW*dp +: DW]), .qout(issue_info_qout[DW*dp +: DW]), .CLK(CLK), .RSTn(RSTn) );

		end
	endgenerate




	gen_dffr #(.DW(DP)) buffer_valid ( .dnxt(buffer_valid_dnxt), .qout(buffer_valid_qout), .CLK(CLK), .RSTn(RSTn) );

	assign buffer_valid_dnxt = flush ? {DP{1'b0}} : (( 
														{DP{(buffer_pop & buffer_push) | (~buffer_pop & ~buffer_push)}}
														& buffer_valid_qout
													)
													| 
													( 
														{DP{(buffer_push & ~buffer_pop) }}
														& (buffer_valid_qout | (1'b1 << issue_push_index_pre))
													) 
													| 
													( 
														{DP{(~buffer_push & buffer_pop)}}
														& (buffer_valid_qout & ~(1'b1 << pop_index))
													));

	

	lzp #(
		.CW($clog2(DP))
	) empty_buffer(
		.in_i(buffer_valid_qout),
		.pos_o(issue_push_index_pre),
		.all0(),
		.all1(buffer_full)
	);














endmodule
module mul_issue #(
	parameter DW = `MUL_ISSUE_INFO_DW,
	parameter DP = `MUL_ISSUE_INFO_DP,
	parameter EXE_DW = `MUL_EXEPARAM_DW
)
(
	//from fifo
	output mul_fifo_pop,
	input mul_fifo_empty,
	input [DW-1:0] mul_issue_info,

	//from execute
	input mul_execute_ready,
	output mul_exeparam_valid_qout,
	output [EXE_DW-1:0] mul_exeparam_qout,

	//from regFile
	input [32*`RP-1 : 0] wbLog_qout,

	input flush,
	input CLK,
	input RSTn
);







	wire rv64m_mul, rv64m_mulh, rv64m_mullhsu, rv64m_mulhu, rv64m_div, rv64m_divu, rv64m_rem, rv64m_remu, rv64m_mulw, rv64m_divw, rv64m_divuw, rv64_remw, rv64m_remuw;




	wire [5+`RB-1:0] mul_rd0;
	wire [5+`RB-1:0] mul_rs1;
	wire [5+`RB-1:0] mul_rs2;

	assign {
			rv64m_mul,
			rv64m_mulh,
			rv64m_mullhsu,
			rv64m_mulhu,
			rv64m_div,
			rv64m_divu,
			rv64m_rem,
			rv64m_remu,
			rv64m_mulw,
			rv64m_divw,
			rv64m_divuw,
			rv64_remw,
			rv64m_remuw,

			mul_rd0,
			mul_rs1,
			mul_rs2

			} = mul_issue_info;



	wire rs1_ready = wbLog_qout[mul_rs1] | (mul_rs1[`RB +: 5] == 5'd0);
	wire rs2_ready = wbLog_qout[mul_rs2] | (mul_rs2[`RB +: 5] == 5'd0);

	wire mul_isClearRAW = ( ~mul_fifo_empty ) 
							& 
							(
								( 
									rv64m_mul | rv64m_mulh | rv64m_mullhsu | rv64m_mulhu | rv64m_mulw
									| rv64m_div | rv64m_divu | rv64m_rem | rv64m_remu | rv64m_divw | rv64m_divuw | rv64_remw | rv64m_remuw
								)
									& rs1_ready & rs2_ready
							);

	wire [EXE_DW-1:0] mul_exeparam_dnxt = 
		mul_exeparam_valid_dnxt ? 
			mul_issue_info : 
			mul_exeparam_qout;

	wire mul_exeparam_valid_dnxt = flush ? 1'b0 : (mul_execute_ready & mul_isClearRAW);
	assign mul_fifo_pop = mul_exeparam_valid_dnxt;

	gen_dffr # (.DW(EXE_DW)) mul_exeparam ( .dnxt(mul_exeparam_dnxt), .qout(mul_exeparam_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(1)) mul_exeparam_valid ( .dnxt(mul_exeparam_valid_dnxt), .qout(mul_exeparam_valid_qout), .CLK(CLK), .RSTn(RSTn));













endmodule
module csr_issue #
	(
		parameter DW = `CSR_ISSUE_INFO_DW,
		parameter EXE_DW = `CSR_EXEPARAM_DW
	)
	(
	
	//from fifo
	output csr_fifo_pop,
	input csr_fifo_empty,
	input [DW-1:0] csr_issue_info,

	output csr_exeparam_valid_qout,
	output [EXE_DW-1 :0] csr_exeparam_qout,

	//from regFile
	input [32*`RP-1 : 0] wbLog_qout,

	//from commit
	input [63:0] commit_pc,

	input flush,
	input CLK,
	input RSTn
);



initial $info("the pervious instruction must be commited, then csr can issue and execute");

	//csr must be ready
	wire csr_exeparam_ready = 1'b1;


	wire rv64csr_rw;
	wire rv64csr_rs;
	wire rv64csr_rc;
	wire rv64csr_rwi;
	wire rv64csr_rsi;
	wire rv64csr_rci;

	wire [63:0] issue_pc;
	wire [(5+`RB)-1:0] csr_rd0;
	wire [(5+`RB)-1:0] csr_rs1;
	wire [11:0] csr_imm;

	wire csrILP_ready = (commit_pc == issue_pc);

	assign { 
			rv64csr_rw, rv64csr_rs, rv64csr_rc, rv64csr_rwi, rv64csr_rsi, rv64csr_rci,
			issue_pc, csr_imm, csr_rd0, csr_rs1


			} = csr_issue_info;







	wire csr_rw = rv64csr_rw | rv64csr_rwi;
	wire csr_rs = rv64csr_rs | rv64csr_rsi;
	wire csr_rc = rv64csr_rc | rv64csr_rci;

	wire rs1_ready = wbLog_qout[csr_rs1] | (csr_rs1[`RB +: 5] == 5'd0);

	wire csr_isClearRAW = ( ~csr_fifo_empty ) & ( 	((rv64csr_rw | rv64csr_rs | rv64csr_rc ) & rs1_ready )
													|
													(rv64csr_rwi | rv64csr_rsi | rv64csr_rci )
												);

	wire is_imm = rv64csr_rwi | rv64csr_rsi | rv64csr_rci;
	wire [11:0] addr = csr_imm;


	wire [EXE_DW-1:0] csr_exeparam_dnxt = csr_exeparam_valid_dnxt ? { 
											csr_rw,
											csr_rs,
											csr_rc,
								
											csr_rd0,
											csr_rs1,

											is_imm,
											addr
											} : csr_exeparam_qout;

	wire csr_exeparam_valid_dnxt = flush ? 1'b0 : (csr_isClearRAW & csrILP_ready & csr_exeparam_ready);

	assign csr_fifo_pop = csr_exeparam_valid_dnxt;


	gen_dffr # (.DW(EXE_DW)) csr_exeparam ( .dnxt(csr_exeparam_dnxt), .qout(csr_exeparam_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(1)) csr_exeparam_valid ( .dnxt(csr_exeparam_valid_dnxt), .qout(csr_exeparam_valid_qout), .CLK(CLK), .RSTn(RSTn));




endmodule
module bru_issue #
	(
		parameter DW = `BRU_ISSUE_INFO_DW,
		parameter EXE_DW = `BRU_EXEPARAM_DW
	)
	(

	//from fifo
	output bru_fifo_pop,
	input bru_fifo_empty,
	input [DW-1:0] bru_issue_info,

	//from execute

	input bru_exeparam_ready,
	output bru_exeparam_valid_qout,
	output [EXE_DW-1:0] bru_exeparam_qout,
	input bruILP_ready,

	input [32*`RP-1 : 0] wbLog_qout,

	input flush,
	input CLK,
	input RSTn
);


	wire rv64i_jal;
	wire rv64i_jalr;
	wire rv64i_beq;
	wire rv64i_bne;
	wire rv64i_blt;
	wire rv64i_bge;
	wire rv64i_bltu;
	wire rv64i_bgeu;

	wire is_rvc;

	wire [63:0] bru_pc;
	wire [63:0] bru_imm;

	wire [5+`RB-1:0] bru_rd0;
	wire [5+`RB-1:0] bru_rs1;
	wire [5+`RB-1:0] bru_rs2;


	assign {
				rv64i_jal,
				rv64i_jalr,
				rv64i_beq,
				rv64i_bne,
				rv64i_blt,
				rv64i_bge,
				rv64i_bltu,
				rv64i_bgeu,

				is_rvc,

				bru_pc,
				bru_imm,

				bru_rd0,
				bru_rs1,
				bru_rs2
			} = bru_issue_info;


	wire rs1_ready = wbLog_qout[bru_rs1] | (bru_rs1[`RB +: 5] == 5'd0);
	wire rs2_ready = wbLog_qout[bru_rs2] | (bru_rs2[`RB +: 5] == 5'd0);

	wire bru_isClearRAW = ( ~bru_fifo_empty ) 
							& (
								( ( rv64i_beq
									| rv64i_bne
									| rv64i_blt
									| rv64i_bge
									| rv64i_bltu
									| rv64i_bgeu
									) & rs1_ready & rs2_ready & bruILP_ready)
								|  rv64i_jal
								| ( rv64i_jalr & rs1_ready )
								);

	wire [EXE_DW-1:0] bru_exeparam_dnxt = bru_exeparam_valid_dnxt ? { 
										rv64i_jal,
										rv64i_jalr,

										rv64i_beq,
										rv64i_bne,
										rv64i_blt,
										rv64i_bge,
										rv64i_bltu,
										rv64i_bgeu,

										is_rvc,

										bru_rs1,
										bru_rs2,
										bru_rd0,

										bru_pc,
										bru_imm
									}
									: bru_exeparam_qout;

	wire bru_exeparam_valid_dnxt = flush ? 1'b0 : (bru_exeparam_ready & bru_isClearRAW);
	assign bru_fifo_pop = bru_exeparam_valid_dnxt;

	gen_dffr # (.DW(EXE_DW)) bru_exeparam ( .dnxt(bru_exeparam_dnxt), .qout(bru_exeparam_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(1)) bru_exeparam_valid ( .dnxt(bru_exeparam_valid_dnxt), .qout(bru_exeparam_valid_qout), .CLK(CLK), .RSTn(RSTn));






endmodule
module lsu_issue #
	(
		parameter DW = `LSU_ISSUE_INFO_DW,
		parameter DP = `LSU_ISSUE_INFO_DP,
		parameter EXE_DW = `LSU_EXEPARAM_DW

	)
	(
		output lsu_fifo_pop,
		input lsu_fifo_empty,
		input [DW-1:0] lsu_issue_info,
		
		input issue_lsu_ready,
		output issue_lsu_valid,
		output [EXE_DW-1:0] issue_lsu_info,

		//from regFile
		input [(64*`RP*32)-1:0] regFileX_read,
		input [32*`RP-1 : 0] wbLog_qout,



		input flush,
		input CLK,
		input RSTn
);



	wire rv64i_lb;
	wire rv64i_lh;
	wire rv64i_lw;
	wire rv64i_ld;

	wire rv64i_lbu;
	wire rv64i_lhu;
	wire rv64i_lwu;

	wire rv64i_sb;
	wire rv64i_sh;
	wire rv64i_sw;
	wire rv64i_sd;

	wire rv64zi_fence_i;
	wire rv64i_fence;

	wire [63:0] imm;

	wire [(5+`RB)-1:0] lsu_rd0;
	wire [(5+`RB)-1:0] lsu_rs1;
	wire [(5+`RB)-1:0] lsu_rs2;

	wire rs1_ready;
	wire rs2_ready;

	wire lsu_isClearRAW;

	wire [63:0] op1;
	wire [63:0] op2;






	assign {
			rv64i_lb, rv64i_lh, rv64i_lw, rv64i_ld, rv64i_lbu, rv64i_lhu, rv64i_lwu,
			rv64i_sb, rv64i_sh, rv64i_sw, rv64i_sd,
			rv64zi_fence_i, rv64i_fence,
			imm,
			lsu_rd0,
			lsu_rs1,
			lsu_rs2
			} = lsu_issue_info;


	assign rs1_ready = wbLog_qout[lsu_rs1] | ( lsu_rs1[`RB +: 5] == 5'd0 );
	assign rs2_ready = wbLog_qout[lsu_rs2] | ( lsu_rs2[`RB +: 5] == 5'd0 );

	assign lsu_isClearRAW = ( ~lsu_fifo_empty ) & (
													(
														(rv64i_lb | rv64i_lh | rv64i_lw | rv64i_ld | rv64i_lbu | rv64i_lhu | rv64i_lwu)
														& rs1_ready 
													)
													|
													(
														(rv64i_sb | rv64i_sh | rv64i_sw | rv64i_sd)
														& rs1_ready & rs2_ready
													)
													|
													(
														rv64zi_fence_i | rv64i_fence
													)
												);


	assign op1 = regFileX_read[lsu_rs1 * 64 +: 64] + imm;
	assign op2 = regFileX_read[lsu_rs2 * 64 +: 64];


	wire issue_lsu_valid_set, issue_lsu_valid_rst, issue_lsu_valid_qout;
	wire [EXE_DW-1:0] issue_lsu_info_dnxt;
	wire [EXE_DW-1:0] issue_lsu_info_qout;



	assign issue_lsu_info_dnxt = issue_lsu_valid_set ? 
								{
									rv64i_lb, rv64i_lh, rv64i_lw, rv64i_ld, rv64i_lbu, rv64i_lhu, rv64i_lwu,
									rv64i_sb, rv64i_sh, rv64i_sw, rv64i_sd,
									rv64zi_fence_i, rv64i_fence,
									lsu_rd0,
									op1,
									op2
								} : issue_lsu_info_qout;
	assign issue_lsu_info = issue_lsu_info_qout;





	assign issue_lsu_valid_set = ~flush & (lsu_isClearRAW & ~issue_lsu_valid_qout);
	assign issue_lsu_valid_rst = flush | (issue_lsu_ready & issue_lsu_valid_qout);
	assign issue_lsu_valid = issue_lsu_valid_qout;

	assign lsu_fifo_pop = issue_lsu_valid_set;



	gen_dffr # (.DW(EXE_DW)) issue_lsu_info_dffr ( .dnxt(issue_lsu_info_dnxt), .qout(issue_lsu_info_qout), .CLK(CLK), .RSTn(RSTn));
	gen_rsffr # (.DW(1)) issue_lsu_valid_rsffr ( .set_in(issue_lsu_valid_set), .rst_in(issue_lsu_valid_rst), .qout(issue_lsu_valid_qout), .CLK(CLK), .RSTn(RSTn));

































endmodule
module issue_fifo #(
	parameter DW = 100,
	parameter DP = 8
)
(

	input [ DW - 1 : 0] issue_info_push,
	output [ DW - 1 : 0] issue_info_pop,

	input issue_push,
	input issue_pop,
	output fifo_full,
	output fifo_empty,

	input flush,
	input CLK,
	input RSTn
	
);



gen_fifo # ( .DW(DW), .AW($clog2(DP)))
i_fifo(
	.fifo_pop(issue_pop), 
	.fifo_push(issue_push),
	.data_push(issue_info_push),

	.fifo_empty(fifo_empty), 
	.fifo_full(fifo_full), 
	.data_pop(issue_info_pop),

	.flush(flush),
	.CLK(CLK),
	.RSTn(RSTn)
);




endmodule
module csr #
	(
		parameter DW = `CSR_EXEPARAM_DW
	)
	(

	input csr_exeparam_valid,
	input [DW-1 :0] csr_exeparam,

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

	output csr_writeback_valid,
	output [63:0] csr_res_qout,
	output [(5+`RB-1):0] csr_rd0_qout,

	input [(64*`RP*32)-1:0] regFileX_read,

	input CLK,
	input RSTn,
	input flush
	
);


	wire rv64csr_rw;
	wire rv64csr_rs;
	wire rv64csr_rc;

	wire [(5+`RB)-1:0] csr_rd0_dnxt;
	wire [(5+`RB)-1:0] csr_rs1;
	wire is_imm;
	wire [63:0] op;


	assign { 
			rv64csr_rw,
			rv64csr_rs,
			rv64csr_rc,

			csr_rd0_dnxt,
			csr_rs1,
			is_imm,
			csrexe_addr

			} = csr_exeparam;


	assign op = ({64{~is_imm}} & regFileX_read[csr_rs1*64 +: 64])
					|
					({64{is_imm}} & {{(64-5){1'b0}}, csr_rs1[`RB +: 5]} );





wire dontRead = (csr_rd0_dnxt[`RB +: 5] == 5'd0) & rv64csr_rw;
wire dontWrite = (op == 64'd0) & ( rv64csr_rs | rv64csr_rc );

initial $warning("no exception in csr exe at this version");
wire illagle_op = 1'b0;




assign rw = ~dontWrite & csr_exeparam_valid & rv64csr_rw;
assign rs = ~dontWrite & csr_exeparam_valid & rv64csr_rs;
assign rc = ~dontWrite & csr_exeparam_valid & rv64csr_rc;

wire [63:0] csr_res_dnxt = csrexe_res;


gen_dffr # (.DW((5+`RB))) csr_rd0_dffr ( .dnxt(csr_rd0_dnxt), .qout(csr_rd0_qout), .CLK(CLK), .RSTn(RSTn));
gen_dffr # (.DW(64)) csr_res_dffr ( .dnxt(csr_res_dnxt), .qout(csr_res_qout), .CLK(CLK), .RSTn(RSTn));
gen_dffr # (.DW(1)) valid_dffr ( .dnxt(csr_exeparam_valid&(~flush)), .qout(csr_writeback_valid), .CLK(CLK), .RSTn(RSTn));



endmodule
module bru #
	(
		parameter DW = `BRU_EXEPARAM_DW
	)
	(

	//from bru issue
	output bru_exeparam_ready,
	input bru_exeparam_valid,
	input [DW-1:0] bru_exeparam, 

	// to pc generate
	output takenBranch_qout,
	output takenBranch_valid_qout,
	output jalr_valid_qout,
	output [63:0] jalr_pc_qout,

	output bru_writeback_valid,
	output [63:0] bru_res_qout,
	output [(5+`RB)-1:0] bru_rd0_qout,

	//from regFile
	input [(64*`RP*32)-1:0] regFileX_read,

	input flush,
	input CLK,
	input RSTn

);

	wire bru_pcGen_ready = 1'b1;

	wire bru_jal;
	wire bru_jalr;
	wire bru_eq;
	wire bru_ne;
	wire bru_lt;
	wire bru_ge;
	wire bru_ltu;
	wire bru_geu;

	wire is_rvc;

	wire [(5+`RB)-1:0] bru_rs1;
	wire [(5+`RB)-1:0] bru_rs2;
	wire [(5+`RB)-1:0] bru_rd0_dnxt;

	wire [63:0] bru_pc;
	wire [63:0] bru_imm;


	assign { 
			bru_jal,
			bru_jalr,

			bru_eq,
			bru_ne,
			bru_lt,
			bru_ge,
			bru_ltu,
			bru_geu,

			is_rvc,

			bru_rs1,
			bru_rs2,
			bru_rd0_dnxt,

			bru_pc,
			bru_imm
			} = bru_exeparam;

	wire [63:0] src1 = regFileX_read[ 64*bru_rs1 +: 64];
	wire [63:0] src2 = regFileX_read[ 64*bru_rs2 +: 64];




	wire [63:0] jalr_pc_dnxt = (src1 + bru_imm) & ~(64'b1);
	wire jalr_valid_dnxt = (~flush) & bru_jalr & bru_exeparam_valid;

	gen_dffr # (.DW(1)) jalr_valid ( .dnxt(jalr_valid_dnxt), .qout(jalr_valid_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(64)) jalr_pc ( .dnxt(jalr_pc_dnxt), .qout(jalr_pc_qout), .CLK(CLK), .RSTn(RSTn));

	


	wire take_eq = (bru_eq & (src1 == src2));
	wire take_ne = (bru_ne & (src1 != src2));
	wire take_lt = (bru_lt) & ($signed(src1) < $signed(src2));
	wire take_ge = (bru_ge) & ($signed(src1) >= $signed(src2));
	wire take_ltu = (bru_ltu) & ($unsigned(src1) < $unsigned(src2));
	wire take_geu = (bru_geu) & ($unsigned(src1) >= $unsigned(src2));

	wire valid_dnxt = (~flush) & bru_pcGen_ready & bru_exeparam_valid 
						& ( bru_eq 
						| bru_ne
						| bru_lt
						| bru_ge
						| bru_ltu
						| bru_geu );

	wire takenBranch_dnxt = valid_dnxt 
								? (take_eq | take_ne | take_lt | take_ge | take_ltu | take_geu)
								: takenBranch_qout;




	gen_dffr # (.DW(1)) takenBranch ( .dnxt(takenBranch_dnxt), .qout(takenBranch_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(1)) takenBranch_valid ( .dnxt(valid_dnxt), .qout(takenBranch_valid_qout), .CLK(CLK), .RSTn(RSTn));


	assign bru_exeparam_ready = bru_pcGen_ready;
	wire [63:0] bru_res_dnxt = ({64{(bru_jal | bru_jalr)}} & (bru_pc + (is_rvc ? 64'd2 : 64'd4)))
								|
								( {64{(~bru_jal & ~bru_jalr)}} & 64'b0 );

	gen_dffr # (.DW((5+`RB))) bru_rd0 ( .dnxt(bru_rd0_dnxt), .qout(bru_rd0_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(64)) bru_res ( .dnxt( bru_res_dnxt), .qout(bru_res_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(1)) valid ( .dnxt(bru_exeparam_valid&(~flush)), .qout(bru_writeback_valid), .CLK(CLK), .RSTn(RSTn));






endmodule
module axi_crossbar_v2_1_22_splitter #
  (
   parameter integer C_NUM_M = 2  // Number of master ports = [2:16]
   )
  (
   // Global Signals
   input  wire                             ACLK,
   input  wire                             ARESET,
   // Slave  Port
   input  wire                             S_VALID,
   output wire                             S_READY,
   // Master Ports
   output wire [C_NUM_M-1:0]               M_VALID,
   input  wire [C_NUM_M-1:0]               M_READY
   );

   reg  [C_NUM_M-1:0] m_ready_d = 0;
   wire               s_ready_i;
   wire [C_NUM_M-1:0] m_valid_i;

   always @(posedge ACLK) begin
      if (ARESET | s_ready_i) m_ready_d <= {C_NUM_M{1'b0}};
      else                    m_ready_d <= m_ready_d | (m_valid_i & M_READY);
   end

   assign s_ready_i = &(m_ready_d | M_READY);
   assign m_valid_i = {C_NUM_M{S_VALID}} & ~m_ready_d;
   assign M_VALID = m_valid_i;
   assign S_READY = s_ready_i;

endmodule
module generic_baseblocks_v2_1_0_carry_and #
  (
   parameter         C_FAMILY                         = "virtex6"
                       // FPGA Family. Current version: virtex6 or spartan6.
   )
  (
   input  wire        CIN,
   input  wire        S,
   output wire        COUT
   );
  
  
  /////////////////////////////////////////////////////////////////////////////
  // Variables for generating parameter controlled instances.
  /////////////////////////////////////////////////////////////////////////////
  
  
  /////////////////////////////////////////////////////////////////////////////
  // Local params
  /////////////////////////////////////////////////////////////////////////////
  
  
  /////////////////////////////////////////////////////////////////////////////
  // Functions
  /////////////////////////////////////////////////////////////////////////////
  
  
  /////////////////////////////////////////////////////////////////////////////
  // Internal signals
  /////////////////////////////////////////////////////////////////////////////

  
  /////////////////////////////////////////////////////////////////////////////
  // Instantiate or use RTL code
  /////////////////////////////////////////////////////////////////////////////
  
  generate
    if ( C_FAMILY == "rtl" ) begin : USE_RTL
      assign COUT = CIN & S;
      
    end else begin : USE_FPGA
      MUXCY and_inst 
      (
       .O (COUT), 
       .CI (CIN), 
       .DI (1'b0), 
       .S (S)
      ); 
      
    end
  endgenerate
  
  
endmodule
module icache_tb (

);


	wire ifu_req_ready;
	wire [63:0] ifu_data_rsp;
	wire ifu_rsp_valid;

	reg ifu_rsp_ready;
	reg ifu_req_valid;
	reg [31:0] ifu_addr_req;

	reg il1_fence;
	reg CLK;
	reg RSTn;





	wire [31:0] IL1_ARADDR;
	wire [7:0] IL1_ARLEN;
	wire [1:0] IL1_ARBURST;
	wire IL1_ARVALID;
	wire IL1_ARREADY;

	wire [63:0] IL1_RDATA;
	wire [1:0] IL1_RRESP;
	wire IL1_RLAST;
	wire IL1_RVALID;
	wire IL1_RREADY;


icache i_icache(

	.IL1_ARADDR(IL1_ARADDR),
	.IL1_ARLEN(IL1_ARLEN),
	.IL1_ARBURST(IL1_ARBURST),
	.IL1_ARVALID(IL1_ARVALID),
	.IL1_ARREADY(IL1_ARREADY),
	.IL1_RDATA(IL1_RDATA),
	.IL1_RRESP(IL1_RRESP),
	.IL1_RLAST(IL1_RLAST),
	.IL1_RVALID(IL1_RVALID),
	.IL1_RREADY(IL1_RREADY),

	.ifu_req_valid(ifu_req_valid),
	.ifu_req_ready(ifu_req_ready),
	.ifu_addr_req(ifu_addr_req),
	.ifu_data_rsp(ifu_data_rsp),
	.ifu_rsp_valid(ifu_rsp_valid),
	.ifu_rsp_ready(ifu_rsp_ready),

	.il1_fence(il1_fence),
	.CLK(CLK),
	.RSTn(RSTn)

);




axi_full_slv_sram s_axi_full_slv_sram
(

	.S_AXI_AWADDR(32'h0),
	.S_AXI_AWLEN(8'h0),
	.S_AXI_AWSIZE(3'h0),
	.S_AXI_AWBURST(2'h0),
	.S_AXI_AWVALID(1'b0),
	.S_AXI_AWREADY(),

	.S_AXI_WDATA(64'h0),
	.S_AXI_WSTRB(8'h0),
	.S_AXI_WLAST(1'b1),
	.S_AXI_WVALID(1'b0),
	.S_AXI_WREADY(),

	.S_AXI_BRESP(),
	.S_AXI_BVALID(),
	.S_AXI_BREADY(1'b1),

	.S_AXI_ARADDR(IL1_ARADDR),
	.S_AXI_ARLEN(IL1_ARLEN),
	.S_AXI_ARSIZE(3'd3),
	.S_AXI_ARBURST(IL1_ARBURST),
	.S_AXI_ARVALID(IL1_ARVALID),
	.S_AXI_ARREADY(IL1_ARREADY),

	.S_AXI_RDATA(IL1_RDATA),
	.S_AXI_RRESP(IL1_RRESP),
	.S_AXI_RLAST(IL1_RLAST),
	.S_AXI_RVALID(IL1_RVALID),
	.S_AXI_RREADY(IL1_RREADY),

	.CLK(CLK),
	.RSTn(RSTn)
);



initial
begin
	$dumpfile("../build/wave.vcd"); //生成的vcd文件名称
	$dumpvars(0, icache_tb);//tb模块名称
end



initial begin

	CLK = 0;
	RSTn = 0;

	#20

	RSTn <= 1;

	#80000
			$display("Time Out !!!");
	 $finish;
end

initial begin
	forever begin 
		#5 CLK <= ~CLK;
	end
end





initial begin
	ifu_rsp_ready = 1'b1;
	ifu_req_valid = 1'b0;
	ifu_addr_req = 32'h18;

	il1_fence = 1'b0;

#100

#22
	ifu_req_valid = 1'b1;
	ifu_addr_req = 32'h18;
#10
	ifu_req_valid = 1'b0;

#1000
	ifu_req_valid = 1'b1;
	ifu_addr_req = 32'h10;
#10
	ifu_req_valid = 1'b0;


#1000
	ifu_req_valid = 1'b1;
	ifu_addr_req = 32'h80000010;
#10
	ifu_req_valid = 1'b0;

#1000
	ifu_req_valid = 1'b1;
	ifu_addr_req = 32'h90000010;
#10
	ifu_req_valid = 1'b0;

end




endmodule
module ALU(
    input wire [31:0] Operand1,
    input wire [31:0] Operand2,
    input wire [3:0] AluContrl,
    output reg [31:0] AluOut
    );
    //
    wire signed [31:0] Operand1S = $signed(Operand1);
    wire signed [31:0] Operand2S = $signed(Operand2);
    //
    always@(*)
    case(AluContrl)
        `SLL:        AluOut<=Operand1<<(Operand2[4:0]);
        `SRL:        AluOut<=Operand1>>(Operand2[4:0]);
        `SRA:        AluOut<=Operand1S >>> (Operand2[4:0]);
        `ADD:        AluOut<=Operand1 + Operand2; 
        `SUB:        AluOut<=Operand1 - Operand2;
        `XOR:        AluOut<=Operand1 ^ Operand2;
        `OR:         AluOut<=Operand1 | Operand2;   
        `AND:        AluOut<=Operand1 & Operand2;
        `SLT:        AluOut<=Operand1S < Operand2S ? 32'd1:32'd0;
        `SLTU:       AluOut<=Operand1 < Operand2 ? 32'd1:32'd0;
        `LUI:        AluOut<={ Operand2[31:12],12'b0 };
        default:    AluOut <= 32'hxxxxxxxx;                          
    endcase
endmodule
module IFSegReg(
    input wire clk,
    input wire en, clear,
    input wire [31:0] PC_In,
    output reg [31:0] PCF
    );
    initial PCF = 0;
    
    always@(posedge clk)
        if(en) begin
            if(clear)
                PCF <= 0;
            else 
                PCF <= PC_In;
        end
    
endmodule
module HarzardUnit(
    input wire CpuRst, ICacheMiss, DCacheMiss, 
    input wire BranchE, JalrE, JalD, 
    input wire [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
    input wire [1:0] RegReadE,
    input wire [2:0] MemToRegE, RegWriteM, RegWriteW,
    output reg StallF, FlushF, StallD, FlushD, StallE, FlushE, StallM, FlushM, StallW, FlushW,
    output reg [1:0] Forward1E, Forward2E
    );
    //
    //Stall and Flush signals generate
    always @ (*)
        if(CpuRst)
            {StallF,FlushF,StallD,FlushD,StallE,FlushE,StallM,FlushM,StallW,FlushW} <= 10'b0101010101;
        else if(DCacheMiss | ICacheMiss)
            {StallF,FlushF,StallD,FlushD,StallE,FlushE,StallM,FlushM,StallW,FlushW} <= 10'b1010101010;
        else if(BranchE | JalrE)
            {StallF,FlushF,StallD,FlushD,StallE,FlushE,StallM,FlushM,StallW,FlushW} <= 10'b0001010000;
        else if(MemToRegE & ((RdE==Rs1D)||(RdE==Rs2D)) )
            {StallF,FlushF,StallD,FlushD,StallE,FlushE,StallM,FlushM,StallW,FlushW} <= 10'b1010010000;
        else if(JalD)
            {StallF,FlushF,StallD,FlushD,StallE,FlushE,StallM,FlushM,StallW,FlushW} <= 10'b0001000000;
        else
            {StallF,FlushF,StallD,FlushD,StallE,FlushE,StallM,FlushM,StallW,FlushW} <= 10'b0000000000;
    //Forward Register Source 1
    always@(*)begin
        if( (RegWriteM!=3'b0) && (RegReadE[1]!=0) && (RdM==Rs1E) &&(RdM!=5'b0) )
            Forward1E<=2'b10;
        else if( (RegWriteW!=3'b0) && (RegReadE[1]!=0) && (RdW==Rs1E) &&(RdW!=5'b0) )
            Forward1E<=2'b01;
        else
            Forward1E<=2'b00;
    end
    //Forward Register Source 2
    always@(*)begin
        if( (RegWriteM!=3'b0) && (RegReadE[0]!=0) && (RdM==Rs2E) &&(RdM!=5'b0) )
            Forward2E<=2'b10;
        else if( (RegWriteW!=3'b0) && (RegReadE[0]!=0) && (RdW==Rs2E) &&(RdW!=5'b0) )
            Forward2E<=2'b01;
        else
            Forward2E<=2'b00;
    end      
endmodule
module IDSegReg(
    input wire clk,
    input wire clear,
    input wire en,
    //Instrution Memory Access
    input wire [31:0] A,
    output wire [31:0] RD,
    //Instruction Memory Debug
    input wire [31:0] A2,
    input wire [31:0] WD2,
    input wire [3:0] WE2,
    output wire [31:0] RD2,
    //
    input wire [31:0] PCF,
    output reg [31:0] PCD 
    );
    
    initial PCD = 0;
    always@(posedge clk)
        if(en)
            PCD <= clear ? 0: PCF;
    
    wire [31:0] RD_raw;
    InstructionRam InstructionRamInst (
         .clk    ( clk        ),
         .addra  ( A[31:2]    ),
         .douta  ( RD_raw     ),
         .web    ( |WE2       ),
         .addrb  ( A2[31:2]   ),
         .dinb   ( WD2        ),
         .doutb  ( RD2        )
     );
     // Add clear and stall support
    // if chip not enabled, output output last read result
    // else if chip clear, output 0
    // else output values from bram
    reg stall_ff= 1'b0;
    reg clear_ff= 1'b0;
    reg [31:0] RD_old=32'b0;
    always @ (posedge clk)
    begin
        stall_ff<=~en;
        clear_ff<=clear;
        RD_old<=RD_raw;
    end    
    assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );

endmodule
module EXSegReg(
    input wire clk,
    input wire en,
    input wire clear,
    //Data Signals
    input wire [31:0] PCD,
    output reg [31:0] PCE, 
    input wire [31:0] JalNPC,
    output reg [31:0] BrNPC, 
    input wire [31:0] ImmD,
    output reg [31:0] ImmE,
    input wire [4:0] RdD,
    output reg [4:0] RdE,
    input wire [4:0] Rs1D,
    output reg [4:0] Rs1E,
    input wire [4:0] Rs2D,
    output reg [4:0] Rs2E,
    input wire [31:0] RegOut1D,
    output reg [31:0] RegOut1E,
    input wire [31:0] RegOut2D,
    output reg [31:0] RegOut2E,
    //Control Signals
    input wire JalrD,
    output reg JalrE,
    input wire [2:0] RegWriteD,
    output reg [2:0] RegWriteE,
    input wire MemToRegD,
    output reg MemToRegE,
    input wire [3:0] MemWriteD,
    output reg [3:0] MemWriteE,
    input wire LoadNpcD,
    output reg LoadNpcE,
    input wire [1:0] RegReadD,
    output reg [1:0] RegReadE, 
    input wire [2:0] BranchTypeD,
    output reg [2:0] BranchTypeE,
    input wire [4:0] AluContrlD,
    output reg [4:0] AluContrlE,
    input wire AluSrc1D,
    output reg AluSrc1E,
    input wire [1:0] AluSrc2D,
    output reg [1:0] AluSrc2E
    );
    initial begin
        PCE        = 32'b0; 
        BrNPC      = 32'b0; 
        ImmE       = 32'b0;
        RdE        = 32'b0;
        Rs1E       = 5'b0;
        Rs2E       = 5'b0;
        RegOut1E   = 32'b0;
        RegOut2E   = 32'b0;
        JalrE      = 1'b0;
        RegWriteE  = 1'b0;
        MemToRegE  = 1'b0;
        MemWriteE  = 1'b0;
        LoadNpcE   = 1'b0;
        RegReadE   = 2'b00;
        BranchTypeE = 3'b0;
        AluContrlE = 5'b0;
        AluSrc1E   = 1'b0; 
        AluSrc2E   = 2'b0; 
    end
    //
    always@(posedge clk) begin
        if(en)
            if(clear)
                begin
                PCE<=32'b0; 
                BrNPC<=32'b0; 
                ImmE<=32'b0;
                RdE<=32'b0;
                Rs1E<=5'b0;
                Rs2E<=5'b0;
                RegOut1E<=32'b0;
                RegOut2E<=32'b0;
                JalrE<=1'b0;
                RegWriteE<=1'b0;
                MemToRegE<=1'b0;
                MemWriteE<=1'b0;
                LoadNpcE<=1'b0;
                RegReadE<=2'b00;
                BranchTypeE = 3'b0;
                AluContrlE<=5'b0;
                AluSrc1E<=1'b0; 
                AluSrc2E<=2'b0;     
            end else begin
                PCE<=PCD; 
                BrNPC<=JalNPC; 
                ImmE<=ImmD;
                RdE<=RdD;
                Rs1E<=Rs1D;
                Rs2E<=Rs2D;
                RegOut1E<=RegOut1D;
                RegOut2E<=RegOut2D;
                JalrE<=JalrD;
                RegWriteE=RegWriteD;
                MemToRegE<=MemToRegD;
                MemWriteE<=MemWriteD;
                LoadNpcE<=LoadNpcD;
                RegReadE<=RegReadD;
                BranchTypeE = BranchTypeD;
                AluContrlE<=AluContrlD;
                AluSrc1E<=AluSrc1D;
                AluSrc2E<=AluSrc2D;         
            end
        end
    
endmodule
module ImmOperandUnit(
    input wire [31:7] In,
    input wire [2:0] Type,
    output reg [31:0] Out
    );
    //
    always@(*)
    begin
        case(Type)
            `ITYPE: Out<={ {21{In[31]}}, In[30:20] };
            `STYPE: Out<={ {21{In[31]}}, In[30:25], In[11:7] };
            `BTYPE: Out<={ {20{In[31]}}, In[7], In[30:25], In[11:8], 1'b0 };
            `UTYPE: Out<={ In[31:12], 12'b0 };
            `JTYPE: Out<={ {12{In[31]}}, In[19:12], In[20], In[30:21], 1'b0 };
            default:Out<=32'hxxxxxxxx;
        endcase
    end
    
endmodule
module DataExt(
    input wire [31:0] IN,
    input wire [1:0] LoadedBytesSelect,
    input wire [2:0] RegWriteW,
    output reg [31:0] OUT
    );
    wire [31:0] LB_IN;
    wire [31:0] LH_IN;
    assign LB_IN = (IN >> (LoadedBytesSelect * 32'h08)) & 32'h000000ff;
    assign LH_IN = (IN >> (LoadedBytesSelect * 32'h08)) & 32'h0000ffff;
    always @(*)
    begin
        case(RegWriteW)
            `LB:	OUT<={{24{LB_IN[7]}},LB_IN[7:0]};
            `LH:    OUT<={{16{LH_IN[15]}},LH_IN[15:0]};
            `LW:    OUT<=IN;
            `LBU:   OUT<={24'b0,LB_IN[7:0]};
            `LHU:   OUT<={16'b0,LH_IN[15:0]};
            default:OUT = 32'hxxxxxxxx;
        endcase
    end
    
endmodule
module MEMSegReg(
    input wire clk,
    input wire en,
    input wire clear,
    //Data Signals
    input wire [31:0] AluOutE,
    output reg [31:0] AluOutM, 
    input wire [31:0] ForwardData2,
    output reg [31:0] StoreDataM, 
    input wire [4:0] RdE,
    output reg [4:0] RdM,
    input wire [31:0] PCE,
    output reg [31:0] PCM,
    //Control Signals
    input wire [2:0] RegWriteE,
    output reg [2:0] RegWriteM,
    input wire MemToRegE,
    output reg MemToRegM,
    input wire [3:0] MemWriteE,
    output reg [3:0] MemWriteM,
    input wire LoadNpcE,
    output reg LoadNpcM
    );
    initial begin
        AluOutM    = 0;
        StoreDataM = 0;
        RdM        = 5'h0;
        PCM        = 0;
        RegWriteM  = 3'h0;
        MemToRegM  = 1'b0;
        MemWriteM  = 4'b0;
        LoadNpcM   = 0;
    end
    
    always@(posedge clk)
        if(en) begin
            AluOutM    <= clear ?     0 : AluOutE;
            StoreDataM <= clear ?     0 : ForwardData2;
            RdM        <= clear ?  5'h0 : RdE;
            PCM        <= clear ?     0 : PCE;
            RegWriteM  <= clear ?  3'h0 : RegWriteE;
            MemToRegM  <= clear ?  1'b0 : MemToRegE;
            MemWriteM  <= clear ?  4'b0 : MemWriteE;
            LoadNpcM   <= clear ?     0 : LoadNpcE;
        end
    
endmodule
module RegisterFile(
    input wire clk,
    input wire rst,
    input wire WE3,
    input wire [4:0] A1,
    input wire [4:0] A2,
    input wire [4:0] A3,
    input wire [31:0] WD3,
    output wire [31:0] RD1,
    output wire [31:0] RD2
    );

    reg [31:0] RegFile[31:1];
    integer i;
    //
    always@(negedge clk or posedge rst) 
    begin 
        if(rst)                                 for(i=1;i<32;i=i+1) RegFile[i][31:0]<=32'b0;
        else if( (WE3==1'b1) && (A3!=5'b0) )    RegFile[A3]<=WD3;   
    end
    //    
    assign RD1= (A1==5'b0)?32'b0:RegFile[A1];
    assign RD2= (A2==5'b0)?32'b0:RegFile[A2];
    
endmodule
module BranchDecisionMaking(
    input wire [2:0] BranchTypeE,
    input wire [31:0] Operand1,Operand2,
    output reg BranchE
    );
wire signed [31:0] Operand1S = $signed(Operand1);
wire signed [31:0] Operand2S = $signed(Operand2);
    //
    always@(*)
    case(BranchTypeE)
//分支预测
    `BEQ:    if(Operand1==Operand2)      BranchE<=1'b1;  //BEQ
            else                        BranchE<=1'b0;
    `BNE:    if(Operand1!=Operand2)      BranchE<=1'b1;  //BNE
            else                        BranchE<=1'b0;   
    `BLT:    if(Operand1S<Operand2S)     BranchE<=1'b1;  //BLT
            else                        BranchE<=1'b0;
    `BLTU:   if(Operand1<Operand2)       BranchE<=1'b1;  //BLTU
            else                        BranchE<=1'b0;
    `BGE:    if(Operand1S>=Operand2S)    BranchE<=1'b1;  //BGE
            else                        BranchE<=1'b0;
    `BGEU:   if(Operand1>=Operand2)      BranchE<=1'b1;  //BGEU
            else                        BranchE<=1'b0;
    default:                            BranchE<=1'b0;  //NOBRANCH                            
    endcase
endmodule
module WBSegReg(
    input wire clk,
    input wire en,
    input wire clear,
    //Data Memory Access
    input wire [31:0] A,
    input wire [31:0] WD,
    input wire [3:0] WE,
    output wire [31:0] RD,
    output reg [1:0] LoadedBytesSelect,
    //Data Memory Debug
    input wire [31:0] A2,
    input wire [31:0] WD2,
    input wire [3:0] WE2,
    output wire [31:0] RD2,
    //input control signals
    input wire [31:0] ResultM,
    output reg [31:0] ResultW, 
    input wire [4:0] RdM,
    output reg [4:0] RdW,
    //output constrol signals
    input wire [2:0] RegWriteM,
    output reg [2:0] RegWriteW,
    input wire MemToRegM,
    output reg MemToRegW
    );
    
    //
    initial begin
        LoadedBytesSelect = 2'b00;
        RegWriteW         =  1'b0;
        MemToRegW         =  1'b0;
        ResultW           =     0;
        RdW               =  5'b0;
    end
    //
    always@(posedge clk)
        if(en) begin
            LoadedBytesSelect <= clear ? 2'b00 : A[1:0];
            RegWriteW         <= clear ?  1'b0 : RegWriteM;
            MemToRegW         <= clear ?  1'b0 : MemToRegM;
            ResultW           <= clear ?     0 : ResultM;
            RdW               <= clear ?  5'b0 : RdM;
        end

    wire [31:0] RD_raw;
    DataRam DataRamInst (
        .clk    ( clk            ),
        .wea    ( WE<<A[1:0]     ),
        .addra  ( A[31:2]        ),
        .dina   ( WD<<(8*A[1:0]) ),
        .douta  ( RD_raw         ),
        .web    ( WE2            ),
        .addrb  ( A2[31:2]       ),
        .dinb   ( WD2            ),
        .doutb  ( RD2            )
    );   
    // Add clear and stall support
    // if chip not enabled, output output last read result
    // else if chip clear, output 0
    // else output values from bram
    reg stall_ff= 1'b0;
    reg clear_ff= 1'b0;
    reg [31:0] RD_old=32'b0;
    always @ (posedge clk)
    begin
        stall_ff<=~en;
        clear_ff<=clear;
        RD_old<=RD_raw;
    end    
    assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );

endmodule
module NPC_Generator(
    input wire [31:0] PCF,JalrTarget, BranchTarget, JalTarget,
    input wire BranchE,JalD,JalrE,
    output reg [31:0] PC_In
    );
    always @(*)
    begin
        if(JalrE)
            PC_In <= JalrTarget;
        else if(BranchE)
            PC_In <= BranchTarget;
        else if(JalD)
            PC_In <= JalTarget;
        else
            PC_In <= PCF+4;
    end
endmodule
module ControlUnit(
    input wire [6:0] Op,
    input wire [2:0] Fn3,
    input wire [6:0] Fn7,
    output wire JalD,
    output wire JalrD,
    output reg [2:0] RegWriteD,
    output wire MemToRegD,
    output reg [3:0] MemWriteD,
    output wire LoadNpcD,
    output reg [1:0] RegReadD,
    output reg [2:0] BranchTypeD,
    output reg [3:0] AluContrlD,
    output wire [1:0] AluSrc2D,
    output wire AluSrc1D,
    output reg [2:0] ImmType        
    );
endmodule
module ALU(
    input wire [31:0] Operand1,
    input wire [31:0] Operand2,
    input wire [3:0] AluContrl,
    output reg [31:0] AluOut
    );
endmodule
module HarzardUnit(
    input wire CpuRst, ICacheMiss, DCacheMiss, 
    input wire BranchE, JalrE, JalD, 
    input wire [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
    input wire [1:0] RegReadE,
    input wire MemToRegE,
    input wire [2:0] RegWriteM, RegWriteW,
    output reg StallF, FlushF, StallD, FlushD, StallE, FlushE, StallM, FlushM, StallW, FlushW,
    output reg [1:0] Forward1E, Forward2E
    );
    //Stall and Flush signals generate

    //Forward Register Source 1

    //Forward Register Source 2

endmodule
module IDSegReg(
    input wire clk,
    input wire clear,
    input wire en,
    //Instrution Memory Access
    input wire [31:0] A,
    output wire [31:0] RD,
    //Instruction Memory Debug
    input wire [31:0] A2,
    input wire [31:0] WD2,
    input wire [3:0] WE2,
    output wire [31:0] RD2,
    //
    input wire [31:0] PCF,
    output reg [31:0] PCD 
    );
    
    initial PCD = 0;
    always@(posedge clk)
        if(en)
            PCD <= clear ? 0: PCF;
    
    wire [31:0] RD_raw;
    InstructionRam InstructionRamInst (
         .clk    (),                        //请完善代码!!!
         .addra  (),                        //请完善代码!!!
         .douta  ( RD_raw     ),
         .web    ( |WE2       ),
         .addrb  ( A2[31:2]   ),
         .dinb   ( WD2        ),
         .doutb  ( RD2        )
     );
    // Add clear and stall support
    // if chip not enabled, output output last read result
    // else if chip clear, output 0
    // else output values from bram
    reg stall_ff= 1'b0;
    reg clear_ff= 1'b0;
    reg [31:0] RD_old=32'b0;
    always @ (posedge clk)
    begin
        stall_ff<=~en;
        clear_ff<=clear;
        RD_old<=RD_raw;
    end    
    assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );

endmodule
module ImmOperandUnit(
    input wire [31:7] In,
    input wire [2:0] Type,
    output reg [31:0] Out
    );
    //
    always@(*)
    begin
        case(Type)
            `ITYPE: Out<={ {21{In[31]}}, In[30:20] };
            //......                                        //请补全!!!
            default:Out<=32'hxxxxxxxx;
        endcase
    end
    
endmodule
module DataExt(
    input wire [31:0] IN,
    input wire [1:0] LoadedBytesSelect,
    input wire [2:0] RegWriteW,
    output reg [31:0] OUT
    );    
endmodule
module BranchDecisionMaking(
    input wire [2:0] BranchTypeE,
    input wire [31:0] Operand1,Operand2,
    output reg BranchE
    );
endmodule
module NPC_Generator(
    input wire [31:0] PCF,JalrTarget, BranchTarget, JalTarget,
    input wire BranchE,JalD,JalrE,
    output reg [31:0] PC_In
    );
endmodule
module InstructionRam(
    input  clk,
    input  web,
    input  [31:2] addra, addrb,
    input  [31:0] dinb,
    output reg [31:0] douta, doutb
);
initial begin douta=0; doutb=0; end

wire addra_valid = ( addra[31:14]==18'h0 );
wire addrb_valid = ( addrb[31:14]==18'h0 );
wire [11:0] addral = addra[13:2];
wire [11:0] addrbl = addrb[13:2];

reg [31:0] ram_cell [0:4095];

initial begin    // you can add simulation instructions here
    ram_cell[0] = 32'h00000000;
        // ......
end

always @ (posedge clk)
    douta <= addra_valid ? ram_cell[addral] : 0;
    
always @ (posedge clk)
    doutb <= addrb_valid ? ram_cell[addrbl] : 0;

always @ (posedge clk)
    if(web & addrb_valid) 
        ram_cell[addrbl] <= dinb;

endmodule
module DataRam(
    input  clk,
    input  [ 3:0] wea, web,
    input  [31:2] addra, addrb,
    input  [31:0] dina , dinb,
    output reg [31:0] douta, doutb
);
initial begin douta=0; doutb=0; end

wire addra_valid = ( addra[31:14]==18'h0 );
wire addrb_valid = ( addrb[31:14]==18'h0 );
wire [11:0] addral = addra[13:2];
wire [11:0] addrbl = addrb[13:2];

reg [31:0] ram_cell [0:4095];

initial begin    // add simulation data here
    ram_cell[0] = 32'h00000000;
    // ......
end

always @ (posedge clk)
    douta <= addra_valid ? ram_cell[addral] : 0;
    
always @ (posedge clk)
    doutb <= addrb_valid ? ram_cell[addrbl] : 0;

always @ (posedge clk)
    if(wea[0] & addra_valid) 
        ram_cell[addral][ 7: 0] <= dina[ 7: 0];
        
always @ (posedge clk)
    if(wea[1] & addra_valid) 
        ram_cell[addral][15: 8] <= dina[15: 8];
        
always @ (posedge clk)
    if(wea[2] & addra_valid) 
        ram_cell[addral][23:16] <= dina[23:16];
        
always @ (posedge clk)
    if(wea[3] & addra_valid) 
        ram_cell[addral][31:24] <= dina[31:24];
        
always @ (posedge clk)
    if(web[0] & addrb_valid) 
        ram_cell[addrbl][ 7: 0] <= dinb[ 7: 0];
                
always @ (posedge clk)
    if(web[1] & addrb_valid) 
        ram_cell[addrbl][15: 8] <= dinb[15: 8];
                
always @ (posedge clk)
    if(web[2] & addrb_valid) 
        ram_cell[addrbl][23:16] <= dinb[23:16];
                
always @ (posedge clk)
    if(web[3] & addrb_valid) 
        ram_cell[addrbl][31:24] <= dinb[31:24];


endmodule
module cpu_tb();
    reg clk = 1'b1;
    reg rst = 1'b1;
    
    always  #2 clk = ~clk;
    initial #8 rst = 1'b0;
    
    RV32Core RV32Core_tb_inst(
        .CPU_CLK    ( clk          ),
        .CPU_RST    ( rst          )
    );
    
endmodule
module IFSegReg(
    input wire clk,
    input wire rst,
    input wire en,
    input wire [31:0] PC_In,
    output reg [31:0] PC
    );
    
    always@(posedge clk or posedge rst)
    begin
        if(rst)
            PC<=32'b0;
        else 
        begin
            if(en)
                PC<=PC_In;
            else
                PC<=PC;        
        end
    end
    
endmodule
module HarzardUnit(
    input wire BranchD, BranchE,
    input wire JalrD, JalrE, JalD,
    input wire [4:0] Rs1D, Rs2D, Rs1E, Rs2E,
    input wire MemToRegE,
    input wire [2:0] RegWriteE, RegWriteM, RegWriteW,
    input wire [4:0] RdE, RdM, RdW,
    input wire ICacheMiss, DCacheMiss ,
    output reg StallF, FlushD, StallD, FlushE, StallE, StallM, StallW,
    output wire Forward1D, Forward2D,
    output reg [1:0] Forward1E, Forward2E
    );
    //
    assign Forward1D=1'b0;
    assign Forward2D=1'b0;
    //Stall and Flush signals generate
    always @ (*)
    begin
        if(DCacheMiss | ICacheMiss)
        begin
            StallF<=1'b1;
            StallD<=1'b1;
            FlushD<=1'b0;
            FlushE<=1'b0;
            StallE<=1'b1;
            StallM<=1'b1;
            StallW<=1'b1;
        end
        else if(BranchE)
        begin
            StallF<=1'b0;
            StallD<=1'b0;
            FlushD<=1'b1;
            FlushE<=1'b0;
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;
        end
        else if(JalrE)
            begin
            StallF<=1'b0;
            StallD<=1'b0;
            FlushD<=1'b1;
            FlushE<=1'b0;
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;
        end
        else if(MemToRegE & ((RdE==Rs1D)||(RdE==Rs2D)) )
            begin
            StallF<=1'b1;
            StallD<=1'b1;
            FlushD<=1'b0;
            FlushE<=1'b1;
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;
        end
        else if(JalrD)
        begin
            StallF<=1'b1;
            StallD<=1'b0;
            FlushD<=1'b1;
            FlushE<=1'b0;
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;
        end
        else if(JalD)
        begin
            StallF<=1'b0;
            StallD<=1'b0;
            FlushD<=1'b1;
            FlushE<=1'b0;        
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;   
        end
        else if(BranchD)
        begin
            StallF<=1'b1;
            StallD<=1'b0;
            FlushD<=1'b1;
            FlushE<=1'b0;
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;
            end
        else
        begin
            StallF<=1'b0;
            StallD<=1'b0;
            FlushD<=1'b0;
            FlushE<=1'b0;
            StallE<=1'b0;
            StallM<=1'b0;
            StallW<=1'b0;
        end
    end
    //ForwardÐÅºÅµÄÊ¹ÓÃ³¡¾°
    always@(*)
    begin
        if( (RegWriteM!=3'b0) && (RdM==Rs1E) &&(RdM!=5'b0) )
            Forward1E<=2'b10;
        else if( (RegWriteW!=3'b0) && (RdW==Rs1E) &&(RdW!=5'b0) )
            Forward1E<=2'b01;
        else
            Forward1E<=2'b00;
    end
    always@(*)
    begin
        if( (RegWriteM!=3'b0) && (RdM==Rs2E) &&(RdM!=5'b0) )
            Forward2E<=2'b10;
        else if( (RegWriteW!=3'b0) && (RdW==Rs2E) &&(RdW!=5'b0) )
            Forward2E<=2'b01;
        else
            Forward2E<=2'b00;
    end      
endmodule
module IDSegReg(
    input wire clk,
    input wire rst,
    input wire clear,
    input wire en,
    //Instrution Memory Access
    input wire [31:0] A,
    output wire [31:0] RD,
    //
    input wire [31:0] PCF,
    output reg [31:0] PCD 
    );
    
    // if chip not enable, output instruction ram read result
    // else if chip clear, output 0
    // else output last read result
    reg stall_or_clear = 1'b0;
    reg  [31:0] stall_or_clear_data = 0;
    wire [31:0] RD_raw;
    assign RD = stall_or_clear ? stall_or_clear_data : RD_raw;
    always @ (posedge clk or posedge rst) begin
        if(rst) begin
            stall_or_clear <= 1'b0;
            stall_or_clear_data <= 0;
        end else begin
            if(~en) begin
                stall_or_clear <= 1'b1;
                stall_or_clear_data <= RD;
            end else if(clear) begin
                stall_or_clear <= 1'b1;
                stall_or_clear_data <= 0;
            end else begin
                stall_or_clear <= 1'b0;
                stall_or_clear_data <= 0;
            end
        end
    end

    always@(posedge clk or posedge rst)
        if(rst)
            PCD <= 0;
        else if(en)
            PCD <= clear ? 0: PCF;
    
    InstructionRamNoCache InstructionRam (
         .clk    ( clk        ),
         .rst    ( rst        ),
         .addra  ( A          ),
         .douta  ( RD_raw     )
     );

    
endmodule
module EXSegReg(
    input wire clk,
    input wire rst,
    input wire en,
    input wire clear,
    //æ°æ®ä¿¡å·
    input wire [31:0] PCD,
    output reg [31:0] PCE, 
    input wire [31:0] BrPCD,
    output reg [31:0] BrPCE, 
    input wire [31:0] ImmD,
    output reg [31:0] ImmE,
    input wire [4:0] RdD,
    output reg [4:0] RdE,
    input wire [4:0] Rs1D,
    output reg [4:0] Rs1E,
    input wire [4:0] Rs2D,
    output reg [4:0] Rs2E,
    input wire [31:0] RegOut1D,
    output reg [31:0] RegOut1E,
    input wire [31:0] RegOut2D,
    output reg [31:0] RegOut2E,
    //æ§å¶ä¿¡å·
    input wire JalrD,
    output reg JalrE,
    input wire [2:0] RegWriteD,
    output reg [2:0] RegWriteE,
    input wire MemToRegD,
    output reg MemToRegE,
    input wire [3:0] MemWriteD,
    output reg [3:0] MemWriteE,
    input wire LoadNpcD,
    output reg LoadNpcE,
    input wire [4:0] AluContrlD,
    output reg [4:0] AluContrlE,
    input wire AluSrc1D,
    output reg AluSrc1E,
    input wire [1:0] AluSrc2D,
    output reg [1:0] AluSrc2E
    );
    //
    always@(posedge clk or posedge rst)
    begin
        if(rst)
            begin
            PCE<=32'b0; 
            BrPCE<=32'b0; 
            ImmE<=32'b0;
            RdE<=32'b0;
            Rs1E<=5'b0;
            Rs2E<=5'b0;
            RegOut1E<=32'b0;
            RegOut2E<=32'b0;
            JalrE<=1'b0;
            RegWriteE<=1'b0;
            MemToRegE<=1'b0;
            MemWriteE<=1'b0;
            LoadNpcE<=1'b0;
            AluContrlE<=5'b0;
            AluSrc1E<=1'b0; 
            AluSrc2E<=2'b0; 
            end
        else if(en)
            if(clear)
                begin
                PCE<=32'b0; 
                BrPCE<=32'b0; 
                ImmE<=32'b0;
                RdE<=32'b0;
                Rs1E<=5'b0;
                Rs2E<=5'b0;
                RegOut1E<=32'b0;
                RegOut2E<=32'b0;
                JalrE<=1'b0;
                RegWriteE<=1'b0;
                MemToRegE<=1'b0;
                MemWriteE<=1'b0;
                LoadNpcE<=1'b0;
                AluContrlE<=5'b0;
                AluSrc1E<=1'b0; 
                AluSrc2E<=2'b0;     
                end
            else
                begin
                PCE<=PCD; 
                BrPCE<=BrPCD; 
                ImmE<=ImmD;
                RdE<=RdD;
                Rs1E<=Rs1D;
                Rs2E<=Rs2D;
                RegOut1E<=RegOut1D;
                RegOut2E<=RegOut2D;
                JalrE<=JalrD;
                RegWriteE=RegWriteD;
                MemToRegE<=MemToRegD;
                MemWriteE<=MemWriteD;
                LoadNpcE<=LoadNpcD;
                AluContrlE<=AluContrlD;
                AluSrc1E<=AluSrc1D;
                AluSrc2E<=AluSrc2D;         
                end                
    end
    
endmodule