Пишу ПИ-регулятор, требуется профессиональная критика) Камень - cyclone III, использовано 4 аппаратных умножителя.
Код:
Код
module pid
(
input clk,
input ena,
input signed [15:0] in_ustavka,
input signed [15:0] in_fakt,
input signed [15:0] Ki,
input signed [15:0] Kp,
input signed [15:0] out_min,
input signed [15:0] out_max,
output reg signed [31:0] out
);
reg signed [31:0] I_reg;
reg signed [31:0] F_reg;
reg signed [31:0] I_prev_reg;
reg [1:0] F_limits_reg;
reg [1:0] I_limits_reg;
reg [1:0] ena_reg;
reg state;
initial
begin
ena_reg = 2'b00;
I_prev_reg = 31'd1000;
out = 0;
state = 1'b0;
end
wire ena_risingEdge;
wire [1:0] w_F_limits;
wire [1:0] w_I_limits;
wire signed [31:0] w_F;
wire signed [31:0] w_I;
wire signed [31:0] w_P;
wire signed [15:0] w_err;
//---------------------------------
// Front detector
//---------------------------------
always @(posedge clk)
begin
ena_reg <= {ena_reg[0], ena};
end
assign ena_risingEdge = (ena_reg == 2'b01);
//---------------------------------
// PID-calculating
//---------------------------------
assign w_err = in_ustavka - in_fakt;
assign w_I = Ki*w_err + I_prev_reg;
assign w_P = Kp*w_err;
assign w_F = w_I + w_P;
assign w_F_limits[0] = (w_F < out_min)? 1'b1 : 1'b0;
assign w_F_limits[1] = (w_F > out_max)? 1'b1 : 1'b0;
assign w_I_limits[0] = (w_I < out_min)? 1'b1 : 1'b0;
assign w_I_limits[1] = (w_I > out_max)? 1'b1 : 1'b0;
always @ (posedge clk)
begin
case (state)
//--------------------------------
// Gets I and F values
//--------------------------------
1'b0:
if (ena_risingEdge)
begin
I_reg <= w_I;
F_reg <= w_F;
I_limits_reg <= w_I_limits;
F_limits_reg <= w_F_limits;
state <= 1'b1;
end
else
state <= 1'b0;
//--------------------------------
// Integral and out limitation
//--------------------------------
1'b1:
begin
case (F_limits_reg)
2'b01: out <= out_min;
2'b10: out <= out_max;
default: out <= F_reg;
endcase
case (I_limits_reg)
2'b01: I_prev_reg <= out_min;
2'b10: I_prev_reg <= out_max;
default: I_prev_reg <= I_reg;
endcase
state <= 1'b0;
end
//--------------------------------
default:
state <= 1'b0;
endcase
//--------------------------------
end
(
input clk,
input ena,
input signed [15:0] in_ustavka,
input signed [15:0] in_fakt,
input signed [15:0] Ki,
input signed [15:0] Kp,
input signed [15:0] out_min,
input signed [15:0] out_max,
output reg signed [31:0] out
);
reg signed [31:0] I_reg;
reg signed [31:0] F_reg;
reg signed [31:0] I_prev_reg;
reg [1:0] F_limits_reg;
reg [1:0] I_limits_reg;
reg [1:0] ena_reg;
reg state;
initial
begin
ena_reg = 2'b00;
I_prev_reg = 31'd1000;
out = 0;
state = 1'b0;
end
wire ena_risingEdge;
wire [1:0] w_F_limits;
wire [1:0] w_I_limits;
wire signed [31:0] w_F;
wire signed [31:0] w_I;
wire signed [31:0] w_P;
wire signed [15:0] w_err;
//---------------------------------
// Front detector
//---------------------------------
always @(posedge clk)
begin
ena_reg <= {ena_reg[0], ena};
end
assign ena_risingEdge = (ena_reg == 2'b01);
//---------------------------------
// PID-calculating
//---------------------------------
assign w_err = in_ustavka - in_fakt;
assign w_I = Ki*w_err + I_prev_reg;
assign w_P = Kp*w_err;
assign w_F = w_I + w_P;
assign w_F_limits[0] = (w_F < out_min)? 1'b1 : 1'b0;
assign w_F_limits[1] = (w_F > out_max)? 1'b1 : 1'b0;
assign w_I_limits[0] = (w_I < out_min)? 1'b1 : 1'b0;
assign w_I_limits[1] = (w_I > out_max)? 1'b1 : 1'b0;
always @ (posedge clk)
begin
case (state)
//--------------------------------
// Gets I and F values
//--------------------------------
1'b0:
if (ena_risingEdge)
begin
I_reg <= w_I;
F_reg <= w_F;
I_limits_reg <= w_I_limits;
F_limits_reg <= w_F_limits;
state <= 1'b1;
end
else
state <= 1'b0;
//--------------------------------
// Integral and out limitation
//--------------------------------
1'b1:
begin
case (F_limits_reg)
2'b01: out <= out_min;
2'b10: out <= out_max;
default: out <= F_reg;
endcase
case (I_limits_reg)
2'b01: I_prev_reg <= out_min;
2'b10: I_prev_reg <= out_max;
default: I_prev_reg <= I_reg;
endcase
state <= 1'b0;
end
//--------------------------------
default:
state <= 1'b0;
endcase
//--------------------------------
end
Моделсим: