Перейти к содержанию
    

Генератор последовательности импульсов на VHDL

Спасибо всем за столь активное участие :)

К сожалению, во всех предложенных вариантах возникает одно неприятная вещь - после окончания последовательности импульсов вылезает еще один пик, то есть длина строба на чуть-чуть больше,чем длина последовательности тактов. (Понятно. что это возникает при моделировании с учетом реальных задержек). Похоже, надо действительно делать синхронное устройство - по входу и выходу.

 

Задача не такая тривиальная, как кажется с первого взгляда.

Тактируемые по переднему фронту триггеры не могут сформровать спад сигнала по заднему фронту клока. Асинхронный ключ не может гарантировать отсутствие глитчей без детального анализа времен распространения сигналов. То есть, в любом случае нужно очень аккуратно учитывать особенности архитектуры, под которую пишется код.

 

Другое дело - а нужно ли пропускать именно N импульсов именно клока? Может быть, достаточно сформировать сигнал разрешения длительностью в N импульсов клока, и использовать его непосредственно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оно у вас и так синхронное. Просто вырезать импульсы временными воротами, которые сформированы этими же клоками - плохой том. В том числе и на микросхемах средней степени интеграции. Или впереди пичок или сзади.

И делали так раньше только лишь из экономии ресурсов. А если ресурсов море. Работайте на удвоенной частоте и отсчитывайте счетчиком удвоенное значение интервала. Тогда младший разряд счетчика выдаст Вам искомую посылку клоков.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оно у вас и так синхронное. Просто вырезать импульсы временными воротами, которые сформированы этими же клоками - плохой том. В том числе и на микросхемах средней степени интеграции. Или впереди пичок или сзади.

И делали так раньше только лишь из экономии ресурсов. А если ресурсов море. Работайте на удвоенной частоте и отсчитывайте счетчиком удвоенное значение интервала. Тогда младший разряд счетчика выдаст Вам искомую посылку клоков.

 

Точно, буду пробовать работать с удвоенной частотой, как раз такая возможность имеется. Спасибо.

 

Другое дело - а нужно ли пропускать именно N импульсов именно клока? Может быть, достаточно сформировать сигнал разрешения длительностью в N импульсов клока, и использовать его непосредственно?

 

Задача у меня такая: есть регистроподобное устройство, с последовательным считыванием. Нужно "выдвинуть" из него информацию, не используя дополнительных сигналов опустошения регистра, так что нужны именно импульсы тактовой частоты.

 

 

Всем огромное спасибо за вклад в развитие аэрокосмической промышленности :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Точно, буду пробовать работать с удвоенной частотой, как раз такая возможность имеется. Спасибо.

Задача у меня такая: есть регистроподобное устройство, с последовательным считыванием. Нужно "выдвинуть" из него информацию, не используя дополнительных сигналов опустошения регистра, так что нужны именно импульсы тактовой частоты.

Всем огромное спасибо за вклад в развитие аэрокосмической промышленности :)

 

Половинная частота клока допустима? Тогда все тривиально - формируете передний и задний фронты своего клока в синхронной схеме, тактуемой исходным клоком.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получилось! Сделал так: счет по удвоенной частоте, и считаем до (2n-1) тактов, где n - количество исходных тактов.

Спасибо! :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мои 5 копеек. Хоть и запоздало, но, думаю, в тему.

Подобные задачи возникают сплошь и рядом. По стробу выдать импульс определённой длины либо один раз, либо в цикле. Либо выдать или принять данные в последовательном коде для какого-либо устройства и пр.. Я нашёл для себя удачную конструкцию и всегда ею пользуюсь. Вот пример:

 

------------------------------------------------

 

LIBRARY ieee;

USE ieee.std_logic_1164.all;

 

 

-- Entity Declaration

 

ENTITY REPLY_CONTROL IS

PORT

(

START : IN STD_LOGIC;

CLK_IN : IN STD_LOGIC;

DATA_OUT : OUT STD_LOGIC

);

 

END REPLY_CONTROL;

 

 

-- Architecture Body

 

ARCHITECTURE REPLY_CONTROL_architecture OF REPLY_CONTROL IS

 

signal count: integer range 0 to 15;

 

BEGIN

process (START, CLK_IN)

-- declarations

begin

if START = '0' then

-- Asynchronous reset code

count <= 0;

DATA_OUT <= '0';

 

elsif CLK_IN='0' and CLK_IN'event then

-- synchronous code

count <= count +1;

 

if count > 8 then

count <= 8;

end if;

 

case count is

when 6 =>

DATA_OUT <= '1';

 

when 7 =>

DATA_OUT <= '1';

 

when others =>

DATA_OUT <= '0';

