Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Взаимодействие с сигналом между процесами.
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
Jenya7
В одном процессе есть сигнал обнуляющий счетчик - 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    
     ------------------------------------

Насколько это правильно? Или так делать нельзя?
KalashKS
Так как вы используете ресет, он у вас не будет срабатывать если 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;

Переменные в таком стиле не применял, но так тоже должно синтезнуться.
Jenya7
Цитата(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 клока. поэтому я применил такой подход.
KalashKS
Цитата(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;

Flip-fl0p
Я вообще предпочитаю задерживать сигналы в сдвиговом регистре.
Такой способ самый понятный с точки зрения описания. Подключил сдвиговый регистр в проект, указал разрядность, и назвал его как-нибудь типа RESET_DELAY_SHREG.В итоге код становиться простым, понятным. Так-же разрядность регистра можно вынести в область GENERIC и очень гибко управлять временем задержки.
Счётчик - хорошо когда надо много считать. А когда надо подождать несколько тактов как мне кажется сдвиговый регистр удобнее.
Очень многое еще зависит от максимальной частоты. Были случаи, когда скорости счетчика просто не хватало для счета.
Jenya7
Цитата(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?
Maverick
Цитата(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;
KalashKS
Цитата(Jenya7 @ Jul 18 2017, 09:31) *
тут в чем проблема. кто обнулит сигнал count_rst?

Тот же конечный автомат. Во всех ситуациях, когда его не нужно устанавливать в единицу - устанавливайте в ноль.
Jenya7
Цитата(KalashKS @ Jul 18 2017, 14:41) *
Тот же конечный автомат. Во всех ситуациях, когда его не нужно устанавливать в единицу - устанавливайте в ноль.

понял. спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.