Added separate counter top register to PWM devices. This stores the full mask allowing more control over the clock frequency. Also fixed a number of PWM issues including that data could not be read from registers, and that if the top value is set to a value under the current counter value the counter would not reset.
diff --git a/verilog/rtl/Peripherals/PWM/PWMDevice.v b/verilog/rtl/Peripherals/PWM/PWMDevice.v
index 4bbff18..fb7a8ca 100644
--- a/verilog/rtl/Peripherals/PWM/PWMDevice.v
+++ b/verilog/rtl/Peripherals/PWM/PWMDevice.v
@@ -14,7 +14,7 @@
 		output wire peripheralBus_busy,
 		input wire[15:0] peripheralBus_address,
 		input wire[3:0] peripheralBus_byteSelect,
-		output wire[31:0] peripheralBus_dataRead,
+		output reg[31:0] peripheralBus_dataRead,
 		input wire[31:0] peripheralBus_dataWrite,
 		output wire requestOutput,
 		
@@ -24,15 +24,19 @@
 		output wire pwm_irq
 	);
 
-	localparam WIDTH_BITS = $clog2(WIDTH);
 	localparam CLOCK_BITS = $clog2(CLOCK_WIDTH);
 
+	wire counterEnable;
+	wire[CLOCK_BITS-1:0] clockScale;
+	wire[OUTPUTS-1:0] compareEnable;
+	wire[OUTPUTS-1:0] outputEnable;
+	wire[OUTPUTS-1:0] riseInterruptEnable;
+	wire[OUTPUTS-1:0] fallInterruptEnable;
+
 	// Counter control
 	reg[CLOCK_WIDTH + WIDTH - 1:0] baseCounter = 'b0;
 	wire[CLOCK_WIDTH + WIDTH - 1:0] nextCounter = baseCounter + 1;
 	wire[WIDTH-1:0] counterValue = baseCounter >> clockScale;
-	wire[WIDTH:0] topBitMaskFull = { {WIDTH{1'b1}} << topBit, 1'b0 };
-	wire[WIDTH-1:0] topBitMask = topBitMaskFull[WIDTH-1:0];
 
 	// Device select
 	wire[11:0] localAddress;
@@ -44,31 +48,29 @@
 		.deviceEnable(deviceEnable));
 
 	// Register
-	// Configuration register 	 Default 0x3DC (for .WIDTH(16), .CLOCK_WIDTH(32))
-	// b00: counterEnable		 Default 0x0
-	// b01-b05: clockScale		 Default 0x0E
-	// b06-09: top 				 Default 0xF
+	// Configuration register 	 Default 0x000003 (for .CLOCK_WIDTH(32))
+	// b00-b04: clockScale		 Default 0x03
+	// b05: counterEnable		 Default 0x0
+	// b06: compareEnable0		 Default 0x0
+	// b07: compareEnable1		 Default 0x0
+	// b08: compareEnable2		 Default 0x0
+	// b09: compareEnable3		 Default 0x0
 	// b10: outputEnable0		 Default 0x0
 	// b11: outputEnable1		 Default 0x0
 	// b12: outputEnable2		 Default 0x0
 	// b13: outputEnable3		 Default 0x0
-	// b14: outputEnable0		 Default 0x0
-	// b15: outputEnable1		 Default 0x0
-	// b16: outputEnable2		 Default 0x0
-	// b17: outputEnable3		 Default 0x0
-	// b18: riseInterruptEnable0 Default 0x0
-	// b19: riseInterruptEnable1 Default 0x0
-	// b20: riseInterruptEnable2 Default 0x0
-	// b21: riseInterruptEnable3 Default 0x0
-	// b22: fallInterruptEnable0 Default 0x0
-	// b23: fallInterruptEnable1 Default 0x0
-	// b24: fallInterruptEnable2 Default 0x0
-	// b25: fallInterruptEnable3 Default 0x0
-	localparam CONFIG_WIDTH = 1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 4);
+	// b14: riseInterruptEnable0 Default 0x0
+	// b15: riseInterruptEnable1 Default 0x0
+	// b16: riseInterruptEnable2 Default 0x0
+	// b17: riseInterruptEnable3 Default 0x0
+	// b18: fallInterruptEnable0 Default 0x0
+	// b19: fallInterruptEnable1 Default 0x0
+	// b20: fallInterruptEnable2 Default 0x0
+	// b21: fallInterruptEnable3 Default 0x0
+	localparam CONFIG_WIDTH = 1 + CLOCK_BITS + (OUTPUTS * 4);
 	wire[CONFIG_WIDTH-1:0] configuration;
 	wire[31:0] configurationRegisterOutputData;
 	wire configurationRegisterOutputRequest;
