|
Тернарный оператор VS конструкция if-else, Какова логика языка? Почему одно не заменяет другое? |
|
|
|
Jun 7 2018, 06:53
|
Участник

Группа: Участник
Сообщений: 30
Регистрация: 4-06-18
Пользователь №: 104 848

|
Предположим, есть конечный автомат, который в работе должен пробрасывать тактовую частоту через себя, а в состоянии IDLE установить выход тактовой частоты в единицу. Тогда код может быть следующий: Код wire clk_in; wire clk_out; reg state;
assign clk_out = clk_in | ~(state^IDLE); Т.е. если state и IDLE совпадают бит-в-бит, то их побитовый XOR будет равен нулю. Инвертированный ноль - это единица. Единица или clk_in - единица. В противном случае, ноль или clk_in - это clk_in. Всё абсолютно прозрачно синтезируется. Или код может быть такой: Код wire clk_in; wire clk_out; reg state;
assign clk_out = clk_in | (state == IDLE);//На месте синтезатора я заменил бы данную конструкцию на предыдущую Или такой: Код wire clk_in; wire clk_out; reg state;
assign clk_out =(state == IDLE) ? 1 : clk_in; Но почему не прокатывает следующий вариант? Код wire clk_in; wire clk_out; reg state;
always @(state) begin if(state == IDLE) begin clk_out = 1; end else begin clk_out = clk_in; end end В таком варианте Квартус ругается на то, что "10137: Object on left-hand side of assignment must have a variable data type". Не, ну нельзя, так - нельзя. Но эмм... в списке чувствительности отсутствуют posedge/negedge. В любом случае, синтезатор будет разворачивать эту конструкцию в комбинационную логику (причем, скорее всего в такую, как в первом примере). Так чего же он лезет на рожон (регистр ему подавай)? Какова логика языка? Почему так писать некорректно?
|
|
|
|
|
 |
Ответов
|
Jun 8 2018, 10:20
|
Частый гость
 
Группа: Свой
Сообщений: 134
Регистрация: 9-11-12
Из: г. Брянск
Пользователь №: 74 311

