PWM RTL Code from opencores
diff --git a/verilog/rtl/pwm/PWM.v b/verilog/rtl/pwm/PWM.v
new file mode 100644
index 0000000..8653ae6
--- /dev/null
+++ b/verilog/rtl/pwm/PWM.v
@@ -0,0 +1,230 @@
+/*Author: Zhuxu 

+	m99a1@yahoo.cn

+Pulse Width Generators/timers with 16-bit main counter.

+Period or timers target number is controlled by register [15:0]period.

+Duty cycle is controlled by register [15:0]DC.

+Clock used for PWM signal generation can be switched between Wishbone Bus clock and external clock. It is down clocked first.

+o_pwm outputs PWM signal or timers interrupt.

+

+control register [7:0]ctrl:

+bit 0:	When set, external clock is chosen for PWM/timer. When cleared, wb clock is used for PWM/timer.

+bit 1:	When set,  PWM is enabled. When cleared,  timer is enabled.

+bit 2:	When set,  PWM/timer starts. When cleared, PWM/timer stops.

+bit 3:	When set, timer runs continuously. When cleared, timer runs one time.

+bit 4:	When set, o_pwm enabled.

+bit 5:	timer interrupt bit	When it is written with 0, interrupt request is cleared. 

+bit 6:	When set, a 16-bit external signal i_DC is used as duty cycle. When cleared, register DC is used.

+bit 7:	When set, counter reset for PWM/timer, it's output and bit 5 will also be cleared. When changing from PWM mode to timer mode reset is needed before timer starts.

+*/

+

+module	PWM (

+

+input	i_wb_clk,

+input	i_wb_rst,

+input	i_wb_cyc,

+input	i_wb_stb,

+input	i_wb_we,

+input	[15:0]i_wb_adr,

+input	[15:0]i_wb_data,

+output	[15:0]o_wb_data,

+output	o_wb_ack,

+

+input	[15:0]i_DC,

+input	i_valid_DC,

+output	o_pwm

+

+);

+

+////////////////////control logic////////////////////////////

+parameter	adr_ctrl=0,

+		adr_divisor=2,

+		adr_period=4,

+		adr_DC=6;

+reg	[7:0]ctrl;

+reg	[15:0]period;

+reg	[15:0]DC;

+reg	[15:0]divisor;	

+integer	i;

+wire	write;

+wire	pwm;

+reg	[1:0]state;

+reg	clrint;		

+wire	ack_clrint;	

+wire	int1;		

+

+assign	write=i_wb_cyc&i_wb_stb&i_wb_we;

+assign	o_wb_ack=i_wb_stb;

+

+always@(posedge i_wb_clk or posedge i_wb_rst)

+	if(i_wb_rst) begin

+		ctrl[4:0]<=0;

+		ctrl[7:6]<=0;

+		DC<=0;

+		period<=0;

+		divisor<=0;	

+	end

+	else if(write) begin

+		case(i_wb_adr)

+			adr_ctrl:begin

+				ctrl[4:0]<=i_wb_data[4:0];

+				ctrl[7:6]<=i_wb_data[7:6];

+			end

+			adr_divisor: divisor<=i_wb_data;

+			adr_period: period<=i_wb_data;

+			adr_DC: DC<=i_wb_data;

+		endcase

+	end

+

+assign	pwm = ctrl[1];

+

+always@(posedge i_wb_clk or posedge i_wb_rst)

+	if(i_wb_rst)begin

+		ctrl[5]<=0;

+		state<=0;

+		clrint<=0;

+	end

+	else begin

+		case(state)			

+			1:begin

+				if(write)begin

+					if(i_wb_data[7])begin

+						ctrl[5]<=0;

+						state<=0;

+					end

+					else if(!i_wb_data[5])begin

+						ctrl[5]<=0;

+						if(!pwm)begin

+							clrint<=1;

+							state<=2;

+						end

+						else state<=0;

+					end

+				end

+			end

+			2:if(ack_clrint)begin

+				clrint<=0;

+				state<=0;	

+			end

+			default:begin

+				if(!pwm)ctrl[5]<=int1;

+				if(int1)state<=1;

+			end

+		endcase

+	end

+

+

+///////////////////////////////////////////////////////////

