module YD_reg (
	input wire clk,  //时钟
	input wire rst,  //高电平同步复位
	input wire jpc,	//流水线气泡,高电平可写PC
	input wire dsv, //数据总线访问指示
//输入口0
	input wire [15:0]din0,
	input wire [3:0]waddr0,
	input wire we0,
//输入口1
	input wire [15:0]din1,
	input wire [3:0]waddr1,
	input wire we1,
//输出口0
	input wire [3:0]raddr0,
	output reg [15:0]dout0,//寄存器读取,数据输出线,always@(*)只能给reg赋值
//输出口1
	input wire [3:0]raddr1,
	output reg [15:0]dout1,//寄存器读取,数据输出线,always@(*)只能给reg赋值
//PC输出
	output reg [15:0]PC,//PC值会直接输出
	output reg [15:0]DKD//直接输出DK或写入值
);
//寄存器组定义
reg [15:0]RX[12:0];
reg [15:0]DK;
//内部必要连线
reg [3:0]raddr0_r;//读地址0打一拍
reg [3:0]raddr1_r;//读地址1打一拍
reg [3:0]waddr0_r;//写地址0打一拍
reg [3:0]waddr1_r;//写地址1打一拍
reg we0_r;//写使能0打一拍
reg we1_r;//写使能1打一拍
reg [15:0]din0_r;//写数据0打一拍
reg [15:0]din1_r;//写数据1打一拍
reg [15:0]dout0_r;//寄存器读取,数据输出线,always@(*)只能给reg赋值
reg [15:0]dout1_r;//
//定义寄存器组地址
localparam ZEA=4'b0000;
localparam DKA=4'b0001;
localparam R0A=4'b0010;
//R0-RC依次排列
localparam PCA=4'b1111;

//寄存器写入
always @(posedge clk) begin
if(rst) begin//寄存器复位
	DK <= 16'h0;
	PC <= 16'h0;
	RX[0] <= 16'h0;
	RX[1] <= 16'h0;
	RX[2] <= 16'h0;
	RX[3] <= 16'h0;
	RX[4] <= 16'h0;
	RX[5] <= 16'h0;
	RX[6] <= 16'h0;
	RX[7] <= 16'h0;
	RX[8] <= 16'h0;
	RX[9] <= 16'h0;
	RX[10] <= 16'h0;
	RX[11] <= 16'h0;
	RX[12] <= 16'h0;
	end 
else begin
	if(~jpc && ~dsv)//不跳转
		PC <= PC+16'h1;
	if(we0&&we1&&(waddr0==waddr1)) begin//写地址冲突,优先写端口0
		case(waddr0)
			ZEA:;//ZE永远为0
			DKA:DK <= din0;
			PCA:if(jpc) PC <= din0;//即将跳转
			default:RX[waddr0-R0A] <= din0;
			endcase 
		end
	else begin//无冲突,正常写
		if(we0) begin//端口0写
			case(waddr0)
				ZEA:;
				DKA:DK <= din0;
				PCA:if(jpc) PC <= din0;//即将跳转
				default:RX[waddr0-R0A] <= din0;
				endcase 
			end
		if(we1) begin//端口1写
			case(waddr1)
				ZEA:;
				DKA:DK <= din1;
				PCA:if(jpc) PC <= din1;//即将跳转
				default:RX[waddr1-R0A] <= din1;
				endcase 
			end
		end
	end
end

//寄存器读取
//读地址打一拍
always @(posedge clk) begin
if(rst) begin
	raddr0_r <= 4'h0;
	raddr1_r <= 4'h0;
	waddr0_r <= 4'h0;
	waddr1_r <= 4'h0;
	din0_r <= 16'h0;
	din1_r <= 16'h0;
	we0_r <= 1'b0;
	we1_r <= 1'b0;
	end 
