Почему бы не использовать Xilinx Clock Manager IP?
Артурс Vancans
Ответы:
19
В принципе, есть два способа сделать это. Во-первых, использовать ядро синтезатора часов Xilinx. Одним из преимуществ этого является то, что инструменты Xlinx распознают часы как таковые и направят их через необходимые пути. Инструменты также будут обрабатывать любые временные ограничения (в данном случае это не совсем применимо, поскольку это тактовая частота 2 Гц)
Второй способ - использовать счетчик для подсчета количества более быстрых тактовых импульсов, пока не пройдет половина вашего более медленного тактового периода. Например, для вашего случая число быстрых тактовых импульсов, составляющих один тактовый период медленного тактового цикла, составляет 50000000/2 = 25000000. Поскольку мы хотим половину тактового периода, это 25000000/2 = 12500000 для каждого полупериода. , (продолжительность каждого максимума или минимума).
Вот как это выглядит в VHDL:
library IEEE;use IEEE.STD_LOGIC_1164.all;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.all;entity scale_clock isport(
clk_50Mhz :instd_logic;
rst :instd_logic;
clk_2Hz :outstd_logic);end scale_clock;architecture Behavioral of scale_clock issignal prescaler :unsigned(23downto0);signal clk_2Hz_i :std_logic;begin
gen_clk :process(clk_50Mhz, rst)begin-- process gen_clkif rst ='1'then
clk_2Hz_i <='0';
prescaler <=(others=>'0');elsif rising_edge(clk_50Mhz)then-- rising clock edgeif prescaler =X"BEBC20"then-- 12 500 000 in hex
prescaler <=(others=>'0');
clk_2Hz_i <=not clk_2Hz_i;else
prescaler <= prescaler +"1";endif;endif;endprocess gen_clk;
clk_2Hz <= clk_2Hz_i;end Behavioral;
Что следует отметить:
Сгенерированные часы равны нулю во время сброса. Это нормально для некоторых приложений, а не для других, это просто зависит от того, для чего вам нужны часы.
Сгенерированные часы будут направлены как обычный сигнал инструментами синтеза Xilinx.
2 Гц очень медленно. Имитация на секунду займет некоторое время. Это небольшой объем кода, поэтому симуляция должна быть относительно быстрой даже в течение 1 секунды, но если вы начнете добавлять код, то время, необходимое для имитации тактового цикла 2 Гц, может быть значительно большим.
EDIT: clk_2Hz_i используется для буферизации выходного сигнала. VHDL не любит использовать сигнал справа от назначения, когда он также является выходом.
Неплохо, но вы можете добавить / сравнить unsigned с целым числом, так что: if prescaler = 50_000_000/4 then ...и prescaler <= prescaler + 1;будет немного проще.
Брайан Драммонд
@StaceyAnne Пытаясь это, я получаю "Не могу прочитать из объекта" out "clk_o; использовать" буфер "или" inout "" я что-то пропустил?
уклонение от
@evading, необходим буфер на выходе. VHDL не нравится тот факт, что clk_2Hzэто выход, но все же его значение читается в этой строке clk_2Hz <= not clk_2Hz;. Я редактировал в исправлении.
Стэнри
+1 Отличный пример. Но вот где мое невежество показывает (новичок в VHDL). В чем разница между prescaler <= (others => '0');и prescaler <= '0';?
cbmeeks
NVM! Я полностью пропустил то, что othersиспользовалось, когда читал книгу VHDL, которую я имею. Это просто ярлык для объявления всех «других» битов общим значением вместо использования чего-то вроде «000000000000000000 ....» и т. Д.
cbmeeks
9
Используйте предварительный пересчет часов.
Ваше предварительное значение будет вашим (clock_speed / требуемый_clock_speed) / 2 так (50 МГц (50 000 000) / 2 Гц (2)) / 2 = 12 500 000, что в двоичном виде будет 101111101011110000100000.
Кажется, вы генерируете два тактовых импульса, один из которых 0,5 Гц, а другой - 1 Гц? (так как ваш тактовый период - ваш прескалер * 2?). Кроме того, «+» выдаст ошибку, так как вы добавляете slvs, и я не очень уверен в том, чтобы использовать свойство переполнения add таким образом в любом случае. почему бы просто не пойти newClock : std_logic := '0', сосчитать до prescaler / 2 и назначить newClk <= not newClk?
Станри
Спасибо, моя логика была немного не в порядке. Я обновил свой первоначальный пост с некоторым протестированным кодом и несколькими вашими предложениями :)
MLM
Тьфу - все эти нули и комментарий, чтобы сказать, что это на самом деле! Почему бы не использовать компилятор, чтобы сделать это для вас ??? И почему бы просто не использовать целые числа?
Мартин Томпсон
Возможно, я ошибаюсь, но я думаю, что использование значений по умолчанию при определении сигналов в архитектуре, таких как ": = (others => '0')", невозможно синтезировать.
Артурс Vancans
Он синтезируемый, но в основном работает только на FPGA на основе SRAM, как и большинство из Xilinx, Altera или Lattice.
Ян Вернье
8
Обычно вы не хотите синхронизировать что-либо медленное, просто создайте разрешение с правильной скоростью и используйте это в логике:
Он имеет графический интерфейс настроек, где вы можете указать, какую частоту вы хотите. Он сгенерирует компонент с желаемым выходом в качестве частоты.
Его можно найти в мастере IP;
И тогда вы сможете указать, какую частоту вы хотите:
Ответы:
В принципе, есть два способа сделать это. Во-первых, использовать ядро синтезатора часов Xilinx. Одним из преимуществ этого является то, что инструменты Xlinx распознают часы как таковые и направят их через необходимые пути. Инструменты также будут обрабатывать любые временные ограничения (в данном случае это не совсем применимо, поскольку это тактовая частота 2 Гц)
Второй способ - использовать счетчик для подсчета количества более быстрых тактовых импульсов, пока не пройдет половина вашего более медленного тактового периода. Например, для вашего случая число быстрых тактовых импульсов, составляющих один тактовый период медленного тактового цикла, составляет 50000000/2 = 25000000. Поскольку мы хотим половину тактового периода, это 25000000/2 = 12500000 для каждого полупериода. , (продолжительность каждого максимума или минимума).
Вот как это выглядит в VHDL:
Что следует отметить:
EDIT: clk_2Hz_i используется для буферизации выходного сигнала. VHDL не любит использовать сигнал справа от назначения, когда он также является выходом.
источник
if prescaler = 50_000_000/4 then ...
иprescaler <= prescaler + 1;
будет немного проще.clk_2Hz
это выход, но все же его значение читается в этой строкеclk_2Hz <= not clk_2Hz;
. Я редактировал в исправлении.prescaler <= (others => '0');
иprescaler <= '0';
?others
использовалось, когда читал книгу VHDL, которую я имею. Это просто ярлык для объявления всех «других» битов общим значением вместо использования чего-то вроде «000000000000000000 ....» и т. Д.Используйте предварительный пересчет часов.
Ваше предварительное значение будет вашим (clock_speed / требуемый_clock_speed) / 2 так (50 МГц (50 000 000) / 2 Гц (2)) / 2 = 12 500 000, что в двоичном виде будет 101111101011110000100000.
Проще говоря: (50 000 000) / 2) / 2 = 12 500 000 преобразовать в двоичный файл -> 101111101011110000100000
Вот некоторый код того, что нужно сделать: используйте newClock для того, что вам нужно 2 Гц для ...
источник
newClock : std_logic := '0'
, сосчитать до prescaler / 2 и назначитьnewClk <= not newClk
?Обычно вы не хотите синхронизировать что-либо медленное, просто создайте разрешение с правильной скоростью и используйте это в логике:
Вы можете создать включение таким образом:
создайте пару констант с вашей тактовой частотой и желаемой частотой включения - и все готово, с самодокументированным кодом для загрузки.
источник
Я бы предпочел использовать IP-менеджер менеджера цифровых часов Xilinx primitice .
Он имеет графический интерфейс настроек, где вы можете указать, какую частоту вы хотите. Он сгенерирует компонент с желаемым выходом в качестве частоты.
Его можно найти в мастере IP;
И тогда вы сможете указать, какую частоту вы хотите:
источник
Фактор = входной сигнал-частота / выходной прескейлер-частота.
CE = часы включены. Это должен быть импульс длительностью один такт (clk) или высокий, если он не используется.
Q = Выходной сигнал импульса шириной один такт с требуемой частотой.
источник