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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> П-И-регулятор
Sprite
сообщение Jun 11 2018, 08:25
Сообщение #1


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

Группа: Участник
Сообщений: 171
Регистрация: 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
Flip-fl0p
сообщение Jun 11 2018, 17:28
Сообщение #2


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

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



Цитата(Sprite @ Jun 11 2018, 11:25) *

Понимаете, код должен быть написан таким образом, чтобы его было можно применить без правок, либо с минимальными правками.
Я бы быстрее написал самостоятельно, чем применил Ваш код. Ибо разбираться, что происходит внутри кода, зачем и почему желания нет никакого...
Вполне возможно, что код отличный. И работает хорошо...
Я обычно проделываю "двойную" работу, и описываю все максимально подробно. И начиню проектирование на листке бумаги. Рисую алгоритмы, блок схемы, графы автоматов. И только потом перевожу на HDL. И не стесняюсь на комментарии. Предпочитаю комментировать так, чтобы листинг можно было читать как книгу.
Ибо практика показала, что я максимум месяц-два помню то, что я написал. Потом забываю начисто. Только сфотографированные листы с которых я начинал проектирование - где описано все что можно, позволяют быстро вспомнить, что было сделано, зачем, почему.
Go to the top of the page
 
+Quote Post
nice_vladi
сообщение Jun 12 2018, 05:40
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 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
Сообщение #4


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

Группа: Свой
Сообщений: 698
Регистрация: 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
Nieve
сообщение Jun 12 2018, 07:02
Сообщение #5





Группа: Участник
Сообщений: 13
Регистрация: 29-04-18
Из: Москва
Пользователь №: 103 558



Использование "case" предпочтительнее (когда это возможно), т.к. при синтезе получается 1 MUX, а при использовании конструкций типа "if ... else" синтезится N-ое количество последовательных MUX-ов. Помимо увеличения логики в схеме, увеличиваются задержки на каждом из элементов.
Go to the top of the page
 
+Quote Post
Sprite
сообщение Jun 12 2018, 07:50
Сообщение #6


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

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



Цитата(nice_vladi @ Jun 12 2018, 12:40) *
Код
    assign w_I = Ki*w_err + I_prev_reg; // 32 бита = (16 бит * 16 бит) + 32 бита -- возможно переполнение

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

Спасибо за замечание! Но значение I_prev_reg, а значит и интегральная составляющая (w_I) у меня ограничивается максимальным и минимальным значениями (out_max и out_min), которые имеют разрядность 16 бит, так что криминала быть не должно.

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

Не совсем понял фразу "щелкает каждый такт", но мысль уловил. Переписал немного добавив регистр (flag):
Код
    reg flag;
    always @ (posedge clk)
    begin
        //--------------------------------
        // Gets I and F values
        //--------------------------------
        if (ena_pulse)
            begin
                I_reg <= w_I;
                F_reg <= w_F;
                I_limits_reg <= w_I_limits;
                F_limits_reg <= w_F_limits;
                flag <= 1'b1;
            end
        //--------------------------------
        // Integral and out limitation
        //--------------------------------
        else if (flag)
        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                        
            flag <= 1'b0;
        end
    end


В чем вообще разница между стэйт-машиной и регистром в данном случае? Что предпочтительнее использовать? Результат симуляции в обоих случаях одинаковый.
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Jun 12 2018, 11:00
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 959
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Flip-fl0p @ Jun 12 2018, 08:53) *
Тут Вы сильно заблуждаетесь.
Во втором случае у вас будет совершенно другая схема синтезироваться, в отличии от case.
Вот тут немного написано про это: https://electronics.stackexchange.com/quest...=google_rich_qa
Сами читали, на что сослались? Всё одно сведётся к логической функции нескольких переменных и ляжет в LUT. Результат будет тот же самый. Соревноваться с оптимизирующим компилятором бессмысленно.
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Jun 12 2018, 18:40
Сообщение #8


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

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



Цитата(andrew_b @ Jun 12 2018, 14:00) *
Сами читали, на что сослались?

Основной смысл - в картинках rolleyes.gif
Цитата
Результат будет тот же самый. Соревноваться с оптимизирующим компилятором бессмысленно.

Тут Вы правы это я немного поспешил. Тут же не приоритетный шифратор. Эх...
Хотя всё-равно считаю, что описывать через case правильнее, с точки зрения стиля написания. Читается проще.
Go to the top of the page
 
+Quote Post
gin
сообщение Jun 14 2018, 07:56
Сообщение #9


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

Группа: Участник
Сообщений: 182
Регистрация: 17-12-10
Пользователь №: 61 682



Цитата(Flip-fl0p @ Jun 12 2018, 21:40) *
Основной смысл - в картинках rolleyes.gif