else begin
	raddr0_r <= raddr0;//读地址0打一拍
	raddr1_r <= raddr1;//读地址1打一拍
	waddr0_r <= waddr0;//写地址0打一拍
	waddr1_r <= waddr1;//写地址1打一拍
	din0_r <= din0;//写数据0打一拍
	din1_r <= din1;//写数据1打一拍
	we0_r <= we0;
	we1_r <= we1;
	end
end
//读取寄存器
always @(*) begin
	case (raddr0_r)
		ZEA:dout0=16'h0;
		DKA:
			if ((raddr0_r==waddr0_r&&we0_r)||(raddr0_r==waddr1_r&&we1_r)) //同步写穿
				if(raddr0_r==waddr0_r&&we0_r)
					dout0=din0_r;
				else if(raddr0_r==waddr1_r&&we1_r)
					dout0=din1_r;
				else
					dout0=DK;
			else
				dout0=DK;
		PCA:
			if (((raddr0_r==waddr0_r&&we0_r)||(raddr0_r==waddr1_r&&we1_r))&&jpc) //同步写穿
				if(raddr0_r==waddr0_r&&we0_r)
					dout0=din0_r;
				else if(raddr0_r==waddr1_r&&we1_r)
					dout0=din1_r;
				else
					dout0=PC;
			else
				dout0=PC;
		default:
			if ((raddr0_r==waddr0_r&&we0_r)||(raddr0_r==waddr1_r&&we1_r))//同步写穿
				if(raddr0_r==waddr0_r&&we0_r)
					dout0=din0_r;
				else if(raddr0_r==waddr1_r&&we1_r)
					dout0=din1_r;
				else
					dout0=RX[raddr0_r-R0A];
			else
				dout0=RX[raddr0_r-R0A];
		endcase

	case (raddr1_r)
		ZEA:dout1_r=16'h0;
		DKA:
			if ((raddr1_r==waddr0_r&&we0_r)||(raddr1_r==waddr1_r&&we1_r)) //同步写穿
				if(raddr1_r==waddr0_r&&we0_r)
					dout1=din0_r;
				else if(raddr1_r==waddr1_r&&we1_r)
					dout1=din1_r;
				else
					dout1=DK;
			else
				dout1=DK;
		PCA:
			if (((raddr1_r==waddr0_r&&we0_r)||(raddr1_r==waddr1_r&&we1_r))&&jpc) //同步写穿
				if(raddr1_r==waddr0_r&&we0_r)
					dout1=din0_r;
				else if(raddr1_r==waddr1_r&&we1_r)
					dout1=din1_r;
				else
					dout1=PC;
			else
				dout1=PC;
		default:
			if ((raddr1_r==waddr0_r&&we0_r)||(raddr1_r==waddr1_r&&we1_r))//同步写穿
				if(raddr1_r==waddr0_r&&we0_r)
					dout1=din0_r;
				else if(raddr1_r==waddr1_r&&we1_r)
					dout1=din1_r;
				else
					dout1=RX[raddr1_r-R0A];
			else
				dout1=RX[raddr1_r-R0A];
		endcase
end

//直接输出DK
always @(*) begin
	if(waddr0==DKA && we0 || waddr1==DKA && we1)//如果同时在写DK
		if(waddr0==DKA && we0)
			DKD=din0;
		else if(waddr1==DKA && we1)
			DKD=din1;
	else
		DKD=DK;
end

/*------- 仅仿真 -------*/
wire [15:0]R0W=RX[0];
wire [15:0]R1W=RX[1];
wire [15:0]R2W=RX[2];
wire [15:0]R3W=RX[3];
wire [15:0]R4W=RX[4];
wire [15:0]R5W=RX[5];
wire [15:0]R6W=RX[6];
wire [15:0]R7W=RX[7];
wire [15:0]R8W=RX[8];
wire [15:0]R9W=RX[9];
wire [15:0]RAW=RX[10];
wire [15:0]RBW=RX[11];
wire [15:0]RCW=RX[12];
/*------- 仅仿真 -------*/
endmodule