Есть модуль ПИ-регулятора, проект собирается на cyclone III, таймквест ругается, выдает слаки.
Код:
Код
module pid
(
input clk,
input use_pid, //Если 1 - включается ПИД-регулятор, иначе выдаем pwm_cur = pwm_fixed
input [24:0] pwm_fixed, //Фиксированное значение ШИМ (используется при use_pid=0)
input start_pulse, //Импульс начала вычислений
input [11:0] ADC_REF, //АЦП уставки, max: 4096 (12 bit)
input [11:0] ADC_FAKT, //АЦП фактическое, max: 4096 (12 bit)
input [15:0] Ki, //Интегральный коэффициент
input [15:0] Kp, //Пропорциональный коэффициент
input [24:0] pwm_min, //Минимальная граница ШИМ
input [24:0] pwm_max, //Макчимальная граница ШИМ
output reg [24:0] pwm_cur, //Выходное значение ШИМ
output reg is_pwm_max, //Если 1 - то ШИМ максимальный
output end_pulse //Импульс окончания вычислений
);
reg signed [25:0] I_reg;
reg signed [26:0] F_reg;
reg signed [24:0] I_prev_reg;
reg [24:0] pwm_fixed_reg;
reg [1:0] F_limits_reg;
reg [1:0] I_limits_reg;
reg [11:0] adc_ref_reg;
reg [11:0] adc_fakt_reg;
reg signed [12:0] err_reg;
reg [9:0] Kp_reg;
reg [9:0] Ki_reg;
initial
begin
I_prev_reg = 25'd1000;
is_pwm_max = 0;
pwm_cur = 0;
end
wire [1:0] w_F_limits;
wire [1:0] w_I_limits;
wire signed [25:0] w_I;
wire signed [23:0] w_P;
wire signed [26:0] w_F;
wire signed [12:0] w_err;
wire w_start_pulse2;
wire w_start_pulse3;
wire w_start_pulse4;
wire w_start_pulse5;
wire w_start_pulse6;
//---------------------------------
// PID-calculating
//---------------------------------
assign w_err =$signed({1'b0, ADC_REF}) - $signed({1'b0, ADC_FAKT}); //max: 13 bit
assign w_I = use_pid? ($signed({1'b0, Ki_reg}) * err_reg + I_prev_reg) : ($signed({1'b0, pwm_fixed_reg})); //max: (10+1) * 13 + 25 = 26 bit
assign w_P = $signed({1'b0, Kp_reg}) * err_reg; //max: (10+1) * 13 = 24 bit
assign w_F = use_pid? (w_I + w_P) : ($signed({1'b0, pwm_fixed_reg})); //max: 26 + 24 = 27 bit;
assign w_F_limits[0] = (w_F < $signed({1'b0, pwm_min}))? 1'b1 : 1'b0;
assign w_F_limits[1] = (w_F > $signed({1'b0, pwm_max}))? 1'b1 : 1'b0;
assign w_I_limits[0] = (w_I < $signed({1'b0, pwm_min}))? 1'b1 : 1'b0;
assign w_I_limits[1] = (w_I > $signed({1'b0, pwm_max}))? 1'b1 : 1'b0;
//============================================
delay delay1(.in(start_pulse),
.clk(clk),
.out(w_start_pulse2));
delay delay2(.in(w_start_pulse2),
.clk(clk),
.out(w_start_pulse3));
delay delay3(.in(w_start_pulse3),
.clk(clk),
.out(w_start_pulse4));
delay delay4(.in(w_start_pulse4),
.clk(clk),
.out(w_start_pulse5));
delay delay5(.in(w_start_pulse5),
.clk(clk),
.out(w_start_pulse6));
delay delay6(.in(w_start_pulse6),
.clk(clk),
.out(end_pulse));
//============================================
always @ (posedge clk)
begin
//========================================
// Начало вычислений, захватываем входные данные
//========================================
if (start_pulse)
begin
Ki_reg = Ki[9:0];
Kp_reg = Kp[9:0];
err_reg <= w_err;
pwm_fixed_reg <= pwm_fixed;
end
//========================================
// Даем 3 такта на вычисления, помещаем результат в регистры
//========================================
else if (w_start_pulse4)
begin
I_reg <= w_I;
F_reg <= w_F;
I_limits_reg <= w_I_limits;
F_limits_reg <= w_F_limits;
end
//========================================
// Выдаем результат, учитывая ограничения
//========================================
else if (w_start_pulse5)
begin
//Ограничиваем выходное воздействие
case (F_limits_reg)
2'b01:
begin
pwm_cur <= pwm_min;
is_pwm_max <= 0;
end
2'b10:
begin
pwm_cur <= pwm_max;
is_pwm_max <= 1;
end
default:
begin
pwm_cur <= F_reg[24:0];
is_pwm_max <= 0;
end
endcase
//Ограничиваем интегральную составляющую
case (I_limits_reg)
2'b01: I_prev_reg <= pwm_min;
2'b10: I_prev_reg <= pwm_max;
default: I_prev_reg <= I_reg[24:0];
endcase
end
end
//============================================
endmodule
(
input clk,
input use_pid, //Если 1 - включается ПИД-регулятор, иначе выдаем pwm_cur = pwm_fixed
input [24:0] pwm_fixed, //Фиксированное значение ШИМ (используется при use_pid=0)
input start_pulse, //Импульс начала вычислений
input [11:0] ADC_REF, //АЦП уставки, max: 4096 (12 bit)
input [11:0] ADC_FAKT, //АЦП фактическое, max: 4096 (12 bit)
input [15:0] Ki, //Интегральный коэффициент
input [15:0] Kp, //Пропорциональный коэффициент
input [24:0] pwm_min, //Минимальная граница ШИМ
input [24:0] pwm_max, //Макчимальная граница ШИМ
output reg [24:0] pwm_cur, //Выходное значение ШИМ
output reg is_pwm_max, //Если 1 - то ШИМ максимальный
output end_pulse //Импульс окончания вычислений
);
reg signed [25:0] I_reg;
reg signed [26:0] F_reg;
reg signed [24:0] I_prev_reg;
reg [24:0] pwm_fixed_reg;
reg [1:0] F_limits_reg;
reg [1:0] I_limits_reg;
reg [11:0] adc_ref_reg;
reg [11:0] adc_fakt_reg;
reg signed [12:0] err_reg;
reg [9:0] Kp_reg;
reg [9:0] Ki_reg;
initial
begin
I_prev_reg = 25'd1000;
is_pwm_max = 0;
pwm_cur = 0;
end
wire [1:0] w_F_limits;
wire [1:0] w_I_limits;
wire signed [25:0] w_I;
wire signed [23:0] w_P;
wire signed [26:0] w_F;
wire signed [12:0] w_err;
wire w_start_pulse2;
wire w_start_pulse3;
wire w_start_pulse4;
wire w_start_pulse5;
wire w_start_pulse6;
//---------------------------------
// PID-calculating
//---------------------------------
assign w_err =$signed({1'b0, ADC_REF}) - $signed({1'b0, ADC_FAKT}); //max: 13 bit
assign w_I = use_pid? ($signed({1'b0, Ki_reg}) * err_reg + I_prev_reg) : ($signed({1'b0, pwm_fixed_reg})); //max: (10+1) * 13 + 25 = 26 bit
assign w_P = $signed({1'b0, Kp_reg}) * err_reg; //max: (10+1) * 13 = 24 bit
assign w_F = use_pid? (w_I + w_P) : ($signed({1'b0, pwm_fixed_reg})); //max: 26 + 24 = 27 bit;
assign w_F_limits[0] = (w_F < $signed({1'b0, pwm_min}))? 1'b1 : 1'b0;
assign w_F_limits[1] = (w_F > $signed({1'b0, pwm_max}))? 1'b1 : 1'b0;
assign w_I_limits[0] = (w_I < $signed({1'b0, pwm_min}))? 1'b1 : 1'b0;
assign w_I_limits[1] = (w_I > $signed({1'b0, pwm_max}))? 1'b1 : 1'b0;
//============================================
delay delay1(.in(start_pulse),
.clk(clk),
.out(w_start_pulse2));
delay delay2(.in(w_start_pulse2),
.clk(clk),
.out(w_start_pulse3));
delay delay3(.in(w_start_pulse3),
.clk(clk),
.out(w_start_pulse4));
delay delay4(.in(w_start_pulse4),
.clk(clk),
.out(w_start_pulse5));
delay delay5(.in(w_start_pulse5),
.clk(clk),
.out(w_start_pulse6));
delay delay6(.in(w_start_pulse6),
.clk(clk),
.out(end_pulse));
//============================================
always @ (posedge clk)
begin
//========================================
// Начало вычислений, захватываем входные данные
//========================================
if (start_pulse)
begin
Ki_reg = Ki[9:0];
Kp_reg = Kp[9:0];
err_reg <= w_err;
pwm_fixed_reg <= pwm_fixed;
end
//========================================
// Даем 3 такта на вычисления, помещаем результат в регистры
//========================================
else if (w_start_pulse4)
begin
I_reg <= w_I;
F_reg <= w_F;
I_limits_reg <= w_I_limits;
F_limits_reg <= w_F_limits;
end
//========================================
// Выдаем результат, учитывая ограничения
//========================================
else if (w_start_pulse5)
begin
//Ограничиваем выходное воздействие
case (F_limits_reg)
2'b01:
begin
pwm_cur <= pwm_min;
is_pwm_max <= 0;
end
2'b10:
begin
pwm_cur <= pwm_max;
is_pwm_max <= 1;
end
default:
begin
pwm_cur <= F_reg[24:0];
is_pwm_max <= 0;
end
endcase
//Ограничиваем интегральную составляющую
case (I_limits_reg)
2'b01: I_prev_reg <= pwm_min;
2'b10: I_prev_reg <= pwm_max;
default: I_prev_reg <= I_reg[24:0];
endcase
end
end
//============================================
endmodule
Модуль delay:
Код
module delay
#(parameter WIDTH = 1)
(
input [WIDTH-1:0] in,
input clk,
output reg [WIDTH-1:0] out
);
always @(posedge clk)
out <= in;
endmodule
#(parameter WIDTH = 1)
(
input [WIDTH-1:0] in,
input clk,
output reg [WIDTH-1:0] out
);
always @(posedge clk)
out <= in;
endmodule
Идея такова: в момент прихода стартового импульса (start_pulse) происходит захват входных значений в регистры, цепочка из элементов delay производит задержку входного сигнала на 6 тактов для того, чтобы вся эта "колбаса" успела посчитаться к моменту выдачи импульса завершения (end_pulse).
Таймквест выдает ошибки:
Но регистр err_reg захватывается на 3 такта раньше чем производится вычисление F_reg, неужели 3 такта недостаточно для умножения?
Файл констрейнов:
Код
derive_clock_uncertainty
create_clock -name clk -period 36.1MHz [get_ports {clk}]
create_generated_clock -name clk_216MHz -source [get_ports {clk}] -multiply_by 6 [get_nets {pll_ena_inst1|pll1|altpll_component|auto_generated|wire_pll1_clk[0]}]
create_generated_clock -name clk_adc -source [get_ports {clk}] -divide_by 17 -multiply_by 15 [get_nets {pll_ena_inst1|pll1|altpll_component|auto_generated|wire_pll1_clk[1]}]
set_false_path -from pll_ena_inst1|pll1|altpll_component|auto_generated|pll1|clk[1] -to adc_inst:adc_inst1|sync:sync_adc|sync[0]
create_clock -name clk -period 36.1MHz [get_ports {clk}]
create_generated_clock -name clk_216MHz -source [get_ports {clk}] -multiply_by 6 [get_nets {pll_ena_inst1|pll1|altpll_component|auto_generated|wire_pll1_clk[0]}]
create_generated_clock -name clk_adc -source [get_ports {clk}] -divide_by 17 -multiply_by 15 [get_nets {pll_ena_inst1|pll1|altpll_component|auto_generated|wire_pll1_clk[1]}]
set_false_path -from pll_ena_inst1|pll1|altpll_component|auto_generated|pll1|clk[1] -to adc_inst:adc_inst1|sync:sync_adc|sync[0]
Какие констрейны прописать для устранения ошибок?
Заранее спасибо!