end case;

 

end if;

end process;

 

END REPLY_CONTROL_architecture;

 

------------------------------------------------

 

Что получается?

Пока START = '0', вся схема ждёт. Как только START отпускаем в '1', начинает работать счётчик count. Когда он досчитает до 6, на выходе появится импульс длиной в два такта, после чего схема остановится. Чтобы снова получить имаульс на выходе, нужно уронить START в '0' и снова поднять в '1'.

 

Если нужно, чтобы импульсы шли постоянно, нужно только изменить условие:

 

if count > 8 then

count <= 0;

end if;

 

Понятно, что первая строчка определяет период следования импульсов.

 

Так можно делать одновибраторы или делители частоты на произвольную величину, не кратную 2. Если программу немного изменить, то её можно использовать для программирования сериальных устройств. Например, программирование PLL:

 

------------------------------------------------

 

LIBRARY ieee;

USE ieee.std_logic_1164.all;

 

 

-- Entity Declaration

 

ENTITY PLL_Program IS

PORT

(

START : IN STD_LOGIC;

DATA_IN : IN STD_LOGIC_VECTOR(71 downto 0);

CLK : IN STD_LOGIC;

RST : IN STD_LOGIC;

PLL_EN : OUT STD_LOGIC;

PLL_DATA : OUT STD_LOGIC;

PLL_CLK : OUT STD_LOGIC

);

 

END PLL_Program;

 

-- Architecture Body

 

ARCHITECTURE PLL_Program_architecture OF PLL_Program IS

 

signal count: integer range 0 to 226;

 

BEGIN

process (CLK, START, DATA_IN, RST)

-- declarations

begin

if RST = '1' then

count <= 222;

 

elsif START = '1' then

-- Asynchronous reset code

count <= 0;

PLL_EN <= '1';

PLL_DATA <= '0';

PLL_CLK <= '0';

 

elsif CLK='1' and CLK'event then

-- synchronous code

count <= count + 1;

 

if count > 222 then

count <= 222;

end if;

 

 

case count is

-- Initialization Latch 11h

when 0 =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(71);

 

when 1 =>

PLL_EN <= '0';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(71);

when 2 =>

PLL_EN <= '0';

PLL_CLK <= '1';

PLL_DATA <= DATA_IN(71);

 

when 3 =>

PLL_EN <= '0';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(70);

when 4 =>

PLL_EN <= '0';

PLL_CLK <= '1';

PLL_DATA <= DATA_IN(70);

 

....

 

 

when 210 =>

PLL_EN <= '0';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(1);

when 211 =>

PLL_EN <= '0';

PLL_CLK <= '1';

PLL_DATA <= DATA_IN(1);

 

when 212 =>

PLL_EN <= '0';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(0);

when 213 =>

PLL_EN <= '0';

PLL_CLK <= '1';

PLL_DATA <= DATA_IN(0);

when 214 =>

PLL_EN <= '0';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(0);

when 215 =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= DATA_IN(0);

 

 

when 216 =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= '0';

when 217 =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= '0';

 

when 218 =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= '0';

when 219 =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= '0';

 

 

when others =>

PLL_EN <= '1';

PLL_CLK <= '0';

PLL_DATA <= '0';

end case;

end if;

end process;

 

END PLL_Program_architecture;

 

------------------------------------------------

 

Входные сигналы:

RST - аппаратный сброс (Global Reset);

DATA_IN - данные;

CLK - задающая частота;

START - сигнал запуска.

 

Если RST = '1', пришёл сброс при включении питания, счётчик count сразу загоняется в верхнее значение. Схема молчит. Это значит, что по сбросу, когда данные ещё не готовы, никаких сигналов вырабатываться не будет.

 

START = '1'. Приготовились!

 

START = '0'. Начало передачи.

 

Для программирования PLL нужно 3 сигнала: PLL_EN - если ='0', PLL выбран. PLL_DATA - последовательные данные, которые стробируются передним фронтом PLL_CLK.

 

Циклы:

0 - готовим старший бит.

1 - опускаем PLL_EN в '0' (активный).

2 - стробируем данные.

3 - готовим следующий бит данных.

4 - стробируем.

... и так далее ...

213 - стробируем последний (младший бит).

214 - выжидаем 1 такт.

215 - поднимаем PLL_EN. Передача завершена.

216-219 - выжидаем небольшую паузу.

 

-----------------------------------------------------

Подобным же образом можно делать и приёмные регистры. Данная конструкция очень универсальная. На её основе можно сделать миллион и одно устройство. Она легко читается и самое главное - не создаёт никаких проблем с гонками.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не думаю, что это удачная конструкция. (Не говоря об асинхронном ресете и странном описании счетчика (нет приоритетности в описании)).

