VHDL: контр-проверка - PullRequest
       40

VHDL: контр-проверка

0 голосов
/ 28 января 2020

Я хочу обнаружить подключение внешнего сигнала к CPLD (только подключен или не подключен). Моя системная тактовая частота составляет 1 МГц, а внешний сигнал - 4 КГц. Я разработал логи c, которая обнаружит передний фронт внешнего сигнала и запустит счетчик. Если счетчик считает, то внешний сигнал подключен, а если счетчик не считает, то внешний сигнал не подключен. Я пишу код, но он не работает, в чем проблема? Я новичок в VHDL. Помогите пожалуйста, как проверить счетчик, работающий в vhdl?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SYNC_detection1 is
Port (  SYNC        : in  STD_LOGIC;
            CLK     : in  STD_LOGIC;
            EDGE        : out  STD_LOGIC;
            OUTPUT  : out  STD_LOGIC;
            BITSOUT : out  STD_LOGIC_VECTOR (3 downto 0)
                );
end SYNC_detection1;

architecture workingarchi of SYNC_detection1 is

signal SYNC_reg : std_LOGIC := '0';
signal SYNC_edge : std_LOGIC := '0';
signal TEMP : std_LOGIC := '0';
signal counter : STD_LOGIC_VECTOR (3 downto 0);

begin

SYNC_edge_p : process(CLK) 
begin
    if (rising_edge(CLK)) then
        SYNC_reg <= SYNC;
    end if;
end process;

SYNC_edge <= not SYNC_reg and SYNC;

counter_p: process(CLK) 
begin
    if (rising_edge(CLK)) then
        if SYNC_edge = '1' then
            counter <= counter + 1; 
                if (counter = "0000") then
                TEMP <= '1';
                end if;
        end if;
    end if;
end process;

OUTPUT <= TEMP;
BITSOUT <= counter;
EDGE <= SYNC_edge;
end workingarchi;

Ответы [ 2 ]

0 голосов
/ 30 января 2020

Прежде всего, вы управляете внешними часами и хотите обработать их с вашими внутренними часами 1 МГц, для этого приложения вы должны использовать блок синхронизации.

Я буду действовать следующим образом. Управляйте внешним сигналом SYN C как часами и используйте его для подсчета восходящего_размера, другой совет - избегать подсчета std_logic_vector (использование целого числа для подсчета делает код более читабельным)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity SYNC_detection1 is
Port (  SYNC        : in  STD_LOGIC;
            EDGE        : out  STD_LOGIC;
            OUTPUT  : out  STD_LOGIC;
            BITSOUT : out  STD_LOGIC_VECTOR (3 downto 0)
                );
end SYNC_detection1;

architecture workingarchi of SYNC_detection1 is


signal SYNC_edge : std_LOGIC := '0';
signal TEMP : std_LOGIC := '0';
signal counter : integer := 0;

begin

SYNC_edge_p : process(SYNC) 
begin
    SYNC_edge <= '0';
    if (rising_edge(SYNC)) then
        counter <= counter + 1; 
        SYNC_edge <= '1';
        if (counter = 0) then
            TEMP <= '1';
        end if;
    end if;
end process;

    OUTPUT <= TEMP;
    BITSOUT <= std_logic_vector(to_unsigned(counter, BITSOUT'length));
    EDGE <= SYNC_edge;

end workingarchi;

С этим Реализация Теперь у вас есть выходные сигналы в тактовой области 4 кГц, вам просто нужно добавить блок синхронизации для каждой выходной линии с тактовой частотой источника 4 кГц и тактовой частотой назначения 1 МГц.

Для блока синхронизации просто в качестве ссылки я пишу следующий блок, который может синхронизировать ребро:

library ieee;
use ieee.std_logic_1164.all;

entity edge_sync is
    port(
         data    : in std_logic;
         clk_src : in std_logic;
         clk_dst : in std_logic;
         line_out: out std_logic
    );

end edge_sync;


architecture beha of edge_sync is

    component ff_D is
        port(   
                lineD : in std_logic;
                clk   : in std_logic;
                lineQ : out std_logic
        );
    end component ff_D;    

   signal input_s : std_logic := '0';
   signal meta  : std_logic:= '0';
   signal Q2_D3 : std_logic:= '0';
   signal Q3    : std_logic:= '0';

begin

   FFsrc  : ff_D port map (
                  lineD => input_s,
                  clk => clk_src,
                  lineQ => meta
              ); 

   FFdst1 : ff_D port map(
                  lineD => meta,
                  clk   => clk_dst  ,
                  lineQ => Q2_D3
              );

   FFdst2 : ff_D port map(
                  lineD => Q2_D3,
                  clk   => clk_dst  ,
                  lineQ => Q3
              );

   input_s <= data;

   line_out <=   (not Q3)  and Q2_D3;

end beha;

Но в режиме онлайн вы можете найти другие реализации.

Из вашего кода:

SYNC_edge <= не SYNC_reg и SYNC; </p>

Эта строка может работать, только если SYN C изменяется между передними фронтами CLK. Вы уверены, что не генерируете 2 такта синхронно? Если 2 такта генерируются с нулевой фазой, так как они кратны, вы никогда не получите границу между нарастающими фронтами CLK, в результате чего вы не увидите изменения SYNC_edge.

PS Вы столкнулись с двумя основными fpga предметы, пересечение области часов и управление метастабильностью, я предлагаю вам изучить теоретический материал об этих аргументах. Это может помочь вам сосредоточиться на аппаратных аспектах, а также на кодировании VHDL.

С уважением

0 голосов
/ 28 января 2020

Если вы просто хотите проверить, что счетчик работает, и вы не хотите писать тестовую среду, что вам, кстати, следует сделать, вы можете поставить условие if, если счетчик равен 1, то повернуть привели в вашу доску. что-то вроде этого:

if counter = "0001" then
  led <= '1';
end if;

если светодиод включен, то ваш счетчик работает.

...