OpenCores
URL https://opencores.org/ocsvn/pid_controller/pid_controller/trunk

Subversion Repositories pid_controller

[/] [pid_controller/] [trunk/] [RTL/] [PID.v] - Rev 11

Go to most recent revision | Compare with Previous | Blame | View Log

/* PID controller
 
sigma=Ki*e(n)+sigma
u(n)=(Kp+Kd)*e(n)+sigma+Kd*(-e(n-1))
 
Data width of Wishbone slave port can be can be toggled between 64-bit, 32-bit and 16-bit.
Address width of Wishbone slave port can be can be modified by changing parameter adr_wb_nb.
 
Wishbone compliant
Work as Wishbone slave, support Classic standard SINGLE/BLOCK READ/WRITE Cycle
 
registers or wires
[15:0]kp,ki,kd,sp,pv;	can be both read and written 
[15:0]kpd;		read only  
[15:0]err[0:1];		read only  
[15:0]mr,md;		not accessable 
[31:0]p,b;			not accessable 
[31:0]un,sigma;		read only 
RS			write 0 to RS will reset err[0], OF, un and sigma
 
 
 
[4:0]of;			overflow register, read only through Wishbone interface, address: 0x40
of[0]==1	:	kpd overflow
of[1]==1	:	err[0] overflow
of[2]==1	:	err[1] overflow
of[3]==1	:	un overflow
of[4]==1	:	sigma overflow
[0:15]rl;			read lock, when asserted corelated reagister can not be read through Wishbone interface
[0:7]wl;			write lock, when asserted corelated reagister can not be written through Wishbone interface
 
 
 
*/
 
