alex1985 0 11 июня, 2018 Опубликовано 11 июня, 2018 · Жалоба Добрый день всем! Пишу ПИ-регулятор, требуется профессиональная критика) Камень - 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 Моделсим: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 11 июня, 2018 Опубликовано 11 июня, 2018 · Жалоба Понимаете, код должен быть написан таким образом, чтобы его было можно применить без правок, либо с минимальными правками. Я бы быстрее написал самостоятельно, чем применил Ваш код. Ибо разбираться, что происходит внутри кода, зачем и почему желания нет никакого... Вполне возможно, что код отличный. И работает хорошо... Я обычно проделываю "двойную" работу, и описываю все максимально подробно. И начиню проектирование на листке бумаги. Рисую алгоритмы, блок схемы, графы автоматов. И только потом перевожу на HDL. И не стесняюсь на комментарии. Предпочитаю комментировать так, чтобы листинг можно было читать как книгу. Ибо практика показала, что я максимум месяц-два помню то, что я написал. Потом забываю начисто. Только сфотографированные листы с которых я начинал проектирование - где описано все что можно, позволяют быстро вспомнить, что было сделано, зачем, почему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nice_vladi 2 12 июня, 2018 Опубликовано 12 июня, 2018 · Жалоба Добрый день всем! Пишу ПИ-регулятор, требуется профессиональная критика) Камень - cyclone III, использовано 4 аппаратных умножителя. На профессионала не потяну, НО :biggrin: 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 12 июня, 2018 Опубликовано 12 июня, 2018 · Жалоба И вместо кейсов на 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nieve 0 12 июня, 2018 Опубликовано 12 июня, 2018 · Жалоба Использование "case" предпочтительнее (когда это возможно), т.к. при синтезе получается 1 MUX, а при использовании конструкций типа "if ... else" синтезится N-ое количество последовательных MUX-ов. Помимо увеличения логики в схеме, увеличиваются задержки на каждом из элементов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 12 июня, 2018 Опубликовано 12 июня, 2018 · Жалоба 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 В чем вообще разница между стэйт-машиной и регистром в данном случае? Что предпочтительнее использовать? Результат симуляции в обоих случаях одинаковый. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 12 июня, 2018 Опубликовано 12 июня, 2018 · Жалоба Тут Вы сильно заблуждаетесь. Во втором случае у вас будет совершенно другая схема синтезироваться, в отличии от case. Вот тут немного написано про это: https://electronics.stackexchange.com/quest...=google_rich_qa Сами читали, на что сослались? Всё одно сведётся к логической функции нескольких переменных и ляжет в LUT. Результат будет тот же самый. Соревноваться с оптимизирующим компилятором бессмысленно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 12 июня, 2018 Опубликовано 12 июня, 2018 · Жалоба Сами читали, на что сослались? Основной смысл - в картинках :rolleyes: Результат будет тот же самый. Соревноваться с оптимизирующим компилятором бессмысленно. Тут Вы правы это я немного поспешил. Тут же не приоритетный шифратор. Эх... Хотя всё-равно считаю, что описывать через case правильнее, с точки зрения стиля написания. Читается проще. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gin 0 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба Основной смысл - в картинках :rolleyes: Тут Вы правы это я немного поспешил. Тут же не приоритетный шифратор. Эх... Хотя всё-равно считаю, что описывать через case правильнее, с точки зрения стиля написания. Читается проще. По поводу описания есть еще один не совсем очевидный момент. Не всегда описание, которое принимается синтезатор, может понять симулятор. Иногда при написании кода приходится помнить, что ModelSim понимает не все конструкции (по крайней мере для VHDL так, не знаю как для Verilog). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба Иногда при написании кода приходится помнить, что ModelSim понимает не все конструкции (по крайней мере для VHDL так, не знаю как для Verilog).Я уверен, что вас не затруднит подтвердить слова кодом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gin 0 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба Я уверен, что вас не затруднит подтвердить слова кодом. На память могу ошибиться. но вот как щас помню объявляем сигнал: 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?; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба На память могу ошибиться. но вот как щас помню объявляем сигнал: 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 почти ничего не знаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба Про vhdl'2008 почти ничего не знаю. А можно нескромный вопрос. А каковы объективные причины не применять VHDL2008 ? Я пока не встретил каких-либо неудобств, или косяков. Ну кроме разве что не всегда работающего присваивания выходного сигнала с порта, внутрь модуля. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба А можно нескромный вопрос. А каковы объективные причины не применять VHDL2008 ? Я пока не встретил каких-либо неудобств, или косяков.Во-первых, я не вижe там какого-то особого профита. Ну кроме разве что не всегда работающего присваивания выходного сигнала с порта, внутрь модуля.А кто виноват? Вот-вот, синтезатор или не полностью его поддерживает. Или может совсем не поддерживать (в случае, если вы пишете код для АСИКа). А '93 поддерживают все. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gin 0 14 июня, 2018 Опубликовано 14 июня, 2018 · Жалоба Я тоже на такое натыкался, но лень было выяснять, Моделсим тут прав или нет. Я просто ввёл новый тип. Про vhdl'2008 почти ничего не знаю. Моделсим его частично поддерживает, по крайней мере в версии 10.2 Там даже отдельный technote есть с описанием того, что и как поддерживается для vhdl2008 Во-первых, я не вижe там какого-то особого профита. А кто виноват? Вот-вот, синтезатор или не полностью его поддерживает. Или может совсем не поддерживать (в случае, если вы пишете код для АСИКа). А '93 поддерживают все. В 2008 стандарте есть удобные фишки, тот же список чувствительности процесса можно задать как process(all) И case удобно применять для описания приоритетного шифратора. Жизнь упрощает, хотя конечно же и без всего этого можно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться