|
Взаимодействие с сигналом между процесами. |
|
|
|
Jul 17 2017, 05:45
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
В одном процессе есть сигнал обнуляющий счетчик - count_rst. Код COUNTER : process(CLK) begin if (rising_edge(CLK)) then
if (count_rst = '1') then ir_counter <= (others => '0'); ir_prescaler <= (others => '0'); end if; if (count_ena = '1') then if (ir_prescaler = PRESCALE_VAL) then ir_prescaler <= (others => '0'); ir_counter <= not ir_counter; else ir_prescaler <= ir_prescaler + '1'; end if; end if; end if; end process COUNTER; В другом процессе в некоторых состояниях я поднимаю этот сигнал и для того чтоб сигнал подержался пару клоков я делаю так Код IR_PARSE : process(CLK) variable ticks : integer range 0 to 255 := 0; variable bit_idx : integer range 0 to 255 := 0; begin if (rising_edge(CLK)) then if (count_rst = '1') then ticks := ticks + 1; if (ticks > 1) then count_rst <= '0'; ticks := 0; end if; end if;
----------------------------------- --дальше идет State Machine ------------------------------------ Насколько это правильно? Или так делать нельзя?
Сообщение отредактировал Jenya7 - Jul 17 2017, 05:48
|
|
|
|
|
 |
Ответов
(1 - 8)
|
Jul 17 2017, 12:37
|
Местный
  
Группа: Участник
Сообщений: 236
Регистрация: 7-02-11
Пользователь №: 62 755

|
Так как вы используете ресет, он у вас не будет срабатывать если counter_ena='1'. Перепишите процесс в стиле CODE if count_rst='1' then elsif count_ena='1' then end if;
По генерации ресета есть вопрос, где он устанавливается в единицу. Если в процессе IR_PARSE, то в принципе работать будет, хотя мне не нравится такой стить написания. Я бы для повышения читаемости прописал установку ресета там же, где он сбрасывается, например после else. CODE if count_rst='1' then else end if;
Переменные в таком стиле не применял, но так тоже должно синтезнуться.
|
|
|
|
|
Jul 17 2017, 13:11
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(KalashKS @ Jul 17 2017, 18:37)  Так как вы используете ресет, он у вас не будет срабатывать если counter_ena='1'. Перепишите процесс в стиле CODE if count_rst='1' then elsif count_ena='1' then end if;
понял. а если так Код if (count_rst = '1') then ir_counter <= (others => '0'); ir_prescaler <= (others => '0'); else if (count_ena = '1') then if (ir_prescaler = PRESCALE_VAL) then ir_prescaler <= (others => '0'); --every 1us ir_counter <= ir_counter + '1'; else ir_prescaler <= ir_prescaler + '1'; end if; end if; end if; Цитата(KalashKS @ Jul 17 2017, 18:37)  По генерации ресета есть вопрос, где он устанавливается в единицу. Если в процессе IR_PARSE, то в принципе работать будет, хотя мне не нравится такой стить написания. Я бы для повышения читаемости прописал установку ресета там же, где он сбрасывается, например после else. CODE if count_rst='1' then else end if;
Переменные в таком стиле не применял, но так тоже должно синтезнуться. весь процес такой Код IR_PARSE : process(CLK) variable ticks : integer range 0 to 255 := 0; variable bit_idx : integer range 0 to 255 := 0; begin if (rising_edge(CLK)) then if (count_rst = '1') then ticks := ticks + 1; if (ticks > 1) then count_rst <= '0'; end if; end if; case IrState is when IR_ST_IDLE => ir_good <= '0'; count_ena <= '0'; if (ir_rx3 = '0') then bit_idx := 0; count_rst <= '1'; count_ena <= '1'; IrState <= IR_ST_START; end if; when IR_ST_START => --detect start header if (ir_rx3 = '0') then if (ir_counter > HEADER_MAX) then IrState <= IR_ST_IDLE; end if; else --signal goes high if (ir_counter < HEADER_MIN or ir_counter > HEADER_MAX) then --invalid header IrState <= IR_ST_IDLE; else --valid header 2400 us count_rst <= '1'; IrState <= IR_ST_BITS; end if; end if; when IR_ST_BITS => if (bit_idx < MAX_BITS) then if (ir_rx3 = '0') then if (ir_counter > BIT_1_MAX) then IrState <= IR_ST_IDLE; end if; else --signal goes high if (ir_counter > BIT_0_MIN or ir_counter < BIT_0_MAX) then --logic 0 - 600us code(bit_idx) <= '0'; elsif (ir_counter > BIT_1_MIN or ir_counter < BIT_1_MAX) then --logic 1 - 1200us code(bit_idx) <= '1'; else ir_good <= '0'; IrState <= IR_ST_IDLE; end if; count_rst <= '1'; bit_idx := bit_idx + 1; end if; else ir_good <= '1'; IrState <= IR_ST_IDLE; end if; end case; end if; end process IR_PARSE; проблема что сигнал рисета надо обнулять после 1-2 клока. поэтому я применил такой подход.
|
|
|
|
|
Jul 17 2017, 16:12
|
Местный
  
