module RegDumpProcessor (PHI0, n_RES, RnW, addr_bus, data_bus, regdump_data, regdump_addr);

	input PHI0; 						// Core PHI0
	input n_RES; 						// Core #RES
	output RnW; 						// Core R/W
	output [15:0] addr_bus; 			// Core address bus
	inout [7:0] data_bus; 				// Core data bus
	input [31:0] regdump_data; 			// Data bus for external asynchronous memory where registers dump is stored (`APULogEntry` entries)
	output [23:0] regdump_addr; 		// Address bus for external asynchronous memory

	reg [31:0] phi_dec_cnt; 			// PHI delta down-counter
	reg [31:0] delta_phi_word; 			// word[0] from regdump
	reg [31:0] regop_word; 				// word[1] from regdump
	reg cnt_ovf_reg;
	reg [31:0] addr_cnt; 		// negedge
	wire cntz; 				// 1: Counter is zero
	wire deltanz; 			// 1: Delta PHI is NOT zero
	wire inc_address; 		// 1: Increment addr_cnt

	wire DoRegOp; 			// 1: Issue register operation
	wire LoadPhiCounter;	// 1: Reload PHI decrement counter
	wire [15:0] RegAddress;
	wire [7:0] RegValue; 	// if write
	wire ReadMode; 			// 1: read register

	initial begin
		phi_dec_cnt <= 0;
		delta_phi_word <= 0;
		regop_word <= 0;
		cnt_ovf_reg <= 0;
		addr_cnt <= 0;
	end

	// Counter + control words

	always @(posedge PHI0) begin
		delta_phi_word <= regdump_data;
		if (LoadPhiCounter) regop_word <= 0;
		if (LoadPhiCounter) phi_dec_cnt <= regdump_data >= 2 ? regdump_data - 2 : 0; 	// Take into account 2 cycles on the RegDump logic
		else if (n_RES) phi_dec_cnt <= phi_dec_cnt - 1;
		cnt_ovf_reg <= cntz;
	end

	assign cntz = phi_dec_cnt == 0;
	assign LoadPhiCounter = cnt_ovf_reg & n_RES;
	assign deltanz = delta_phi_word != 0;
	assign DoRegOp = (PHI0 & deltanz & cntz & ~LoadPhiCounter & n_RES);
	assign inc_address = DoRegOp | LoadPhiCounter;

	always @(posedge DoRegOp) begin
		regop_word <= regdump_data;
	end

	always @(negedge inc_address) begin
		if (n_RES) addr_cnt <= addr_cnt + 1;
	end

	// RegOp

	assign RegAddress = 'h4000 | ({11'b0, regop_word[4:0]});
	assign RegValue = regop_word[15:8];
	assign ReadMode = regop_word[7];

	// Default core mode: read address 0

	assign RnW = DoRegOp ? ReadMode : 1'b1;
	assign addr_bus = DoRegOp ? RegAddress : 16'b0;
	assign data_bus = (DoRegOp & ~ReadMode) ? RegValue : 8'bz;
	
	assign regdump_addr = addr_cnt;

endmodule // RegDumpProcessor