Попробуйте в случае формирования периодической последовательности вставить параметр

generic (PERIOD : integer := 15); и что то отличное, например

generic (PERIOD : integer := 10); Получите разные приращения, неговоря уже о том, что приращений быть не должно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пытаюсь переложить данный код на verilog. С обоими языками плохо знаком, помогите пожалуйста "доделать". Написал так:

module ct_laa(

input EN,

input CLK,

output LATCH

);

 

reg [6:0] TEMP_Q = 7'b0;

reg TEMP_EN = 1'b0;

reg [2:0] shift = 3'b0;

wire ena;

 

always @(posedge CLK)

begin

shift <= {shift[1:0], EN};

if (ena == 1'b1)

begin

TEMP_EN <= 1'b1;

TEMP_Q <= 7'b0000000;

end

 

else if

(TEMP_Q == 7'b0000011);

begin

TEMP_EN <= 1'b0;

end

 

if (TEMP_EN == 1'b1);

begin

TEMP_Q <= TEMP_Q + 1;

end

end

 

 

ena <= not shift[2], and shift[1]; На этой строке Quartus ругается: Error (10170): Verilog HDL syntax error at ct_laa.v(35) near text "<="; expecting ".", or "("

 

assign LATCH = TEMP_EN;

 

endmodule

 

Как правильно описать? Также не уверен, что все остальное правильно. Прошу проверить. Внизу оригинал.

Заранее всем спасибо!

 

 

Врядли найдется симулятор, который все что выше не поймет.

Хотя можно и по другому. (относительно возможных изменений сигнала EN логика функционирования другая)

 

library IEEE;

use IEEE.STD_LOGIC_1164.all;

use IEEE.std_logic_unsigned.all;

 

entity ct_laa is

port (

EN : in std_logic;

CLK : in std_logic;

LATCH : out std_logic:='0'

);

end entity;

 

 

architecture count_latch_arch of ct_laa is

 

signal TEMP_Q : std_logic_vector (6 downto 0):=(others =>'0');

signal TEMP_EN : std_logic:='0';

signal shift : std_logic_vector (2 downto 0):=(others =>'0');

signal ena : std_logic;

begin

 

process (CLK)

begin

if rising_edge (CLK) then

shift <= shift (1 downto 0) & EN;

if ena = '1' then

TEMP_EN <='1';

TEMP_Q <="0000000";

else

if TEMP_Q = "0000111" then -- n-1

TEMP_EN <='0';

end if;

if TEMP_EN = '1' then

TEMP_Q <= TEMP_Q+1;

end if;

end if;

end if;

end process;

 

ena <= not shift(2) and shift(1);

LATCH <=TEMP_EN;

 

end architecture;

Изменено пользователем Evgeny72

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задача вроде бы простая. но у меня не получается ни в какую - три дня бьюсь...

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

Может, кто подскажет, как эту штуку слепить? Вроде на первый взгляд так просто казалось... :(

Я бы взял не "тактовая частота", а ровно вдвое больше. Потом сделал бы программируемый таймер, и на выходе - триггер.

программируемый таймер должен давать разрешение на триггер, который бы и сделал на "выходе" нужное количество импульсов...

И это нужно только если эти импульсы выдавать во вне кристалла. А если внутри кристалла, то вполне хватит и выхода таймера, как сигнала разрешения для чего-то...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал и получил: Error (10137): Verilog HDL Procedural Assignment error at ct_laa.v(33): object "ena" on left-hand side of assignment must have a variable data type. Если декларирую как reg ena, получаю дополнительный триггер в RTL схеме. В исходном коде триггера в RTL схеме нет.

 

ena <= ~ shift[2] & shift[1];

 

 

Код на VHDL рабочий, свою задачу выполняет. :) Данный код, по изменению сигнала EN, выдает импульс длинною if (TEMP_Q == 7'bХ - 1).

 

Я бы взял не "тактовая частота", а ровно вдвое больше. Потом сделал бы программируемый таймер, и на выходе - триггер.

программируемый таймер должен давать разрешение на триггер, который бы и сделал на "выходе" нужное количество импульсов...

И это нужно только если эти импульсы выдавать во вне кристалла. А если внутри кристалла, то вполне хватит и выхода таймера, как сигнала разрешения для чего-то...

Изменено пользователем Evgeny72

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нельзя просто так взять и использовать "<=" вне блока always. Почитайте про виды присвоений в verilog.

assign ena = ~ shift[2] & shift[1];

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, все ОК!

 

Нельзя просто так взять и использовать "<=" вне блока always. Почитайте про виды присвоений в verilog.

assign ena = ~ shift[2] & shift[1];

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...