Группа: Участник
Сообщений: 236
Регистрация: 7-02-11
Пользователь №: 62 755

|
Цитата(Jenya7 @ Jul 17 2017, 16:11)  понял. а если так Так, да. Только через elsif немного короче. В следующем процессе (так как написано), должно заработать при обнулении переменной ticks одновременно с установкой count_rst. Кстати, у вас это обнуление вообще куда-то пропало. Хотя и это я это назвал бы костылем. Если нужно продержать сброс в течение двух тактов, я бы на вашем месте выставлял count_rst на один такт, а дальше прощелкнул бы его в еще один регистр, например, так CODE count_rst_reg<=count_rst; if (count_rst = '1' or count_rst_reg='1') then ir_counter <= (others => '0'); ir_prescaler <= (others => '0'); elsif (count_ena = '1') then if (ir_prescaler = PRESCALE_VAL) then ir_prescaler <= (others => '0'); --every 1us ir_counter <= ir_counter + '1'; else ir_prescaler <= ir_prescaler + '1'; end if; end if;
|
|
|
|
|
Jul 18 2017, 06:31
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(KalashKS @ Jul 17 2017, 22:12)  Так, да. Только через elsif немного короче. В следующем процессе (так как написано), должно заработать при обнулении переменной ticks одновременно с установкой count_rst. Кстати, у вас это обнуление вообще куда-то пропало. Хотя и это я это назвал бы костылем. Если нужно продержать сброс в течение двух тактов, я бы на вашем месте выставлял count_rst на один такт, а дальше прощелкнул бы его в еще один регистр, например, так CODE count_rst_reg<=count_rst; if (count_rst = '1' or count_rst_reg='1') then ir_counter <= (others => '0'); ir_prescaler <= (others => '0'); elsif (count_ena = '1') then if (ir_prescaler = PRESCALE_VAL) then ir_prescaler <= (others => '0'); --every 1us ir_counter <= ir_counter + '1'; else ir_prescaler <= ir_prescaler + '1'; end if; end if; тут в чем проблема. кто обнулит сигнал count_rst?
|
|
|
|
|
Jul 18 2017, 06:59
|

я только учусь...
     
Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839

|
Цитата(Flip-fl0p @ Jul 17 2017, 21:30)  Я вообще предпочитаю задерживать сигналы в сдвиговом регистре. Такой способ самый понятный с точки зрения описания. Подключил сдвиговый регистр в проект, указал разрядность, и назвал его как-нибудь типа RESET_DELAY_SHREG.В итоге код становиться простым, понятным. Так-же разрядность регистра можно вынести в область GENERIC и очень гибко управлять временем задержки. Счётчик - хорошо когда надо много считать. А когда надо подождать несколько тактов как мне кажется сдвиговый регистр удобнее. Очень многое еще зависит от максимальной частоты. Были случаи, когда скорости счетчика просто не хватало для счета. если здержка больше 64/128 тактов можно подумать про использование блочной памяти для заержки Код library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;
entity delay_line is generic( W : integer := 8; -- data width L : integer := 1200); -- delay length, shall be > 3 port( i_clk : in std_logic; i_sync_reset : in std_logic; i_data : in std_logic_vector(W-1 downto 0); o_data : out std_logic_vector(W-1 downto 0)); end delay_line;
architecture rtl of delay_line is
type t_ram is array (L-2 downto 0) of std_logic_vector(W-1 downto 0); signal m_ram : t_ram;
signal r_addr_wr : integer range 0 to L-2; signal r_addr_rd : integer range 0 to L-2; signal r_enable_read : std_logic;
begin
p_write : process (i_clk) begin if rising_edge(i_clk) then if(i_sync_reset='1') then r_addr_wr <= 0; r_enable_read <= '0'; else m_ram(r_addr_wr) <= i_data; if(r_addr_wr<L-2) then r_addr_wr <= r_addr_wr + 1; else r_addr_wr <= 0; r_enable_read <= '1'; -- enable reading section end if; end if; end if; end process p_write;
p_read : process (i_clk) begin if rising_edge(i_clk) then if(i_sync_reset='1') then r_addr_rd <= 0; else if(r_enable_read='1') then o_data <= m_ram(r_addr_rd); -- additional delay if(r_addr_rd<L-2) then r_addr_rd <= r_addr_rd + 1; else r_addr_rd <= 0; end if; end if; end if; end if; end process p_read;
end rtl;
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
Jul 18 2017, 08:41
|
Местный
  
Группа: Участник
Сообщений: 236
Регистрация: 7-02-11
Пользователь №: 62 755

|
Цитата(Jenya7 @ Jul 18 2017, 09:31)  тут в чем проблема. кто обнулит сигнал count_rst? Тот же конечный автомат. Во всех ситуациях, когда его не нужно устанавливать в единицу - устанавливайте в ноль.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|