Как взять образцы с помощью FPGA?
Я хочу взять образцы цифровых данных, поступающих извне в FPGA spartan 3. Сначала я хочу взять 1000 выборок / сек. Как выбрать тактовую частоту в VHDL-кодировании?
Благодарю.
3 ответа
Не используйте счетчик для генерации тактового сигнала более низкой частоты.
Многочисленные тактовые частоты в FPGA вызывают множество проблем проектирования, некоторые из которых относятся к разделу "расширенные темы", и, хотя они могут (при необходимости) быть рассмотрены и решены, изучение использования одних быстрых часов является и проще, и в целом лучше практиковать (синхронный дизайн).
Вместо этого используйте любую быструю синхронизацию, которую обеспечивает ваша плата ПЛИС, и генерируйте из нее низкочастотные синхронизирующие сигналы, и, что особенно важно, используйте их как тактовые импульсы, а не тактовые сигналы.
Библиотеки DLL, DCM, PLL и другие диспетчеры тактовых импульсов имеют свое применение, но генерация тактовых сигналов 1 кГц, как правило, нецелесообразна, даже если их ограничения позволяют это. Это приложение просто требует включения часов...
Кроме того, не балуйтесь магическими числами, пусть VHDL-компилятор сделает всю работу! Я поместил требования к времени в пакет, чтобы вы могли поделиться ими с тестовым набором и всем, что нужно для их использования.
package timing is
-- Change the first two constants to match your system requirements...
constant Clock_Freq : real := 40.0E6;
constant Sample_Rate : real := 1000.0;
-- These are calculated from the above, so stay correct when you make changes
constant Divide : natural := natural(Clock_Freq / Sample_Rate);
-- sometimes you also need a period, e.g. in a testbench.
constant clock_period : time := 1 sec / Clock_Freq;
end package timing;
И мы можем записать сэмплер следующим образом: (Я разделил включение часов в отдельный процесс, чтобы пояснить использование разрешений часов, но эти два процесса можно легко объединить в один для некоторого дальнейшего упрощения; сигнал "выборки" будет тогда будет ненужно)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use work.timing.all;
entity sampler is
Port (
Clock : in std_logic;
Reset : in std_logic;
ADC_In : in signed(7 downto 0);
-- signed for audio, or unsigned, depending on your app
Sampled : out signed(7 downto 0);
);
end sampler;
architecture Behavioral of Sampler is
signal Sample : std_logic;
begin
Gen_Sample : process (Clock,Reset)
variable Count : natural;
begin
if reset = '1' then
Sample <= '0';
Count := 0;
elsif rising_edge(Clock) then
Sample <= '0';
Count := Count + 1;
if Count = Divide then
Sample <= '1';
Count := 0;
end if;
end if;
end process;
Sample_Data : process (Clock)
begin
if rising_edge(Clock) then
if Sample = '1' then
Sampled <= ADC_In;
end if;
end if;
end process;
end Behavioral;
Базовая тактовая частота должна быть основана на внешней тактовой частоте и не может быть сгенерирована только с помощью внутренних ресурсов в FPGA Spartan-3. При необходимости вы можете использовать ресурсы Диспетчера цифровых часов (DCM) FPGA Spartan-3 для масштабирования внешних часов. Синтезированный код VHDL сам по себе не может генерировать часы.
Если у вас есть базовый тактовый генератор на более высокой частоте, например 100 МГц, вы можете легко разделить его, чтобы сгенерировать индикацию на частоте 1 кГц для выборки внешнего входа.
Это зависит от того, какая тактовая частота у вас есть. Если у вас есть тактовый источник 20 МГц, вам нужно разделить его на 20000, чтобы получить 1 кГц, вы можете сделать это в VHDL или использовать DCM для этого.
Это пример того, как создать тактовую частоту 1 кГц на входе 20 МГц:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clk20Hz is
Port (
clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
clk_out: out STD_LOGIC
);
end clk200Hz;
architecture Behavioral of clk20Hz is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 10000 := 0;
begin
frequency_divider: process (reset, clk_in) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
elsif rising_edge(clk_in) then
if (counter = 10000) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;