|
Ну вот такой теоретический пример CODE module cnt_test ( //Global input CLK_i , input nRESET_i ,
//Input input IN_PULSE0_i , input IN_PULSE1_i ,
//Control input ENA_CNT_i , input CLR_CNT_i ,
//Output of counter output [31:0] OUT_CNT0_o32 , output [31:0] OUT_CNT1_o32 );
reg [31:0] out_cnt0_o32; reg [31:0] out_cnt1_o32; assign OUT_CNT0_o32 = out_cnt0_o32; assign OUT_CNT1_o32 = out_cnt1_o32;
reg [7:0] state; //FSM localparam integer sIDLE = 0, sCOUNT = 1, sSTOP = 2;
reg cnt_1_en; reg cnt_1_clr;
always @(posedge CLK_i or negedge nRESET_i) begin if(~nRESET_i) begin out_cnt0_o32 <= 0; cnt_1_en <= 0; cnt_1_clr <= 0; state <= sIDLE; end else begin case(state)
sIDLE: begin cnt_1_clr <= 0; if(ENA_CNT_i) state <= sCOUNT; end
sCOUNT: begin if(ENA_CNT_i) begin if(IN_PULSE_i) begin out_cnt0_o32 <= out_cnt0_o32 + 1'b1; cnt_1_en <= 1'b1; end else cnt_1_en <= 0; end else begin cnt_1_en <= 0; state <= sSTOP; end end
sSTOP: begin state <= sIDLE; if(CLR_CNT_i) begin out_cnt0_o32 <= 0; cnt_1_clr <= 1'b1; end end
endcase end
end
always @(posedge CLK_i or negedge nRESET_i) begin if(~nRESET_i) begin out_cnt1_o32 <= 0; end else begin if(cnt_1_en) out_cnt1_o32 <= out_cnt1_o32 + 1'b1; else if(cnt_1_clr) out_cnt1_o32 <= 0; end end
endmodule Два счетчика. Один работает напрямую из автомата, второй через сигналы разрешения и сброса. Насчет упрощения кода при выносе счетчика из автомата я ошибся - проще не получилось. Для работы встроенного счетчика достаточно всего двух строк. Выносного счетчика - целых 5. Вынос счетчика усложнил код. Плюс на выносной счетчик будет работать с задержкой в один такт. И это надо учитывать там, где критично. Но с точки зрения времянок выносной счетчик выиграет. Как раз за счет промежуточных триггеров на сигналах разрешения/сброса. На практике я это не проверял, это просто рассуждения. Warning from admin: Используйте codebox для оформления длинных блоков кода. Не загромождайте сообщения!
Сообщение отредактировал makc - Jun 8 2018, 10:27
Причина редактирования: предупреждение про codebox
|
|
|
|
|
Jun 8 2018, 10:48
|
Профессионал
    
Группа: Свой
Сообщений: 1 214
Регистрация: 23-12-04
Пользователь №: 1 643

|
Приветствую! Цитата(dima32rus @ Jun 8 2018, 13:20)  ... Два счетчика. Один работает напрямую из автомата, второй через сигналы разрешения и сброса. Насчет упрощения кода при выносе счетчика из автомата я ошибся - проще не получилось. Для работы встроенного счетчика достаточно всего двух строк. Выносного счетчика - целых 5. Вынос счетчика усложнил код. И это еще простой случай - а если еще надо загружать разные счетчики разными значениями и считать их вверх/вниз/поперек? Цитата(dima32rus @ Jun 8 2018, 13:20)  Плюс на выносной счетчик будет работать с задержкой в один такт. И это надо учитывать там, где критично. Но с точки зрения времянок выносной счетчик выиграет. Как раз за счет промежуточных триггеров на сигналах разрешения/сброса. Вот оно что - понятное дело если вы пропускаете сигналы управления через регистр то это уменьшает времянку - но это ведь разная логика работы счетчиков!!! При чем тут реализация счетчиков в FSM? Удачи! Rob.
|
|
|
|
|
Jun 8 2018, 11:06
|
Частый гость
 
Группа: Свой
Сообщений: 134
Регистрация: 9-11-12
Из: г. Брянск
Пользователь №: 74 311

|
Цитата(RobFPGA @ Jun 8 2018, 13:48)  Вот оно что - понятное дело если вы пропускаете сигналы управления через регистр то это уменьшает времянку - но это ведь разная логика работы счетчиков!!! При чем тут реализация счетчиков в FSM? Согласен, если через триггеры не пропускать, то, наверное, особой разницы в реализации не будет. Цитата(Flip-fl0p @ Jun 8 2018, 13:50)  Упрощается автомат - банально меньше писанины. И вместо инкрементирования счетчика внутри автомата - автомат выдает сигнал разрешения работы счетчику. Получается, наоборот. Если счетчик внутри автомата - достаточно просто одной строчкой делать инкремент там, где это надо. Если счетчик выносим, то надо выдать сигнал разрешения, а потом его еще снять. Получается 2 и более строк кода на одну только функцию. А еще есть сброс, загрузка...
|
|
|
|
|
Jun 8 2018, 11:26
|

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

|
Цитата(dima32rus @ Jun 8 2018, 14:06)  Согласен, если через триггеры не пропускать, то, наверное, особой разницы в реализации не будет.
Получается, наоборот. Если счетчик внутри автомата - достаточно просто одной строчкой делать инкремент там, где это надо. Если счетчик выносим, то надо выдать сигнал разрешения, а потом его еще снять. Получается 2 и более строк кода на одну только функцию. А еще есть сброс, загрузка... А всё дело в том, что Вы сигнал разрешения выдаете в "синхронной части" автомата. Поэтому ещё надо ещё где-то описать его снятие. Я все делаю в "комбинацонной" части автомата. Примерно вот так: CODE --==================================================================== -- Кобинационная часть работы автомата --==================================================================== output_data : process(all) begin --============================= -- Сигналы по-умолчанию --============================= irdreq <= '0'; -- Запроса на чтение буффера нет aclr_buff <= '0'; -- Беффер не сбрасываем V_offset_ena <= '0'; -- Счет счетчику запрещен V_offset_sld_ena <= '0'; -- Ничего в него не загружаем H_offset_ena <= '0'; -- Счет счетчику запрещен H_offset_sld_ena <= '0'; -- Ничего в него не загружаем case pres_state is -- Анализируем текущее состояние автомата --================================================================================ =============================== when V_offset => -- В состоянии ожидания вертикального смещения if (DE_re = '1') then -- При начале периода активных данных V_offset_ena <= '1'; -- Инкрементируем счетчик вертикального смещения end if; --================================================================================ =============================== when H_offset => -- В состоянии горизонтального смещения H_offset_ena <= '1'; -- Инкрементируем счетчик горизонтального смещения --================================================================================ =============================== when PIP_image => -- В состоянии вывода масштабированного изображения irdreq <= '1'; -- Разрешаем чтение буффера с данными --================================================================================ =============================== when clear_buff => -- В состоянии сброса буффера aclr_buff <= '1'; -- Разрешаем его сброс --================================================================================ =============================== when wait_active_video => -- В состоянии ожидания начала периода активных данных H_offset_sld_ena <= '1'; -- Загружаем в счетчик горизонтального смещения значение этого смещения --================================================================================ =============================== when stop => -- В осостоянии остановки отрисованного изображание V_offset_sld_ena <= '1'; -- Загружаем счетчики необходимым значением смещения H_offset_sld_ena <= '1'; when others => null; end case; end process; А вообще, Вы можете в синхронной части задать значение "по-умолчанию" и в нужном состоянии выдавать сигналы разрешения. Т.е "по-умолчанию" сигнал разрешения снимается. А в каком-то из состояний он выставляется. Получите то-же самое, но только сдвинутое на такт. Более того. При таком стиле как у меня, если комбинационный сигнал зависит только от состояния автомата, то он идет с триггера, защелкнувшего это состояние, если идет кодировка "One-Hot" И выходы автомата у меня получаются сфоримрованны не комбинационной схемой, а триггером  Например сигнал "aclr_buff " - это выход триггера. Соответственно он не имеет иголок, и можно применить как асинхронный сброс. Во всяком случае у Altera DC FIFO имеет только такой тип сброса....
|
|
|
|
Сообщений в этой теме
flammmable Тернарный оператор VS конструкция if-else Jun 7 2018, 06:53 Flip-fl0p Цитата(flammmable @ Jun 7 2018, 09:53)
1... Jun 7 2018, 07:20 iosifk Цитата(Flip-fl0p @ Jun 7 2018, 10:20... Jun 7 2018, 08:14  flammmable Цитата(Flip-fl0p @ Jun 7 2018, 10:20... Jun 7 2018, 10:32   iosifk Цитата(flammmable @ Jun 7 2018, 13:32) Ко... Jun 7 2018, 11:45    flammmable Цитата(iosifk @ Jun 7 2018, 14:45) Для на... Jun 7 2018, 12:26     iosifk Цитата(flammmable @ Jun 7 2018, 15:26) Т.... Jun 7 2018, 12:30      flammmable Цитата(iosifk @ Jun 7 2018, 15:30) Тогда ... Jun 7 2018, 15:17    flammmable Цитата(iosifk @ Jun 7 2018, 14:45) Если В... Jun 13 2018, 08:31     iosifk Цитата(flammmable @ Jun 13 2018, 11:31) к... Jun 13 2018, 08:49   RobFPGA Приветсвую!
Цитата(flammmable @ Jun 7 201... Jun 7 2018, 12:16   sazh Цитата(flammmable @ Jun 7 2018, 13:32) 1.... Jun 7 2018, 19:20  Viktuar Цитата(iosifk @ Jun 7 2018, 09:14) Вот та... Jun 7 2018, 17:27   iosifk Цитата(Viktuar @ Jun 7 2018, 20:27) Прост... Jun 7 2018, 18:18    RobFPGA Приветствую!
Цитата(iosifk @ Jun 7 2018,... Jun 7 2018, 18:39     Bad0512 Цитата(RobFPGA @ Jun 8 2018, 01:39) Приве... Jun 8 2018, 02:18      flammmable Цитата(Bad0512 @ Jun 8 2018, 05:18) Думаю... Jun 8 2018, 05:31       Bad0512 Цитата(flammmable @ Jun 8 2018, 12:31) Бу... Jun 8 2018, 06:58     dima32rus Цитата(RobFPGA @ Jun 7 2018, 21:39) Прост... Jun 8 2018, 06:43      RobFPGA Приветствую!
Цитата(dima32rus @ Jun 8 20... Jun 8 2018, 08:35 RobFPGA Приветсвую!
Цитата(flammmable @ Jun 7 20... Jun 7 2018, 08:05 andrew_b Цитата(flammmable @ Jun 7 2018, 09:53) Пр... Jun 7 2018, 08:22 Dantist2k17 ЦитатаНо почему не прокатывает следующий вариант?
... Jun 7 2018, 11:30 lembrix Цитата(flammmable @ Jun 7 2018, 13:32) Пр... Jun 8 2018, 07:39 Flip-fl0p Цитата(lembrix @ Jun 8 2018, 10:39)
Я бы... Jun 8 2018, 07:43 Flip-fl0p Цитата(dima32rus @ Jun 8 2018, 13:20)
Да... Jun 8 2018, 10:50  RobFPGA Приветствую!
Цитата(Flip-fl0p @ Jun... Jun 8 2018, 11:30   Flip-fl0p Цитата(RobFPGA @ Jun 8 2018, 14:30)
Экон... Jun 8 2018, 11:39    RobFPGA Приветствую!
Цитата(Flip-fl0p @ Jun ... Jun 8 2018, 11:49     Flip-fl0p Цитата(RobFPGA @ Jun 8 2018, 14:49) ....
... Jun 8 2018, 12:08 dima32rus Переделал модуль. Теперь счетчик, вынесенный из ав... Jun 8 2018, 12:19
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|