Перейти к содержанию
    

Взаимодействие с сигналом между процесами.

В одном процессе есть сигнал обнуляющий счетчик - 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так как вы используете ресет, он у вас не будет срабатывать если counter_ena='1'. Перепишите процесс в стиле

if count_rst='1' then
elsif count_ena='1' then
end if;

По генерации ресета есть вопрос, где он устанавливается в единицу. Если в процессе IR_PARSE, то в принципе работать будет, хотя мне не нравится такой стить написания.

Я бы для повышения читаемости прописал установку ресета там же, где он сбрасывается, например после else.

if count_rst='1' then
else
end if;

Переменные в таком стиле не применял, но так тоже должно синтезнуться.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так как вы используете ресет, он у вас не будет срабатывать если counter_ena='1'. Перепишите процесс в стиле

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;

По генерации ресета есть вопрос, где он устанавливается в единицу. Если в процессе IR_PARSE, то в принципе работать будет, хотя мне не нравится такой стить написания.

Я бы для повышения читаемости прописал установку ресета там же, где он сбрасывается, например после else.

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 клока. поэтому я применил такой подход.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

понял. а если так

Так, да. Только через elsif немного короче.

 

В следующем процессе (так как написано), должно заработать при обнулении переменной ticks одновременно с установкой count_rst. Кстати, у вас это обнуление вообще куда-то пропало. Хотя и это я это назвал бы костылем.

Если нужно продержать сброс в течение двух тактов, я бы на вашем месте выставлял count_rst на один такт, а дальше прощелкнул бы его в еще один регистр, например, так

    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;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я вообще предпочитаю задерживать сигналы в сдвиговом регистре.

Такой способ самый понятный с точки зрения описания. Подключил сдвиговый регистр в проект, указал разрядность, и назвал его как-нибудь типа RESET_DELAY_SHREG.В итоге код становиться простым, понятным. Так-же разрядность регистра можно вынести в область GENERIC и очень гибко управлять временем задержки.

Счётчик - хорошо когда надо много считать. А когда надо подождать несколько тактов как мне кажется сдвиговый регистр удобнее.

Очень многое еще зависит от максимальной частоты. Были случаи, когда скорости счетчика просто не хватало для счета.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так, да. Только через elsif немного короче.

 

В следующем процессе (так как написано), должно заработать при обнулении переменной ticks одновременно с установкой count_rst. Кстати, у вас это обнуление вообще куда-то пропало. Хотя и это я это назвал бы костылем.

Если нужно продержать сброс в течение двух тактов, я бы на вашем месте выставлял count_rst на один такт, а дальше прощелкнул бы его в еще один регистр, например, так

    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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я вообще предпочитаю задерживать сигналы в сдвиговом регистре.

Такой способ самый понятный с точки зрения описания. Подключил сдвиговый регистр в проект, указал разрядность, и назвал его как-нибудь типа 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;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

тут в чем проблема. кто обнулит сигнал count_rst?

Тот же конечный автомат. Во всех ситуациях, когда его не нужно устанавливать в единицу - устанавливайте в ноль.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тот же конечный автомат. Во всех ситуациях, когда его не нужно устанавливать в единицу - устанавливайте в ноль.

понял. спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...