Документация: секвенсор заряда/разряда (sequencer.vhd)
Содержание
- Назначение
- Аппаратный тракт компаратора
- Интерфейс
- Архитектура
- Логика режимов
- Статусные регистры
- Сброс
- Цепочка данных до ARM
- Результаты испытаний
- Известные ограничения
- Рекомендации
- Версия
1. Назначение
Модуль sequencer координирует работу двух импульсных генераторов (pulse_generator_core) — канала 0 (заряд) и канала 1 (разряд) — на основе сигналов двух аналоговых компараторов, контролирующих напряжение на накопительном конденсаторе.
Секвенсор реализует четыре режима работы, которые выбираются битами SEQUENCE в
регистрах управления ch0_control(4) и ch1_control(4):
| Режим | ch0_seq | ch1_seq | Поведение |
|---|---|---|---|
| 1 | '1' |
'1' |
Совместный автоколебательный (эстафета заряд ↔ разряд) |
| 2 | '1' |
'0' |
Секвенсор только на заряде |
| 3 | '0' |
'1' |
Секвенсор только на разряде |
| 4 | '0' |
'0' |
Полностью ручной (байпас) |
Секвенсор также встраивает значение компаратора в бит 5 статусного регистра, который ARM читает через AXI-Lite.
2. Аппаратный тракт компаратора
2.1. Принципиальная схема TLV3502AID (U12)
Дискретизация уровней напряжения накопителя выполняется интегральным сдвоенным компаратором TLV3502AID (корпус SOIC-8, t_pd = 4,5 нс, двухтактный Push-Pull выход). Питание микросхемы осуществляется напряжением +5 В (VLT1_5V) относительно локальной аналоговой земли VLT1_GND.
TLV3502AID (U12)
┌───∪───┐
Vref_high (0.310 В) ────┤ 1 8 ├── VLT1_5V (+5 В)
U_in ──┬─┤ 2 7 ├── OUTA (Порог 55 В) ──> ISO7220 Pin 2
└─┤ 3 6 ├── OUTB (Порог 45 В) ──> ISO7220 Pin 3
Vref_low (0.254 В) ────┤ 4 5 ├── VLT1_GND (0 В)
└───────┘
| Вывод | Имя | Назначение и подключение |
|---|---|---|
| 1 | +IN_A | Опорный потенциал верхнего порога V_ref_high = 0,310 В (соответствует 55 В на накопителе) |
| 2 | -IN_A | Измеряемый потенциал U_in от делителя накопителя (0,287 В при 50 В) |
| 3 | +IN_B | Объединён с выводом 2, потенциал U_in |
| 4 | -IN_B | Опорный потенциал нижнего порога V_ref_low = 0,254 В (соответствует 45 В на накопителе) |
| 5 | V- | Потенциал аналоговой земли VLT1_GND |
| 6 | OUTB | Выход дискриминатора нижнего порога (45 В) |
| 7 | OUTA | Выход дискриминатора верхнего порога (55 В) |
| 8 | V+ | Шина питания VLT1_5V с развязывающим конденсатором 0,1 мкФ |
Измеряемый потенциал U_in подан на инвертирующие входы (-IN_A, -IN_B), поэтому выходы компараторов имеют активный низкий уровень (см. §2.2).
2.2. Передаточная характеристика и карта компараторов
Сигналы с выходов компаратора OUTA и OUTB транслируются на разъёмы ПЛИС через цифровой изолятор ISO7220MDR (согласование уровней 5 В → 3,3 В). На выводах ПЛИС (comp_high_0 — вывод N20, comp_low_0 — вывод P20) действует активный низкий уровень ('0'):
comp_high_0 = '0'⟺ U ≥ порога потолка (предел заряда);comp_low_0 = '0'⟺ U ≤ порога дна (предел разряда);comp_high_0 = '1'иcomp_low_0 = '1'— напряжение внутри окна.
| Напряжение U | comp_high | comp_low |
|---|---|---|
| U < порога дна | '1' |
'0' |
| порог дна ≤ U ≤ порог потолка | '1' |
'1' |
| U > порога потолка | '0' |
'1' |
Каждый компаратор равен '1', пока напряжение не вышло за его порог (для
comp_high — пока U ниже потолка, для comp_low — пока U выше дна). Значения
порогов задаются аппаратно потенциометрами:
- POT0 = 0x11 → переход
comp_highв районе 56,5 В; - POT1 = 0x0B → переход
comp_lowв районе 33,5 В.
Примечание: в описании задачи фигурируют «45 В» и «55 В», но фактические пороги определяются потенциометрами. Логика секвенсора не зависит от абсолютных значений — только от переходов
'1' → '0'.
3. Интерфейс
3.1. Порты
| Порт | Направление | Ширина | Назначение |
|---|---|---|---|
| clk | in | 1 | Системная тактовая частота |
| rst_n | in | 1 | Сброс, активный низкий |
| ch0_cmd_seq | in | 1 | Бит 4 ch0_control — SEQUENCE канала 0 |
| ch0_cmd_run | in | 1 | Бит 0 ch0_control — RUN канала 0 |
| ch0_cmd_reset | in | 1 | Бит 1 ch0_control — RESET канала 0 |
| ch1_cmd_seq | in | 1 | Бит 4 ch1_control — SEQUENCE канала 1 |
| ch1_cmd_run | in | 1 | Бит 0 ch1_control — RUN канала 1 |
| ch1_cmd_reset | in | 1 | Бит 1 ch1_control — RESET канала 1 |
| comp_low_0 | in | 1 | Компаратор дна, '0' при U ≤ порога дна |
| comp_high_0 | in | 1 | Компаратор потолка, '0' при U ≥ порога потолка |
| ch0_gen_run | out | 1 | RUN генератора заряда |
| ch0_gen_stop | out | 1 | STOP генератора заряда (зарезервирован, всегда '0') |
| ch0_gen_reset | out | 1 | RESET генератора заряда |
| ch1_gen_run | out | 1 | RUN генератора разряда |
| ch1_gen_stop | out | 1 | STOP генератора разряда (зарезервирован, всегда '0') |
| ch1_gen_reset | out | 1 | RESET генератора разряда |
| ch0_status_in | in | 32 | Статус от генератора заряда (o_status) |
| ch1_status_in | in | 32 | Статус от генератора разряда (o_status) |
| ch0_status_out | out | 32 | Статус в timing_controller (бит 5 = компаратор) |
| ch1_status_out | out | 32 | Статус в timing_controller (бит 5 = компаратор) |
4. Архитектура
4.1. Структурная схема
┌──────────────────────────────────────────┐
│ sequencer │
│ │
comp_high_0 ─────┤──► CDC ──► comp_high_sync ──┐ │
comp_low_0 ─────┤──► CDC ──► comp_low_sync ──┤ │
│ │ │
ch0_cmd_seq ─────┤──► CDC ──► ch0_seq_sync ────┤ │
ch0_cmd_run ─────┤──► CDC ──► ch0_run_sync ────┤ Логика │
ch0_cmd_reset ───┤──► CDC ──► ch0_rst_sync ────┤ режимов │
ch1_cmd_seq ─────┤──► CDC ──► ch1_seq_sync ────┤ │
ch1_cmd_run ─────┤──► CDC ──► ch1_run_sync ────┤ │
ch1_cmd_reset ───┤──► CDC ──► ch1_rst_sync ────┤ │
│ │ │
│ ▼ │
│ r_ch0_run / r_ch1_run │
│ │ │
ch0_status_in ───┤──► сборка статуса ──► ch0_status_out │
ch1_status_in ───┤──► сборка статуса ──► ch1_status_out │
│ │
└──────────────────────────────────────────┘
│ │
▼ ▼
ch0_gen_run ch1_gen_run
ch0_gen_reset ch1_gen_reset
ch0_gen_stop ch1_gen_stop
4.2. CDC-синхронизация
Все асинхронные входы проходят двухступенчатый синхронизатор (meta → sync) с
атрибутом ASYNC_REG = "TRUE":
comp_high_0 → comp_high_meta → comp_high_synccomp_low_0 → comp_low_meta → comp_low_syncch0_cmd_seq → ch0_seq_meta → ch0_seq_syncch0_cmd_run → ch0_run_meta → ch0_run_syncch0_cmd_reset → ch0_rst_meta → ch0_rst_sync
(аналогично для канала 1).
- Назначение: защита от метастабильности при переходе сигналов между тактовыми доменами.
- Задержка: 2 такта
clkна каждый сигнал.
4.3. Выходные регистры
Состояние генераторов хранится в двух регистрах:
r_ch0_run— управление зарядом;r_ch1_run— управление разрядом.
Начальные значения: r_ch0_run = '1', r_ch1_run = '0'. При rst_n = '0' оба
сбрасываются в '0'.
5. Логика режимов
5.1. РЕЖИМ 1: совместный автоколебательный
Условие: ch0_seq_sync = '1' и ch1_seq_sync = '1'.
Назначение: автоматическая эстафета заряд ↔ разряд по порогам компараторов.
Логика (приоритет сверху вниз):
| Условие | Действие | Комментарий |
|---|---|---|
comp_high_sync = '0' |
r_ch0_run <= '0', r_ch1_run <= '1' |
Потолок достигнут: гасим заряд, запускаем разряд |
comp_low_sync = '0' |
r_ch1_run <= '0', r_ch0_run <= '1' |
Дно достигнуто: гасим разряд, запускаем заряд |
r_ch1_run = r_ch0_run |
r_ch0_run <= '1', r_ch1_run <= '0' |
Окно: оба в одинаковом состоянии (оба вкл — конфликт, оба выкл — простой) → включаем заряд |
| (иначе) | — | Окно, активен ровно один генератор → фаза сохраняется |
Ключевые особенности:
- Break-before-make: в ветках потолка и дна сначала гасится активный генератор, потом запускается неактивный.
- Приоритет заряда в окне: при простое (оба
'0') или конфликте (оба'1') включается заряд, разряд гасится. - Удержание фазы: если активен ровно один генератор, состояние не меняется — разряд продолжается, пока не дойдёт до дна; заряд — пока не дойдёт до потолка.
Диаграмма состояний:
comp_high = '0' comp_low = '0'
(потолок) (дно)
│ │
▼ ▼
┌───────────┐ ┌───────────┐
│ РАЗРЯД │◄──── окно ──────►│ ЗАРЯД │
│ активен │ (удержание) │ активен │
└───────────┘ └───────────┘
│ ▲
│ │
└────── окно (конфликт/ ──────┘
простой → заряд)
5.2. РЕЖИМ 2: секвенсор только на заряде
Условие: ch0_seq_sync = '1' и ch1_seq_sync = '0'.
r_ch0_run <= ch0_run_sync and comp_high_sync;
r_ch1_run <= ch1_run_sync;
- Канал 0 (заряд): управляется ARM через
ch0_run_sync, но отсекается по потолку — приcomp_high_sync = '0'заряд гасится. - Канал 1 (разряд): полностью под управлением ARM (
ch1_run_sync), компараторы не влияют.
Применение: ручной нагрев с защитой по верхнему порогу.
5.3. РЕЖИМ 3: секвенсор только на разряде
Условие: ch0_seq_sync = '0' и ch1_seq_sync = '1'.
r_ch0_run <= ch0_run_sync;
r_ch1_run <= ch1_run_sync and comp_low_sync;
- Канал 0 (заряд): полностью под управлением ARM.
- Канал 1 (разряд): управляется ARM, но отсекается по дну — при
comp_low_sync = '0'разряд гасится.
Применение: ручной разряд с защитой по нижнему порогу.
5.4. РЕЖИМ 4: полностью ручной
Условие: ch0_seq_sync = '0' и ch1_seq_sync = '0'.
r_ch0_run <= ch0_run_sync;
r_ch1_run <= ch1_run_sync;
Полный байпас: биты RUN от ARM транслируются на генераторы напрямую. Компараторы не участвуют.
Применение: ручное управление без автоматики.
6. Статусные регистры
6.1. Формирование
Секвенсор принимает ch0_status_in от генератора (o_status) и подменяет бит 5 на
синхронизированное значение компаратора:
ch0_status_out <= ch0_status_in(31 downto 6) & comp_high_sync & ch0_status_in(4 downto 0);
ch1_status_out <= ch1_status_in(31 downto 6) & comp_low_sync & ch1_status_in(4 downto 0);
Разбор для ch0_status_out:
| Часть | Биты входа | Куда попадает |
|---|---|---|
| ch0_status_in(31 downto 6) | 31..6 | биты 31..6 выхода |
| comp_high_sync | — | бит 5 выхода |
| ch0_status_in(4 downto 0) | 4..0 | биты 4..0 выхода |
6.2. Карта бит ch0_status (ARM читает)
| Бит | Источник | Смысл |
|---|---|---|
| 0 | генератор | running — генератор работает |
| 1 | генератор | running (дубль) |
| 2 | генератор | done — завершено |
| 3 | генератор | bReset — флаг программного сброса |
| 4 | генератор | error — ошибка (burst=0 или pulse=0) |
| 5 | секвенсор | comp_high — потолок |
| 6..31 | генератор | должны быть '0' |
6.3. Карта бит ch1_status (ARM читает)
| Бит | Источник | Смысл |
|---|---|---|
| 0 | генератор | running |
| 1 | генератор | running (дубль) |
| 2 | генератор | done |
| 3 | генератор | bReset |
| 4 | генератор | error |
| 5 | секвенсор | comp_low — дно |
| 6..31 | генератор | должны быть '0' |
6.4. Интерпретация компаратора через статус
ARM читает ch0_status(5) и ch1_status(5):
| ch0_status(5) | ch1_status(5) | Напряжение |
|---|---|---|
'1' |
'1' |
окно (между порогами) |
'0' |
'1' |
потолок достигнут |
'1' |
'0' |
дно достигнуто |
'0' |
'0' |
переход или авария |
7. Сброс
7.1. Аппаратный сброс (rst_n = '0')
- все CDC-регистры обнуляются;
r_ch0_runиr_ch1_runсбрасываются в'0';ch0_status_outиch1_status_outпринимают значениеch0_status_in/ch1_status_inсcomp_*_sync = '0'в бите 5.
7.2. Программный сброс (ch0_cmd_reset)
Транслируется в генератор через ch0_gen_reset после CDC. Секвенсор не сбрасывает
свои регистры r_ch0_run/r_ch1_run по этому сигналу — только транслирует.
8. Цепочка данных до ARM
pulse_generator_core.o_status
│
▼
sequencer.ch0_status_in
│ (бит 5 → comp_high_sync)
▼
sequencer.ch0_status_out
│
▼
timing_controller.ch0_status
│
▼
AXI-slave → Zynq PS → ARM
ARM читает ch0_status по адресу в AXI-пространстве timing_controller.
9. Результаты испытаний
9.1. Прогон 30 → 60 В (секвенсор только на заряде)
| U, В | L1 | L2 | ГЕН1 | ГЕН2 | ST1 | ST2 |
|---|---|---|---|---|---|---|
| 30 | 1 | 0 | RUN | RUN | 0x23 | 0x03 |
| 34 | 1 | 1 | RUN | RUN | 0x23 | 0x23 |
| … | … | … | … | … | … | … |
| 54 | 1 | 1 | RUN | RUN | 0x23 | 0x23 |
| 56 | 1 | 1 | STOP | RUN | 0x00 | 0x23 |
| 58 | 0 | 1 | STOP | RUN | 0x08 | 0x23 |
| 60 | 0 | 1 | STOP | RUN | 0x00 | 0x23 |
Вывод: секвенсор канала 0 корректно отсекает заряд по потолку. Бит 5 статуса (ST1) = comp_high.
9.2. Прогон 60 → 30 В (секвенсор только на разряде)
| U, В | L1 | L2 | ГЕН1 | ГЕН2 | ST1 | ST2 |
|---|---|---|---|---|---|---|
| 60 | 0 | 1 | RUN | RUN | 0x03 | 0x23 |
| 56 | 1 | 1 | RUN | RUN | 0x03 | 0x23 |
| 54 | 1 | 1 | RUN | RUN | 0x23 | 0x23 |
| … | … | … | … | … | … | … |
| 34 | 1 | 1 | RUN | RUN | 0x23 | 0x23 |
| 32 | 1 | 0 | RUN | STOP | 0x23 | 0x08 |
| 30 | 1 | 0 | RUN | STOP | 0x23 | 0x08 |
Вывод: секвенсор канала 1 корректно отсекает разряд по дну. Бит 5 статуса (ST2) = comp_low.
9.3. Ключевые наблюдения
- CDC работает — компараторы доходят до статуса без залипаний.
- Бит 5 статуса = компаратор — подтверждено для обоих каналов.
- Отсечки работают — РЕЖИМ 2 по потолку, РЕЖИМ 3 по дну.
bReset = '1'появляется в статусе при остановке генератора (бит 3, 0x08).- Аппаратные пороги: потолок ~56,5 В (POT0 = 0x11), дно ~33,5 В (POT1 = 0x0B).
10. Известные ограничения
- Нет дебаунса компараторов. Вблизи порогов возможен дребезг, который вызовет
многократное переключение
r_ch0_run/r_ch1_run. Для отладки переходов это не мешает, но в реальной работе требуется фильтр. - Бит 5 o_status генератора не задан явно. В pulse_generator_core строка
o_status(31 downto 5) <= (others => '0')закомментирована. Это может дать'U'в симуляции. Рекомендуется раскомментировать. - bReset в статусе. ARM видит флаг программного сброса генератора (0x08). Это не ошибка, но стоит задокументировать.
- i_stop не используется. Вход
i_stopгенератора не задействован. Секвенсор подаёт'0'. Зарезервирован на будущее. - Бит 1 статуса — дубль running. Возможно, должен быть
ready, ноreadyв генераторе объявлен и не используется.
11. Рекомендации
- Добавить дебаунс компараторов после CDC, перед логикой режимов. Логика:
одиночный
'0'в одном такте = дребезг; реальный переход — устойчивое состояние N тактов. Плюс заморозка до срабатывания противоположного порога. - Раскомментировать обнуление старших бит в pulse_generator_core:
o_status(31 downto 5) <= (others => '0');
- Проверить РЕЖИМ 1 — включить оба секвенсора, проверить эстафету заряд ↔ разряд.
- Проверить холодный старт в окне — оба генератора выключены, напряжение между порогами → должен включиться заряд.
- Добавить constraints для CDC —
set_false_pathилиset_max_delay -datapath_onlyдляcomp_*иcmd_*в XDC.
12. Версия
- v1.0 — базовая логика без дебаунса. Подтверждена на прогонах 30→60 В и 60→30 В.
- Следующая версия: добавить дебаунс, проверить РЕЖИМ 1.
Приложение. Исходный код (VHDL)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity sequencer is
port (
-- Системная тактовая частота и сброс CDC-регистров
clk : in std_logic;
rst_n : in std_logic;
-- Управление процессора: Канал 0 (Заряд)
ch0_cmd_seq : in std_logic; -- Бит 4 регистра ch0_control (SEQUENCE)
ch0_cmd_run : in std_logic; -- Бит 0 регистра ch0_control (RUN)
ch0_cmd_reset : in std_logic; -- Бит 1 регистра ch0_control (RESET)
-- Управление процессора: Канал 1 (Разряд)
ch1_cmd_seq : in std_logic; -- Бит 4 регистра ch1_control (SEQUENCE)
ch1_cmd_run : in std_logic; -- Бит 0 регистра ch1_control (RUN)
ch1_cmd_reset : in std_logic; -- Бит 1 регистра ch1_control (RESET)
-- Входные сигналы аналоговых компараторов с платы
-- comp_high = '0' при U >= 55 В, comp_low = '0' при U <= 45 В
-- В окне 45..55 В оба равны '1'
comp_low_0 : in std_logic;
comp_high_0 : in std_logic;
-- Выходной интерфейс управления: pulse_generator_core_0 (Заряд)
ch0_gen_run : out std_logic;
ch0_gen_stop : out std_logic; -- Резервная линия (фиксированный '0')
ch0_gen_reset : out std_logic; -- Синхронизированный сброс
-- Выходной интерфейс управления: pulse_generator_core_1 (Разряд)
ch1_gen_run : out std_logic;
ch1_gen_stop : out std_logic; -- Резервная линия (фиксированный '0')
ch1_gen_reset : out std_logic; -- Синхронизированный сброс
-- Статусы: вход от генераторов (o_status), выход в timing_controller
-- Бит 5 заменяется на значение компаратора:
-- ch0_status_out(5) = comp_high_sync (потолок 55 В, управляется sequence_0)
-- ch1_status_out(5) = comp_low_sync (дно 45 В, управляется sequence_1)
-- Биты 0..4 остаются от генератора (running, running, done, bReset, error)
ch0_status_in : in std_logic_vector(31 downto 0);
ch1_status_in : in std_logic_vector(31 downto 0);
ch0_status_out : out std_logic_vector(31 downto 0);
ch1_status_out : out std_logic_vector(31 downto 0)
);
end entity sequencer;
architecture Behavioral of sequencer is
attribute ASYNC_REG : string;
-- CDC-регистры синхронизации входов компараторов
signal comp_low_meta : std_logic := '0';
signal comp_low_sync : std_logic := '0';
signal comp_high_meta : std_logic := '0';
signal comp_high_sync : std_logic := '0';
attribute ASYNC_REG of comp_low_meta : signal is "TRUE";
attribute ASYNC_REG of comp_low_sync : signal is "TRUE";
attribute ASYNC_REG of comp_high_meta : signal is "TRUE";
attribute ASYNC_REG of comp_high_sync : signal is "TRUE";
-- CDC-регистры синхронизации битов SEQUENCE
signal ch0_seq_meta : std_logic := '0';
signal ch0_seq_sync : std_logic := '0';
signal ch1_seq_meta : std_logic := '0';
signal ch1_seq_sync : std_logic := '0';
attribute ASYNC_REG of ch0_seq_meta : signal is "TRUE";
attribute ASYNC_REG of ch0_seq_sync : signal is "TRUE";
attribute ASYNC_REG of ch1_seq_meta : signal is "TRUE";
attribute ASYNC_REG of ch1_seq_sync : signal is "TRUE";
-- CDC-регистры синхронизации битов RUN
signal ch0_run_meta : std_logic := '0';
signal ch0_run_sync : std_logic := '0';
signal ch1_run_meta : std_logic := '0';
signal ch1_run_sync : std_logic := '0';
attribute ASYNC_REG of ch0_run_meta : signal is "TRUE";
attribute ASYNC_REG of ch0_run_sync : signal is "TRUE";
attribute ASYNC_REG of ch1_run_meta : signal is "TRUE";
attribute ASYNC_REG of ch1_run_sync : signal is "TRUE";
-- CDC-регистры синхронизации битов RESET
signal ch0_rst_meta : std_logic := '0';
signal ch0_rst_sync : std_logic := '0';
signal ch1_rst_meta : std_logic := '0';
signal ch1_rst_sync : std_logic := '0';
attribute ASYNC_REG of ch0_rst_meta : signal is "TRUE";
attribute ASYNC_REG of ch0_rst_sync : signal is "TRUE";
attribute ASYNC_REG of ch1_rst_meta : signal is "TRUE";
attribute ASYNC_REG of ch1_rst_sync : signal is "TRUE";
-- Выходные регистры управления генераторами
signal r_ch0_run : std_logic := '1';
signal r_ch1_run : std_logic := '0';
begin
-- Синхронизированный транзит служебных линий
ch0_gen_reset <= ch0_rst_sync;
ch1_gen_reset <= ch1_rst_sync;
ch0_gen_stop <= '0';
ch1_gen_stop <= '0';
-- =====================================================================
-- Сборка статусов: бит 5 = компаратор, остальные 31 бит - сквозь
-- Биты 0..4 остаются от генератора (running, running, done, bReset, error)
-- =====================================================================
ch0_status_out <= ch0_status_in(31 downto 6) & comp_high_sync & ch0_status_in(4 downto 0);
ch1_status_out <= ch1_status_in(31 downto 6) & comp_low_sync & ch1_status_in(4 downto 0);
-- Синхронизация асинхронных дискретных сигналов
process(clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
comp_low_meta <= '0';
comp_low_sync <= '0';
comp_high_meta <= '0';
comp_high_sync <= '0';
ch0_seq_meta <= '0';
ch0_seq_sync <= '0';
ch1_seq_meta <= '0';
ch1_seq_sync <= '0';
ch0_run_meta <= '0';
ch0_run_sync <= '0';
ch1_run_meta <= '0';
ch1_run_sync <= '0';
ch0_rst_meta <= '0';
ch0_rst_sync <= '0';
ch1_rst_meta <= '0';
ch1_rst_sync <= '0';
else
comp_low_meta <= comp_low_0;
comp_low_sync <= comp_low_meta;
comp_high_meta <= comp_high_0;
comp_high_sync <= comp_high_meta;
ch0_seq_meta <= ch0_cmd_seq;
ch0_seq_sync <= ch0_seq_meta;
ch1_seq_meta <= ch1_cmd_seq;
ch1_seq_sync <= ch1_seq_meta;
ch0_run_meta <= ch0_cmd_run;
ch0_run_sync <= ch0_run_meta;
ch1_run_meta <= ch1_cmd_run;
ch1_run_sync <= ch1_run_meta;
ch0_rst_meta <= ch0_cmd_reset;
ch0_rst_sync <= ch0_rst_meta;
ch1_rst_meta <= ch1_cmd_reset;
ch1_rst_sync <= ch1_rst_meta;
end if;
end if;
end process;
-- Единый синхронный процесс управления выходами генераторов
process(clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
r_ch0_run <= '0';
r_ch1_run <= '0';
else
-- =================================================================
-- РЕЖИМ 1: СОВМЕСТНЫЙ АВТОКОЛЕБАТЕЛЬНЫЙ (Оба SEQUENCE = '1')
-- Эстафета переключения по порогам.
-- =================================================================
if (ch0_seq_sync = '1' and ch1_seq_sync = '1') then
-- Потолок (U >= 55 В): comp_high = '0'
-- Сначала гасим заряд, потом запускаем разряд
if comp_high_sync = '0' then
r_ch0_run <= '0';
r_ch1_run <= '1';
-- Дно (U <= 45 В): comp_low = '0'
-- Сначала гасим разряд, потом запускаем заряд
elsif comp_low_sync = '0' then
r_ch1_run <= '0';
r_ch0_run <= '1';
-- Окно (оба компаратора = '1'):
-- Если оба генератора в одинаковом состоянии
-- (оба выключены - простой, или оба включены - конфликт),
-- включаем заряд и гасим разряд.
-- Если активен ровно один - сохраняем фазу.
elsif (r_ch1_run = r_ch0_run) then
r_ch0_run <= '1';
r_ch1_run <= '0';
end if;
-- =================================================================
-- РЕЖИМ 2: СЕКВЕНСОР ТОЛЬКО НА КАНАЛЕ 0 (ЗАРЯД)
-- Канал 1 - прямой транзит от ПО.
-- Канал 0 запускается от ПО и отсекается по потолку 55 В.
-- =================================================================
elsif (ch0_seq_sync = '1' and ch1_seq_sync = '0') then
r_ch0_run <= ch0_run_sync and comp_high_sync;
r_ch1_run <= ch1_run_sync;
-- =================================================================
-- РЕЖИМ 3: СЕКВЕНСОР ТОЛЬКО НА КАНАЛЕ 1 (РАЗРЯД)
-- Канал 0 - прямой транзит от ПО.
-- Канал 1 запускается от ПО и отсекается по дну 45 В.
-- =================================================================
elsif (ch0_seq_sync = '0' and ch1_seq_sync = '1') then
r_ch0_run <= ch0_run_sync;
r_ch1_run <= ch1_run_sync and comp_low_sync;
-- =================================================================
-- РЕЖИМ 4: ПОЛНОСТЬЮ РУЧНОЙ РЕЖИМ (Оба SEQUENCE = '0')
-- Прямой транзит битов RUN от ПО в оба генератора.
-- =================================================================
else
r_ch0_run <= ch0_run_sync;
r_ch1_run <= ch1_run_sync;
end if;
end if;
end if;
end process;
-- Прямое назначение выходных регистров на ядра генераторов
ch0_gen_run <= r_ch0_run;
ch1_gen_run <= r_ch1_run;
end architecture Behavioral;