Счетчик не работает в FPGA

У меня есть компонент VHDL, который подключен к приемнику UART. uart имеет 2 выходных сигнала, один для полученного байта и один для флага, который установлен в 1, когда байт завершен.

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

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;

entity test is
port (
  clk : in std_logic;
  rst : in std_logic;
  ena : in std_logic;
  rx :  in std_logic;
  led0 : out std_logic;
  led1 : out std_logic;
  led2 : out std_logic;
  led3 : out std_logic;
  led4 : out std_logic;
  led5 : out std_logic;
  led6 : out std_logic;
  led7 : out std_logic
);
end test;

architecture arch of test is
    component UART_RX
    generic (
        g_CLKS_PER_BIT : integer := 115     -- Needs to be set correctly
    );
    port (
        i_Clk       : in  std_logic;
        i_RX_Serial : in  std_logic;
        o_RX_DV     : out std_logic;
        o_RX_Byte   : out std_logic_vector(7 downto 0)
    );
   end component;

   signal sig_Din   : std_logic_vector(7 downto 0);
   signal sig_Dout  : std_logic_vector(7 downto 0);
   signal sig_RxErr : std_logic;
   signal sig_RxRdy : std_logic;
   signal sig_TxBusy    : std_logic;
   signal sig_StartTx: std_logic;

   begin

     UUT : UART_RX
     generic map (
        g_CLKS_PER_BIT => 434
     )
     port map (
        i_clk       => clk,
        i_rx_serial => rx,
        o_rx_dv     => sig_RxRdy,
        o_rx_byte   => sig_Dout
    );

    process(clk)
        variable position : integer := 0;
        variable position_v : std_logic_vector(7 downto 0) := "00000000";
    begin
        if(sig_RxRdy = '1') then
            position := position + 1;
            position_v := std_logic_vector((unsigned(position_v1), 1));
            led0 <= position_v(0);
            led1 <= position_v(1);
            led2 <= position_v(2);
            led3 <= position_v(3);
            led4 <= position_v(4);
            led5 <= position_v(5);
            led6 <= position_v(6);
            led7 <= position_v(7);
        end if;
    end process;


end arch;

Есть ли проблемы с реализацией? Каждый новый символ, который я отправляю, приводит к увеличению счетчика более чем на 1. И это даже не одно и то же значение каждый раз. Я, должно быть, не понимаю, как на самом деле работают FPGA, потому что это просто, и я не могу заставить его работать.


person user3013172    schedule 15.06.2018    source источник
comment
Ваш процесс не чувствителен к какому-либо конкретному фронту тактового сигнала. Я не знаю, является ли это решением, но вы определенно должны добавить if rising_edge(clk) или if falling_edge(clk), чтобы процесс запускался только на одном фронте тактов.   -  person Staszek    schedule 15.06.2018
comment
Код неполный. Где position_v1? Что вообще означает std_logic_vector((unsigned(position_v1), 1)). Опубликуйте РАБОТАЮЩИЙ минимально воспроизводимый пример.   -  person JHBonarius    schedule 15.06.2018
comment
Ваш код содержит ошибки и недействителен синтаксически или семантически. Похоже, что вместо position_v := std_logic_vector((unsigned(position_v1), 1)); у вас должно быть position_v := std_logic_vector(to_unsigned(position, 8)); Кроме того, ваш RTL не синтезирует использование переднего фронта clk, вместо этого создает осциллятор релаксации, управляемый sig_RxRdy, используемый в качестве защелки для position с задержкой, обеспечиваемой цепочкой переноса для приращения, отмечая который всегда будет инвертировать хотя бы один бит. См. руководство пользователя XST для получения информации о распознаваемой последовательной логике, чувствительной к переднему фронту.   -  person    schedule 15.06.2018
comment
Извините за мой код, я знаю, что он был неполным, но я думаю, что этого было достаточно, чтобы вы могли понять мою проблему. Большое спасибо, я смог исправить это. Проблема заключалась в том, что я не проверял ни одного края часов. Я добавил это условие, и теперь оно работает как шарм.   -  person user3013172    schedule 22.06.2018


Ответы (1)


Вы используете sig_RxRdy как условие для увеличения. Но мы не можем видеть, как ведет себя этот сигнал, поскольку он выходит из модуля, для которого у нас нет кода.

Судя по поведению, которое вы описываете, выход o_rx_dv (откуда sig_RxRdy), вероятно, будет высоким для более чем одного из ваших циклов clk. Поскольку вход UART поступает от внешнего источника, время, когда он высокий, может быть переменным, что приводит к тому, что приращение вашего счетчика отличается.

Решение состоит в том, чтобы обнаружить нарастающий фронт на sig_RxRdy с помощью задержанной версии:

prev_sig_RxRdy <= sig_RxRdy; 
sig_RxRdy_rising <= sig_RxRdy and not prev_sig_RxRdy;

Затем увеличьте свои счетчики на этом сигнале. Это работает, только если o_rx_dv уже синхронизирован с вашими часами.

person Oldfart    schedule 15.06.2018
comment
Смотрите мой комментарий под вопросом. - person Staszek; 15.06.2018