-	ConfigurationRegister #(.WIDTH(CONFIG_WIDTH), .ADDRESS(12'h000), .DEFAULT({CONFIG_WIDTH{12'h3DC}})) configurationRegister(
 	ConfigurationRegister #(.WIDTH(CONFIG_WIDTH), .ADDRESS(12'h000), .DEFAULT({ {(CONFIG_WIDTH-5){1'b0}}, 5'h0E })) configurationRegister(
 		.clk(clk),
 		.rst(rst),
@@ -82,13 +84,41 @@
 		.requestOutput(configurationRegisterOutputRequest),
 		.currentValue(configuration));
 
-	wire counterEnable = configuration[0];
-	wire[CLOCK_BITS-1:0] clockScale = configuration[CLOCK_BITS:1];
-	wire[WIDTH_BITS-1:0] topBit = configuration[CLOCK_BITS + WIDTH_BITS:1 + CLOCK_BITS];
-	wire[OUTPUTS-1:0] compareEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + OUTPUTS)-1:1 + CLOCK_BITS + WIDTH_BITS];
-	wire[OUTPUTS-1:0] outputEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 2))-1:1 + CLOCK_BITS + WIDTH_BITS + OUTPUTS];
-	wire[OUTPUTS-1:0] riseInterruptEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 3))-1:1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 2)];
-	wire[OUTPUTS-1:0] fallInterruptEnable = configuration[(1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 4))-1:1 + CLOCK_BITS + WIDTH_BITS + (OUTPUTS * 3)];
+	assign clockScale = configuration[CLOCK_BITS-1:0];
+	assign counterEnable = configuration[CLOCK_BITS];
+	assign compareEnable = configuration[(1 + CLOCK_BITS + OUTPUTS)-1:1 + CLOCK_BITS];
+	assign outputEnable = configuration[(1 + CLOCK_BITS + (OUTPUTS * 2))-1:1 + CLOCK_BITS + OUTPUTS];
+	assign riseInterruptEnable = configuration[(1 + CLOCK_BITS + (OUTPUTS * 3))-1:1 + CLOCK_BITS + (OUTPUTS * 2)];
+	assign fallInterruptEnable = configuration[(1 + CLOCK_BITS + (OUTPUTS * 4))-1:1 + CLOCK_BITS + (OUTPUTS * 3)];
+
+	// Counter top compare Default 0x1388 (for .WIDTH(16))
+	// With clockScale=0x03, this gives a 1kHz signal with a 200ns resolution
+	localparam DEFAULT_TOP_COMPARE_VALUE = 'h1388;
+	wire[31:0] topCompareRegisterOutputData;
+	wire topCompareRegisterOutputRequest;
+	wire topCompareRegisterBusBusy_nc;
+	wire[WIDTH-1:0] topCompareRegisterWriteData;
+	wire topCompareRegisterWriteDataEnable;
+	wire topCompareRegisterReadDataEnable_nc;
+	reg[WIDTH-1:0] topCompare;
+	DataRegister #(.WIDTH(WIDTH), .ADDRESS(12'h004)) topCompareRegister(
+		.clk(clk),
+		.rst(rst),
+		.enable(deviceEnable),
+		.peripheralBus_we(peripheralBus_we),
+		.peripheralBus_oe(peripheralBus_oe),
+		.peripheralBus_busy(topCompareRegisterBusBusy_nc),
+		.peripheralBus_address(localAddress),
+		.peripheralBus_byteSelect(peripheralBus_byteSelect),
+		.peripheralBus_dataWrite(peripheralBus_dataWrite),
+		.peripheralBus_dataRead(topCompareRegisterOutputData),
+		.requestOutput(topCompareRegisterOutputRequest),
+		.writeData(topCompareRegisterWriteData),
+		.writeData_en(topCompareRegisterWriteDataEnable),
+		.writeData_busy(1'b0),
+		.readData(topCompare),
+		.readData_en(topCompareRegisterReadDataEnable_nc),
+		.readData_busy(1'b0));
 
 	// Current data register (for .WIDTH(16), .OUTPUTS(4))
 	// b00-b15: counterValue
@@ -96,17 +126,17 @@
 	wire[OUTPUTS-1:0] outputs;
 	wire[31:0] dataRegisterOutputData;
 	wire dataRegisterOutputRequest;
-	wire dataRegisterBusBust_nc;
+	wire dataRegisterBusBusy_nc;
 	wire[WIDTH+OUTPUTS-1:0] dataRegisterWriteData_nc;
 	wire dataRegisterWriteDataEnable_nc;
 	wire dataRegisterReadDataEnable_nc;
-	DataRegister #(.WIDTH(WIDTH + OUTPUTS), .ADDRESS(12'h004)) dataRegister(
+	DataRegister #(.WIDTH(WIDTH + OUTPUTS), .ADDRESS(12'h008)) dataRegister(
 		.clk(clk),
 		.rst(rst),
 		.enable(deviceEnable),
 		.peripheralBus_we(peripheralBus_we),
 		.peripheralBus_oe(peripheralBus_oe),
-		.peripheralBus_busy(dataRegisterBusBust_nc),
+		.peripheralBus_busy(dataRegisterBusBusy_nc),
 		.peripheralBus_address(localAddress),
 		.peripheralBus_byteSelect(peripheralBus_byteSelect),
 		.peripheralBus_dataWrite(peripheralBus_dataWrite),
@@ -120,17 +150,45 @@
 		.readData_busy(1'b0));
 
 	always @(posedge clk) begin
-		if (rst || |(counterValue & topBitMask) || !counterEnable) baseCounter <= 'b0;
-		else if (counterEnable) baseCounter <= nextCounter;
+		if (rst) begin
+			baseCounter <= 'b0;
+			topCompare <= DEFAULT_TOP_COMPARE_VALUE;
+		end else begin
+			if (topCompareRegisterWriteDataEnable) begin
+				baseCounter <= 'b0;
+				topCompare <= topCompareRegisterWriteData;
+			end else begin
+				if (counterEnable) begin
+					if (nextCounter == topCompare) baseCounter <= 'b0;
+					else baseCounter <= nextCounter;
+				end else begin
+					baseCounter <= 'b0;
+				end
+			end
+		end
 	end
 
 	wire[OUTPUTS-1:0] compareRegisterOutputRequest;
 	wire[(32 * OUTPUTS) - 1:0] compareRegisterOutputData;
+	wire[31:0] compareValuesOutputData;
+	wire compareValuesOutputRequest;
 	Mux #(.WIDTH(32), .INPUTS(OUTPUTS), .DEFAULT(~32'b0)) mux(
 		.select(compareRegisterOutputRequest),
 		.in(compareRegisterOutputData),
-		.out(peripheralBus_dataRead),
-		.outputEnable(requestOutput));
+		.out(compareValuesOutputData),
+		.outputEnable(compareValuesOutputRequest));
+
+	assign requestOutput = configurationRegisterOutputRequest || topCompareRegisterOutputRequest || dataRegisterOutputRequest || compareValuesOutputRequest;
+
+	always @(*) begin
+		case (1'b1)
+			configurationRegisterOutputRequest: peripheralBus_dataRead <= configurationRegisterOutputData;
+			topCompareRegisterOutputRequest: peripheralBus_dataRead <= topCompareRegisterOutputData;
+			dataRegisterOutputRequest: peripheralBus_dataRead <= dataRegisterOutputData;
+			compareValuesOutputRequest: peripheralBus_dataRead <= compareValuesOutputData;
+			default: peripheralBus_dataRead <= 32'b0;
+		endcase
+	end
 
 	wire[OUTPUTS-1:0] compareRise;
 	wire[OUTPUTS-1:0] compareFall;
@@ -141,7 +199,7 @@
 		for (i = 0; i < OUTPUTS; i = i + 1) begin
 			// Compare value register
 			wire[WIDTH-1:0] compareValue;
-			ConfigurationRegister #(.WIDTH(WIDTH), .ADDRESS(12'h008 + (i * 12'h004)), .DEFAULT('b0)) compareRegister(
+			ConfigurationRegister #(.WIDTH(WIDTH), .ADDRESS(12'h010 + (i * 12'h004)), .DEFAULT('b0)) compareRegister(
 				.clk(clk),
 				.rst(rst),
 				.enable(deviceEnable),