+

+//////down clocking for pwm/timer///////////////////

+wire	clk_source;

+wire	eclk,oclk;

+assign	clk_source= i_wb_clk;

+down_clocking_even	down_clocking_even_0(

+clk_source,

+(!i_wb_rst),

+{1'b0,divisor[15:1]},

+eclk

+);

+down_clocking_odd	down_clocking_odd_0(

+clk_source,

+(!i_wb_rst),

+{1'b0,divisor[15:1]},

+oclk

+);

+wire	clk;

+assign	clk=divisor[0]?oclk:eclk;

+///////////////////////////////////////////////////////

+

+/////////////////main counter //////////////////////////

+reg	[15:0]ct;

+reg	pts;	//PWM signal or timer interrupt signal

+reg	[15:0]extDC;

+wire	[15:0]DC_1;

+assign	DC_1=ctrl[6]? extDC:DC;	//external or internal duty cycle toggle

+wire	[15:0]period_1;

+assign	period_1= (period==0) ? 0:(period-1);

+reg	switch_ack_clrint;

+wire	state_timer;

+assign	state_timer=ctrl[3];

+wire	rst_ct;

+assign	rst_ct=i_wb_rst|ctrl[7];

+assign	int1=pwm?0:pts;

+assign	ack_clrint=switch_ack_clrint?clrint:0;

+always@(posedge clk or posedge rst_ct)

+	if(rst_ct)begin

+		pts<=0;

+		ct<=0;

+		switch_ack_clrint<=0;

+		extDC<=0;

+	end

+	else begin

+	if(i_valid_DC)

+		extDC<=i_DC;

+	if(switch_ack_clrint&&(!clrint))

+		switch_ack_clrint<=0;

+	if(ctrl[2])begin

+		case(pwm)

+			1:begin

+				if(ct>=period_1)

+					ct<=0;

+				else 

+					ct<=ct+1;

+

+				if(ct<DC_1)

+					pts<=1;

+				else 

+					pts<=0;

+			end

+			0:begin

+

+				case(state_timer)

+					0:begin

+						if(clrint)

+							switch_ack_clrint<=1;

+						if(ct>=period_1)begin

+							if(clrint)begin

+								pts<=0;

+								ct<=0;	

+							end

+							else 

+								pts<=1;

+							

+						end

+						else 

+							ct<=ct+1;

+					end

+					1:begin

+						if(ct>=period_1)begin

+							pts<=1;

+							ct<=0;

+						end

+						else begin

+							if(clrint)begin

+								switch_ack_clrint<=1;

+								pts<=0;

+							end

+							ct<=ct+1;

+						end

+					end

+				endcase

+			end

+		endcase

+	end

+	else if(clrint)begin

+		switch_ack_clrint<=1;

+		if(!pwm)begin

+			pts<=0;

+			ct<=0;

+		end

+	end

+	end

+//////////////////////////////////////////////////////////

+

+assign	o_pwm=ctrl[4]?pts:0;

+assign	o_wb_data=	i_wb_adr==adr_ctrl?{8'h0,ctrl}:

+			i_wb_adr==adr_divisor?divisor:

+			i_wb_adr==adr_period?period:

+			i_wb_adr==adr_DC?DC:0;

+

+

+endmodule

diff --git a/verilog/rtl/pwm/down_clocking_even.v b/verilog/rtl/pwm/down_clocking_even.v
new file mode 100644
index 0000000..bfebb01
--- /dev/null
+++ b/verilog/rtl/pwm/down_clocking_even.v
@@ -0,0 +1,37 @@
+/*Down clocking module

+Output clock frequency is the original frequency divided by an even number

+*/

+module	down_clocking_even(

+input	i_clk,

+input	i_rst,

+input	[15:0]i_divisor,

+output	o_clk

+);

+

+wire	[15:0]divisor;

+wire	borrow;

+

+minus_one	minus_one_0(

+i_divisor,

+divisor,

+borrow

+);

+

+wire	go;

+assign	go=((i_divisor!=0)&&i_rst);

+reg	[15:0]ct;

+reg	clk;

+always@(posedge i_clk or negedge i_rst)

+	if(!i_rst)begin

+		ct<=0;

+		clk<=0;

+	end

+	else if(go)begin

+		if(ct>=divisor)begin

+			ct<=0;

+			clk<=~clk;

+		end

+		else ct<=ct+1;

+	end

+assign	o_clk=go?clk:i_clk;

+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/pwm/down_clocking_odd.v b/verilog/rtl/pwm/down_clocking_odd.v
new file mode 100644
index 0000000..52f48de
--- /dev/null
+++ b/verilog/rtl/pwm/down_clocking_odd.v
@@ -0,0 +1,69 @@
+/*Author: Zhuxu

+	m99a1@yahoo.cn

+Down clocking module

+Output clock frequency is the original frequency divided by an odd number

+*/

+module down_clocking_odd(

+input	i_clk,

+input	i_rst,

+input	[15:0]i_divisor,

+output	o_clk

+);

+

+reg	a,b;

+wire	c;

+

+assign	c=(~a)&(~b);

+wire	[15:0]divisor;

+wire	borrow;

+minus_one	minus_one_0(

+i_divisor,

+divisor,

+borrow

+);

+

+wire	go;

+assign	go=((i_divisor!=0)&&i_rst);

+reg	[15:0]ct_0;

+always@(posedge i_clk or negedge i_rst)

+	if(!i_rst)begin

+		a<=0;

+		ct_0<=0;	

+	end

+	else if(go)begin

+		if(a)begin

+			if(ct_0>=divisor)begin

+				ct_0<=0;

+				a<=0;

+			end

+			else ct_0<=ct_0+1;

+		end

+		else if(c)a<=c;

+	end

+

+

+reg	[15:0]ct_1;

+always@(negedge i_clk or negedge i_rst)

+	if(!i_rst)begin

+		b<=0;

+		ct_1<=0;	

+	end

+	else if(go)begin

+		if(b)begin

+			if(ct_1>=divisor)begin

+				ct_1<=0;

+				b<=0;

+			end

+			else ct_1<=ct_1+1;

+		end

+		else if(c)b<=c;

+	end

+

+reg	clk;

+always@(posedge c or negedge i_rst)

+	if(!i_rst)clk<=0;

+	else	clk<=~clk;

+

+assign	o_clk=go?clk:i_clk;

+

+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/pwm/minus_one.v b/verilog/rtl/pwm/minus_one.v
new file mode 100644
index 0000000..f3575c9
--- /dev/null
+++ b/verilog/rtl/pwm/minus_one.v
@@ -0,0 +1,122 @@
+/*Author: Zhuxu

+	m99a1@yahoo.cn

+Use parallel prefix tree structure to reduce a 16-bit number by one.

+

+stage 0:	number of genration=16;	number of logic operation=16;	G_0[xx]=~i_operand[xx];

+stage 1:	NOG=16;			NOO=8;				G_1[2n-1]=G_0[2n-1]&&G_0[2n-2];	n=8:1

+stage 2:	NOG=16;			NOO=7;				G_2[2n-1]=G_1[2n-1]&&G_1[2n-3];	n=8:2

+stage 3:	NOG=16;			NOO=6;				G_3[2n-1]=G_2[2n-1]&&G_2[2n-5];	n=8:3	

+stage 4:	NOG=16;			NOO=4;				G_4[2n-1]=G_3[2n-1]&&G_3[2n-9];	n=8:5	

+stage 5:	NOG=16;			NOO=7;				G_5[2n]=G_4[2n]&&G_4[2n-1];	n=7:1

+

+*/

+module minus_one(

+input	[15:0]i_operand,

+output	[15:0]o_result,

+output	o_borrow

+);

+//stage 0

+wire	[15:0]G_0;

+assign	G_0=~i_operand;

+

+//stage 1

+wire	[15:0]G_1;

+assign	G_1[1]=G_0[1]&G_0[0];

+assign	G_1[3]=G_0[3]&G_0[2];

+assign	G_1[5]=G_0[5]&G_0[4];

+assign	G_1[7]=G_0[7]&G_0[6];

+assign	G_1[9]=G_0[9]&G_0[8];

+assign	G_1[11]=G_0[11]&G_0[10];

+assign	G_1[13]=G_0[13]&G_0[12];

+assign	G_1[15]=G_0[15]&G_0[14];

+assign	G_1[0]=G_0[0];

+assign	G_1[2]=G_0[2];

+assign	G_1[4]=G_0[4];

+assign	G_1[6]=G_0[6];

+assign	G_1[8]=G_0[8];

+assign	G_1[10]=G_0[10];

+assign	G_1[12]=G_0[12];

+assign	G_1[14]=G_0[14];

+

+//stage 2

+wire	[15:0]G_2;

+assign	G_2[3]=G_1[3]&G_1[1];

+assign	G_2[5]=G_1[5]&G_1[3];

+assign	G_2[7]=G_1[7]&G_1[5];

+assign	G_2[9]=G_1[9]&G_1[7];

+assign	G_2[11]=G_1[11]&G_1[9];

+assign	G_2[13]=G_1[13]&G_1[11];

+assign	G_2[15]=G_1[15]&G_1[13];

+assign	G_2[0]=G_1[0];

+assign	G_2[2]=G_1[2];

+assign	G_2[1]=G_1[1];

+assign	G_2[4]=G_1[4];

+assign	G_2[6]=G_1[6];

+assign	G_2[8]=G_1[8];

+assign	G_2[10]=G_1[10];

+assign	G_2[12]=G_1[12];

+assign	G_2[14]=G_1[14];

+

+//stage 3

+wire	[15:0]G_3;

+assign	G_3[5]=G_2[5]&G_2[1];

+assign	G_3[7]=G_2[7]&G_2[3];

+assign	G_3[9]=G_2[9]&G_2[5];

+assign	G_3[11]=G_2[11]&G_2[7];

+assign	G_3[13]=G_2[13]&G_2[9];

+assign	G_3[15]=G_2[15]&G_2[11];

+assign	G_3[0]=G_2[0];

+assign	G_3[2]=G_2[2];

+assign	G_3[1]=G_2[1];

+assign	G_3[4]=G_2[4];

+assign	G_3[3]=G_2[3];

+assign	G_3[6]=G_2[6];

+assign	G_3[8]=G_2[8];

+assign	G_3[10]=G_2[10];

+assign	G_3[12]=G_2[12];

+assign	G_3[14]=G_2[14];

+

+//stage 4

+wire	[15:0]G_4;

+assign	G_4[9]=G_3[9]&G_3[1];

+assign	G_4[11]=G_3[11]&G_3[3];

+assign	G_4[13]=G_3[13]&G_3[5];

+assign	G_4[15]=G_3[15]&G_3[7];

+assign	G_4[0]=G_3[0];

+assign	G_4[2]=G_3[2];

+assign	G_4[1]=G_3[1];

+assign	G_4[4]=G_3[4];

+assign	G_4[3]=G_3[3];

+assign	G_4[6]=G_3[6];

+assign	G_4[5]=G_3[5];

+assign	G_4[8]=G_3[8];

+assign	G_4[7]=G_3[7];

+assign	G_4[10]=G_3[10];

+assign	G_4[12]=G_3[12];

+assign	G_4[14]=G_3[14];

+

+//stage 5

+wire	[15:0]G_5;

+assign	G_5[2]=G_4[2]&G_4[1];

+assign	G_5[4]=G_4[4]&G_4[3];

+assign	G_5[6]=G_4[6]&G_4[5];

+assign	G_5[8]=G_4[8]&G_4[7];

+assign	G_5[10]=G_4[10]&G_4[9];

+assign	G_5[12]=G_4[12]&G_4[11];

+assign	G_5[14]=G_4[14]&G_4[13];

+assign	G_5[1]=G_4[1];

+assign	G_5[3]=G_4[3];

+assign	G_5[5]=G_4[5];

+assign	G_5[7]=G_4[7];

+assign	G_5[9]=G_4[9];

+assign	G_5[11]=G_4[11];

+assign	G_5[13]=G_4[13];

+assign	G_5[15]=G_4[15];

+assign	G_5[0]=G_4[0];

+

+//stage 6

+assign	o_result[0]=~i_operand[0];

+assign	o_result[15:1]=(G_5[14:0]&(~i_operand[15:1]))|((~G_5[14:0])&i_operand[15:1]);

+assign	o_borrow=G_5[15];

+

+endmodule
\ No newline at end of file