`include "PID_defines.v"
 
module	PID #(
`ifdef wb_16bit
parameter	wb_nb=16,
`endif
`ifdef wb_32bit
parameter	wb_nb=32,
`endif
`ifdef wb_64bit
parameter	wb_nb=64,
`endif
		adr_wb_nb=16,
		kp_adr		=	0,
		ki_adr		=	1,
		kd_adr		=	2,
		sp_adr		=	3,
		pv_adr		=	4,
		kpd_adr		=	5,
		err_0_adr		=	6,
		err_1_adr		=	7,
		un_adr		=	8,
		sigma_adr	=	9,
		of_adr		=	10,
		RS_adr		=	11
)(
input	i_clk,
input	i_rst,	//reset when low
//Wishbone Slave port
input	i_wb_cyc,
input	i_wb_stb,
input	i_wb_we,
input	[adr_wb_nb-1:0]i_wb_adr,
input	[wb_nb-1:0]i_wb_data,
output	o_wb_ack,
output	[wb_nb-1:0]o_wb_data,
 
//u(n) output
output	[31:0]o_un,
output	o_valid
);
 
 
 
reg	[15:0]kp,ki,kd,sp,pv;
reg	wla,wlb;	// write locks
wire	wlRS;
assign	wlRS=wla|wlb;
wire	[0:7]wl={{3{wla}},{2{wlb}},3'h0};
 
reg	wack;	//write acknowledged
 
wire	[2:0]adr; // address for write
`ifdef wb_16bit
assign	adr=i_wb_adr[3:1];
`endif
`ifdef wb_32bit
assign	adr=i_wb_adr[4:2];
`endif
`ifdef wb_64bit
assign	adr=i_wb_adr[5:3];
`endif
 
wire	[3:0]adr_1; // address for read
`ifdef	wb_32bit
assign	adr_1=i_wb_adr[5:2];
`endif
`ifdef	wb_16bit
assign	adr_1=i_wb_adr[4:1];
`endif
`ifdef	wb_64bit
assign	adr_1=i_wb_adr[6:3];
`endif
 
 
wire	we;	// write enable
assign	we=i_wb_cyc&i_wb_we&i_wb_stb;
wire	re;	//read enable
assign	re=i_wb_cyc&(~i_wb_we)&i_wb_stb;
 
reg	state_0;  //state machine No.1's state register
 
wire	adr_check_1;	// A '1' means address is within the range of adr_1
`ifdef	wb_32bit
assign	adr_check_1=i_wb_adr[adr_wb_nb-1:6]==0;
`endif
`ifdef	wb_16bit
assign	adr_check_1=i_wb_adr[adr_wb_nb-1:5]==0;
`endif
`ifdef	wb_64bit
assign	adr_check_1=i_wb_adr[adr_wb_nb-1:7]==0;
`endif
 
wire	adr_check;	// A '1' means address is within the range of adr
`ifdef wb_16bit
assign	adr_check=i_wb_adr[4]==0&&adr_check_1;
`endif
`ifdef wb_32bit
assign	adr_check=i_wb_adr[5]==0&&adr_check_1;
`endif
`ifdef wb_64bit
assign	adr_check=i_wb_adr[6]==0&&adr_check_1;
`endif
 
 //state machine No.1
reg	RS;
always@(posedge i_clk or posedge i_rst)
	if(i_rst)begin
		state_0<=0;
		wack<=0;
		kp<=0;
		ki<=0;
		kd<=0;
		sp<=0;
		pv<=0;
		RS<=0;
	end
	else	begin
		if(wack&&(!i_wb_stb)) wack<=0;
		if(RS)RS<=0;
		case(state_0)
		0:	begin
			if(we&&(!wack)) state_0<=1;
		end
		1:	begin
			if(adr_check)begin
				if(!wl[adr])begin
					wack<=1;
					state_0<=0;
					case(adr)
					0:	begin
						kp<=i_wb_data[15:0];
					end
					1:	begin
						ki<=i_wb_data[15:0];
					end
					2:	begin
						kd<=i_wb_data[15:0];
					end
					3:	begin
						sp<=i_wb_data[15:0];
					end
					4:	begin
						pv<=i_wb_data[15:0];
					end
					endcase
 
				end
			end
			else if((adr_1==RS_adr)&&(!wlRS)&&(i_wb_data==0))begin
				wack<=1;
				state_0<=0;
				RS<=1;
			end
			else begin
				wack<=1;
				state_0<=0;
			end
		end
		endcase
	end
 
 
 //state machine No.2
reg	[9:0]state_1;
 
wire	update_kpd;
assign	update_kpd=wack&&(~adr[2])&&(~adr[0])&&adr_check;	//adr==0||adr==2
 
wire	update_esu;	//update e(n), sigma and u(n)
assign	update_esu=wack&&(adr==4)&&adr_check;
 
reg	rla;	// read locks
reg	rlb;
 
 
reg	[4:0]of;
reg	[15:0]kpd;
reg	[15:0]err[0:1];
 
wire	[15:0]mr,md;
 
reg	[31:0]p;
reg	[31:0]a,sigma,un;
 
reg	cout;
wire	cin;
wire	[31:0]sum;
wire	[31:0]product;
 
reg 	start;	//start signal for multiplier
 
reg	[1:0]mr_index;
reg	[1:0]md_index;
assign	mr=	mr_index==1?kpd:
		mr_index==2?kd:ki;
assign	md=	md_index==2?err[1]:
		md_index==1?err[0]:sum[15:0];
 
 
wire	of_addition[0:1];
assign	of_addition[0]=(p[15]&&a[15]&&(!sum[15]))||((!p[15])&&(!a[15])&&sum[15]);
assign	of_addition[1]=(p[31]&&a[31]&&(!sum[31]))||((!p[31])&&(!a[31])&&sum[31]);
 
always@(posedge i_clk or posedge i_rst)
	if(i_rst)begin
		state_1<=12'b000000000001;
		wla<=0;
		wlb<=0;
		rla<=0;
		rlb<=0;
		of<=0;
		kpd<=0;
		err[0]<=0;
		err[1]<=0;
		p<=0;
		a<=0;
		sigma<=0;
		un<=0;
		start<=0;
		mr_index<=0;
		md_index<=0;
		cout<=0;
	end
	else begin
		case(state_1)
		10'b0000000001:	begin
			if(update_kpd)begin
				state_1<=10'b0000000010;
				wla<=1;
				rla<=1;
			end
			else if(update_esu)begin
				state_1<=10'b0000001000;
				wla<=1;
				wlb<=1;	
				rlb<=1;
			end
			else if(RS)begin	//start a new sequance of U(n)
				un<=0;
				sigma<=0;
				of<=0;
				err[0]<=0;
			end
		end
		10'b0000000010:	begin
			p<={{16{kp[15]}},kp};
			a<={{16{kd[15]}},kd};
			state_1<=10'b0000000100;
		end
		10'b0000000100:	begin
			kpd<=sum[15:0];
			wla<=0;
			rla<=0;
			of[0]<=of_addition[0];
			state_1<=10'b0000000001;
		end
		10'b0000001000:	begin
			p<={{16{sp[15]}},sp};
			a<={{16{~pv[15]}},~pv};
			cout<=1;
			start<=1;			// start calculate err0 * ki
			state_1<=10'b0000010000;
		end
		10'b0000010000:	begin
			err[0]<=sum[15:0];
			of[1]<=of_addition[0];
			of[2]<=of[1];
			p<={{16{~err[0][15]}},~err[0]};
			a<={31'b0,1'b1};
			cout<=0;
			mr_index<=1;		// start calculate err0 * kpd	
			md_index<=1;		
			state_1<=10'b0000100000;
		end		
		10'b0000100000:	begin
			err[1]<=sum[15:0];
			mr_index<=2;	// start calculate err1 * kd
			md_index<=2;
			state_1<=10'b0001000000;
		end
		10'b0001000000:	begin
			mr_index<=0;
			md_index<=0;
			start<=0;
			p<=product;	// start calculate err0*ki + sigma_last
			a<=sigma;
			state_1<=10'b0010000000;
		end
		10'b0010000000:	begin
			a<=sum;		// start calculate err0*kpd + sigma_recent
			sigma<=sum;
			of[3]<=of[4]|of_addition[1];
			of[4]<=of[4]|of_addition[1];
			p<=product;
			state_1<=10'b0100000000;
		end
		10'b0100000000:	begin
			a<=sum;		// start calculate err0*kpd + sigma_recent+err1*kd
			of[3]<=of[3]|of_addition[1];
			p<=product;
			state_1<=10'b1000000000;
		end
		10'b1000000000:	begin
			un<=sum;
			of[3]<=of[3]|of_addition[1];
			state_1<=10'b0000000001;
			wla<=0;
			wlb<=0;	
			rlb<=0;
		end
		endcase
	end
 
 
wire	ready;
multiplier_16x16bit_pipelined	multiplier_16x16bit_pipelined(
i_clk,
~i_rst,
start,
md,
mr,
product,
ready
);
 
adder_32bit	adder_32bit_0(
a,
p,
cout,
sum,
cin
);
 
 
wire	[wb_nb-1:0]rdata[0:15];	//wishbone read data array
`ifdef	wb_16bit
assign	rdata[0]=kp;
assign	rdata[1]=ki;
assign	rdata[2]=kd;
assign	rdata[3]=sp;
assign	rdata[4]=pv;
assign	rdata[5]=kpd;
assign	rdata[6]=err[0];
assign	rdata[7]=err[1];
assign	rdata[8]=un[15:0];
assign	rdata[9]=sigma[15:0];
assign	rdata[10]={11'b0,of};
`endif
 
`ifdef	wb_32bit
assign	rdata[0]={{16{kp[15]}},kp};
assign	rdata[1]={{16{ki[15]}},ki};
assign	rdata[2]={{16{kd[15]}},kd};
assign	rdata[3]={{16{sp[15]}},sp};
assign	rdata[4]={{16{pv[15]}},pv};
assign	rdata[5]={{16{kpd[15]}},kpd};
assign	rdata[6]={{16{err[0][15]}},err[0]};
assign	rdata[7]={{16{err[1][15]}},err[1]};
assign	rdata[8]=un;
assign	rdata[9]=sigma;
assign	rdata[10]={27'b0,of};
`endif
 
`ifdef	wb_64bit
assign	rdata[0]={{48{kp[15]}},kp};
assign	rdata[1]={{48{ki[15]}},ki};
assign	rdata[2]={{48{kd[15]}},kd};
assign	rdata[3]={{48{sp[15]}},sp};
assign	rdata[4]={{48{pv[15]}},pv};
assign	rdata[5]={{48{kpd[15]}},kpd};
assign	rdata[6]={{48{err[0][15]}},err[0]};
assign	rdata[7]={{48{err[1][15]}},err[1]};
assign	rdata[8]={{32{un[31]}},un};
assign	rdata[9]={{32{sigma[31]}},sigma};
assign	rdata[10]={59'b0,of};
`endif
 
assign	rdata[11]=0;
assign	rdata[12]=0;
assign	rdata[13]=0;
assign	rdata[14]=0;
assign	rdata[15]=0;
 
 
wire	[0:15]rl;
assign	rl={5'b0,rla,{4{rlb}},rla|rlb,5'b0};
 
wire	rack;	// wishbone read acknowledged
assign	rack=(re&adr_check_1&(~rl[adr_1]))|(re&(~adr_check_1));
 
assign	o_wb_ack=(wack|rack)&i_wb_stb;
 
assign	o_wb_data=adr_check_1?rdata[adr_1]:0;
assign	o_un=un;
assign	o_valid=~rlb;
 
 
endmodule

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.