FPGA: использование как заднего, так и переднего фронта в одном процессе

Я новичок в fpga и vhdl..

Моя среда разработки выглядит следующим образом.

ПЛИС: Спартанский 6 XC6SLX9

Компилятор: ИСЕ 14.04

Симулятор: Изим

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

Следующий код - это то, что я написал. Я ожидал, что w_count будет увеличиваться при каждом спадающем фронте тактового сигнала и сбрасываться на 0, когда w_count достигает N_data во время нарастающего фронта тактового сигнала. В процессе компиляции проблем не возникло, и симуляция тоже работает хорошо, как я и ожидал. Но применительно к реальной fpga w_count увеличивалось для каждого триггера, но не обнулялось при достижении N_data..

w_state_proc : process(r_clk, reset_n_clean)
begin
    if(reset_n_clean = '0') then
        w_count <= 0;
    elsif(r_clk'event and r_clk = '0') then
        if(state = write_state and w_proc = '1') then
            w_count <= w_count + 1;
        end if;
    elsif(r_clk'event and r_clk = '1') then
        if(w_count = N_data) then
            w_count <= 0;
        end if;
    end if;
end process w_state_proc;

Когда я изменил положение двух утверждений elsif, w_count вообще не увеличилось..

w_state_proc : process(r_clk, reset_n_clean)
begin
    if(reset_n_clean = '0') then
        w_count <= 0;
    elsif(r_clk'event and r_clk = '1') then
        if(w_count = N_data) then
            w_count <= 0;
        end if;
    elsif(r_clk'event and r_clk = '0') then
        if(state = write_state and w_proc = '1') then
            w_count <= w_count + 1;
        end if;
    end if;
end process w_state_proc;

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


person YJ Kim    schedule 19.04.2017    source источник
comment
Я подозреваю, что w_proc разрешает ввод?   -  person Staszek    schedule 19.04.2017
comment
да. Это триггер, исходящий из-за пределов FPGA.   -  person YJ Kim    schedule 19.04.2017


Ответы (1)


Ваша FPGA не имеет триггеров с двойной скоростью передачи данных (DDR) в структуре общего назначения, поэтому это не рекомендуется — «как есть» оно не может реализовать желаемую функциональность.

Кроме того, вы используете асинхронный сброс. Хотя это возможно, но также настоятельно не рекомендуется, поскольку FPGA уже имеет триггеры синхронного сброса, и поэтому для него не требуется никакой дополнительной логики, в отличие от ASIC, и вы получите известное значение для каждого сигнала даже без сброса. Асинхронный сброс создаст вам проблемы в достижении закрытия времени так или иначе.

В вашем примере действительно нет необходимости в DDR FF. Казалось бы, причина вашего поведения заключается в том, что w_count может быть очищен между тактовыми циклами, так что w_count никогда не будет N_data при увеличении. Почему бы не сравнить его со значением, которое на единицу меньше?

Или вы можете использовать переменные (очень осторожно!) для достижения очень похожего поведения:

  w_state_proc : process(r_clk) is
    variable v_count : integer range 0 to N_data;
  begin
    if (rising_edge(r_clk)) then
      v_count := w_count;
      if(state = write_state and w_proc = '1') then
        v_count := v_count + 1;
      end if;

      if(reset_n_clean = '0' or v_count = N_data) then
        w_count <= 0;
      else
        w_count <= v_count;
      end if;

    end if;
  end process w_state_proc;

Если вам действительно нужно, чтобы w_count имел значение N_data в течение половины тактового цикла, вы всегда можете сделать часы в два раза быстрее и использовать сигнал включения, активный каждый второй тактовый цикл, и распространять это вместе с вашим трубопровод. Это приведет вас к целому ряду других (очень поучительных) проблем, но выполнимых.

person FritzDC    schedule 19.04.2017