Тут Вы правы это я немного поспешил. Тут же не приоритетный шифратор. Эх...
Хотя всё-равно считаю, что описывать через case правильнее, с точки зрения стиля написания. Читается проще.


По поводу описания есть еще один не совсем очевидный момент. Не всегда описание, которое принимается синтезатор, может понять симулятор. Иногда при написании кода приходится помнить, что ModelSim понимает не все конструкции (по крайней мере для VHDL так, не знаю как для Verilog).
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Jun 14 2018, 08:08
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 959
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(gin @ Jun 14 2018, 10:56) *
Иногда при написании кода приходится помнить, что ModelSim понимает не все конструкции (по крайней мере для VHDL так, не знаю как для Verilog).
Я уверен, что вас не затруднит подтвердить слова кодом.
Go to the top of the page
 
+Quote Post
gin
сообщение Jun 14 2018, 08:22
Сообщение #11


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

Группа: Участник
Сообщений: 182
Регистрация: 17-12-10
Пользователь №: 61 682



Цитата(andrew_b @ Jun 14 2018, 11:08) *
Я уверен, что вас не затруднит подтвердить слова кодом.


На память могу ошибиться. но вот как щас помню

объявляем сигнал:

Код
signal cnt : natural range 0 to 5


затем его используем в каком-нить процессе:

Код
if (cnt = cnt'high) then


Квартус это проглатывал, а вот Modelsim ругался.
Версию моделсима щас уже не вспомню


Так же моделсим вот на такую контсрукцию ругается

Код
case? <expression> is
    when <constant_expression> =>
        -- Sequential Statement(s)
    when <constant_expression> =>
        -- Sequential Statement(s)
    when others =>
        -- Sequential Statement(s)
end case?;

Go to the top of the page
 
+Quote Post
andrew_b
сообщение Jun 14 2018, 09:32
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 959
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(gin @ Jun 14 2018, 11:22) *
На память могу ошибиться. но вот как щас помню

объявляем сигнал:

Код
signal cnt : natural range 0 to 5


затем его используем в каком-нить процессе:

Код
if (cnt = cnt'high) then


Квартус это проглатывал, а вот Modelsim ругался.
Я тоже на такое натыкался, но лень было выяснять, Моделсим тут прав или нет. Я просто ввёл новый тип.

Цитата
Так же моделсим вот на такую контсрукцию ругается

Код
case? <expression> is
     when <constant_expression> =>
         -- Sequential Statement(s)
     when <constant_expression> =>
         -- Sequential Statement(s)
     when others =>
         -- Sequential Statement(s)
end case?;
Про vhdl'2008 почти ничего не знаю.
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Jun 14 2018, 10:23
Сообщение #13


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

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



Цитата(andrew_b @ Jun 14 2018, 12:32) *
Про vhdl'2008 почти ничего не знаю.

А можно нескромный вопрос. А каковы объективные причины не применять VHDL2008 ? Я пока не встретил каких-либо неудобств, или косяков. Ну кроме разве что не всегда работающего присваивания выходного сигнала с порта, внутрь модуля.
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Jun 14 2018, 12:09
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 959
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Flip-fl0p @ Jun 14 2018, 13:23) *
А можно нескромный вопрос. А каковы объективные причины не применять VHDL2008 ? Я пока не встретил каких-либо неудобств, или косяков.
Во-первых, я не вижe там какого-то особого профита.
Цитата
Ну кроме разве что не всегда работающего присваивания выходного сигнала с порта, внутрь модуля.
А кто виноват?
Вот-вот, синтезатор или не полностью его поддерживает. Или может совсем не поддерживать (в случае, если вы пишете код для АСИКа).
А '93 поддерживают все.
Go to the top of the page
 
+Quote Post
gin
сообщение Jun 14 2018, 13:19
Сообщение #15


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

Группа: Участник
Сообщений: 182
Регистрация: 17-12-10
Пользователь №: 61 682



Цитата(andrew_b @ Jun 14 2018, 12:32) *
Я тоже на такое натыкался, но лень было выяснять, Моделсим тут прав или нет. Я просто ввёл новый тип.

Про vhdl'2008 почти ничего не знаю.


Моделсим его частично поддерживает, по крайней мере в версии 10.2
Там даже отдельный technote есть с описанием того, что и как поддерживается для vhdl2008

Цитата(andrew_b @ Jun 14 2018, 15:09) *
Во-первых, я не вижe там какого-то особого профита.
А кто виноват?
Вот-вот, синтезатор или не полностью его поддерживает. Или может совсем не поддерживать (в случае, если вы пишете код для АСИКа).
А '93 поддерживают все.


В 2008 стандарте есть удобные фишки, тот же список чувствительности процесса можно задать как

Код
process(all)


И case удобно применять для описания приоритетного шифратора. Жизнь упрощает, хотя конечно же и без всего этого можно
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th August 2018 - 13:41
Рейтинг@Mail.ru


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