реклама на сайте
подробности

 
 
> П-И-регулятор
Sprite
сообщение Jun 11 2018, 08:25
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Добрый день всем!
Пишу ПИ-регулятор, требуется профессиональная критика) Камень - 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

Моделсим:

Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
nice_vladi
сообщение Jun 12 2018, 05:40
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 7-09-16
Из: Томск
Пользователь №: 93 239



Цитата(Sprite @ Jun 11 2018, 09:25) *
Добрый день всем!
Пишу ПИ-регулятор, требуется профессиональная критика) Камень - cyclone III, использовано 4 аппаратных умножителя.

На профессионала не потяну, НО biggrin.gif

Код
    assign w_I = Ki*w_err + I_prev_reg; // 32 бита = (16 бит * 16 бит) + 32 бита -- возможно переполнение

Всегда дико заморочно следить за разрядностями, но иногда из-за этого все ломается.

А вместо машины на два состояния, которая щелкает каждый такт (если я правильно понял) можно сделать простой однобитный счетчик, который будет по какому-то событию перекидываться 0-1-0-1... мне кажется и лаконичнее и писанины меньше (хотя, наверное, дело религии).

И вместо кейсов на 2-3 состояния красивше писать if-else. Опять же лаконичнее и писанины меньше (но, наверное, это тоже дела религиозные))).
Т.е. получаем вместо:
Код
case (F_limits_reg)
    2'b01:        out <= out_min;
     2'b10:         out <= out_max;
     default:    out <= F_reg;
endcase


Что-то вроде:

Код
    if (F_limits_reg == 2'b01)         out <= out_min;
    else if (F_limits_reg == 2'b10)  out <= out_max;
      else                                     out <= F_reg;





Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Jun 12 2018, 05:53
Сообщение #3


В поисках себя...
****

Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Цитата(nice_vladi @ Jun 12 2018, 08:40) *
И вместо кейсов на 2-3 состояния красивше писать if-else. Опять же лаконичнее и писанины меньше (но, наверное, это тоже дела религиозные))).
Т.е. получаем вместо:
Код
case (F_limits_reg)
    2'b01:        out <= out_min;
     2'b10:         out <= out_max;
     default:    out <= F_reg;
endcase


Что-то вроде:

Код
    if (F_limits_reg == 2'b01)         out <= out_min;
    else if (F_limits_reg == 2'b10)  out <= out_max;
      else                                     out <= F_reg;


Тут Вы сильно заблуждаетесь.
Во втором случае у вас будет совершенно другая схема синтезироваться, в отличии от case.
Вот тут немного написано про это: https://electronics.stackexchange.com/quest...=google_rich_qa
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 03:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.02145 секунд с 7
ELECTRONIX ©2004-2016