
Проектирование цифровых устройств на программируемой элементной базе.
Лекция 08.11.12
Появление СБИС программируемой логики сверхвысокой логической емкости, развитие средств проектирования (системы (САПР): MAX+plus и Quartus программируют кристаллы, также имеются системы Function Series и ISE) и уровень сложности создаваемых в настоящее время цифровых систем предопределяют существенные изменения в методологии проектирования.
Существует два способа описания элементов: графический и текстовый.
Графическое описание (Minter graphics corporation) → Достоинствами этого метода являются: традиционность и наглядность, однако, широкое применение графического описания проектируемого устройства, базирующееся на ручном и не формализованном, импирическом, синтезе управляющих автоматов, остается в прошлом. На смену приходит другая методология, в основе которой лежат два ключевых момента:
Автоматический синтез → процедура формального перевода текстового описания в схемное описание на заданном элементном базисе, выполняемая системой автоматизации проектирования.
Текстовое описание → применение высокоуровневых языковых конструкций (языков описания аппаратуры) для задания алгоритма работы создаваемого устройства.
Текстовое описание аппаратуры выполняется на языках HDL (Hardware description language), которые обладают средствами поведенческого (функционального) и структурного описания.
Достоинства: компактность, простота автоматизации преобразований, возможность переноса проекта с одной аппаратной платформы на другую, перехода с одной САПР на другую.
Рассмотрим таблицу 1.
Таблица 1.
Уровень языка |
Языки программирования |
Языки проектирования устройств |
Уровень реализации |
Машинный программный код (.exe, .com) |
Таблица соединений (типы логических элементов (ЛЭ) и связи между ними). RTL |
Приборно-ориентированный уровень |
Язык Ассемблера (до 60-ых годов) |
PLDASM, ABEL, AHDL (Altera HDL) |
Процедурно- ориентированный уровень |
FORTRAN, Pascal, C |
HDL (появился в 80-ых годах), Verilog |
Объектно- ориентированный уровень |
C++, C#, Java (сеть), Пролог (ИИ), Delphi 7, Simula, Modula |
Hardware - C |
Здесь приняты следующие сокращения:
RTL – Register Transfer Language,
CDL – Computer Digital Language,
DDL – Digital Design Language.
Приборно (машинно) -ориентированные языки предназначены для конкретных машин.
Процедурно- ориентированные языки подходят для любых машин. В них имеются не только последовательные, но и параллельные связи.
Объектно- ориентированные языки строятся как последовательность методов вызова объектов. Выходом компилятора с таких устройств является файл конфигурации.
Altera HDL.
Язык описания функционирования и структуры цифровых устройств. С его помощью можно описать автоматы (машины состояния — state mashine), комбинационные и регистровые схемы.
Язык полностью интегрирован с САПР MAX+plus II и Quartus. Модули на этом языке имеют расширение .tdf. Для создания описания могут быть использованы любые текстовые редакторы. Altera поддерживает иерархическое проектирование. Конечным результатом является создание файла конфигурации и размещение его на конкретной микросхеме, т.е. создание устройства.
Элементы языка.
Устройства и связи описываются с помощью имен. Существует три типа имен:
- символическое (Symbolic name);
- имя модуля (Sub design name);
- имя вывода (Port name) -буфер или регистр.
Символическое имя - описывается пользователем. Используется для задания: переменных, констант, состояний и разрядов конечного автомата, параметров, обозначаемых арифметических выражений, именованных операторов.
Имя модуля — определяется пользователем для именования модуля и логического файла (проекта), в котором хранится его текстовое описание.
Имя вывода — определяется пользователем для обозначения входного модуля, выходного модуля, двунаправленного вывода модуля, входа для импортируемого и выхода для экспортируемого конечного автомата.
Имя может быть задано в одной из двух форм:
- строкой символов длиной от 1 до 32 символов (Unquoted name – UQN) — имя без кавычек;
- строкой символов длиной от 1 до 32 символов (Quoted name – QN) — имя в одинарных кавычках.
Понятие групп.
Группа — набор однотипных переменных и выводов. Порядковый номер переменной или вывода в группе — это индекс. Максимальное число переменных/выводов ограничивается 256.
Существует три типа групп:
одномерные (single range);
двумерные (dual range);
последовательные (sequential) или временные.
Одномерные группы задаются символическим именем (имя группы) + диапазоном изменения индексов в группе.
Двумерные группы — имя группы + пара диапазонов изменения индексов.
Последовательные группы — задаются списком в скобках. Элементами списка могут быть переменные, выводы модуля, одномерные группы, двумерные группы.
Элементы группы отделяются друг от друга запятой.
Индексы одномерных и двумерных групп должны быть положительными числами в виде двух границ: [граница А .. граница В]
В-начало значения границы может быть число, арифметическое выражение, константа, параметр.
Порядок расположения индексов: А>В. Если он задан возрастающим или используются оба способа задания индексов, то рекомендуется установить опцию:
BIT 0 – MSB (most significant bit); BIT 0 = A. Примеры обозначений: 1) А[5..0] это А5,А4,А3,А2,А1,А0. 2) Constant upper = “4” это В [upper .. 1]
3) С[2x2..0][3..2] это С43, С42, С33, С32, С23, С22, С13, С12. - порядок размещения элементов группы. 4) D[1..4] это D1, D2, D3, D4 и опция. 5) (А, Е[2..1], F) это А,Е2, Е1, F.
Описывается:
-десятичными числами: 0..9;
-двоичными числами: В «0, 1, х»;
-восьмеричными: 0 «0-7» ; Q(q) «0-7»;
-шестнадцатеричными: X/H “0-9, А, B, C, D, E, F”.
Пример:
В «10Х01»= 10001 или 10101;
Х «А8».
Одноразрядные переменные могут быть только такими: b «1», b «0», VCC, GND (ground – низкий уровень).
Пример: out = b«0»;
out = 0 — неверно!
out = GND.
Выражения.
Существует два типа выражений:
-арифметические (arithmetic expressions (AE) ) ;
-логические ( Boolean exp. (BE) ).
Арифметические выражения используются для задания обозначаемого выражения в операторе обозначения: «define statement»; для задания констант: «constant statement»; границ диапазона изменения индексов группы, границ диапазона изменения внутренней переменной в операторе FOR GENERATE, оцениваемого выражения в операторе: IF GENERATE и ASSERT. Примеры:
Определить DEFINE М(а<b)=(а<b)? а:b (если а<b то а, иначе b)
CONSTANT const=1+2DIV(делить) 3+LOG(256);
A[2+4^2..3-2]:INPUT;
Результат арифметического выражения всегда целое число. Если получилось дробное число, то результат округляется до ближайшего большего целого (2/3=1).
Лекция 15.11.12
Иерархическая структура.
Примеры: Логические операторы: AND, NAND, OR, NOR, XOR, NXOR. Применяются к одноразрядным переменным, группам и числам. 1) R[4..1]=(A, B, C, D)# OP[3..0]
R4= A# OP 3
R3= B# OP 2
R2= C# OP 1
R1= D# OP 0
Должно быть везде одинаковое число разрядов (переменных). Может быть один операнд- группа, второй операнд- одна переменная. 2) R[3..1]=(a, B[2..1])&D
R3= a&D
R2= B2&D
R1= B1&D
3) Оба операнда могут быть числами (двоичными). Если разрядность разная, то она дополняется наращиванием разрядности меньшего операнда (дополняется нулями):
3814=B “0011” & B “1110”= B “0010”= 2
4) Один операнд - число; два операнда - группа (разряд).
Если число разрядов не совпадает:
R[3..1]= (a, b, c) & 3= (a, b, c) & B “011” => R3=a & 0= 0;
R2= b&1= b;
R1= c&1= c.
5) R[3..1]= (a, b, c)&9 => это ошибка, т. к. нечем дополнять разряды букв в группе до четырёх разрядов числа 9=11020314. Примитивы.
Это встроенное в языках HDL функциональное описание того или иного внутреннего ресурса ПЛИС.
Существует 2 класса примитивов:
-буфер;
-триггер: синхронный (Flip Flop); защёлки (Latch).
Примитивы буферов: 1) CARRY (цепочка)
2) CASCADE (буфер каскадного наращивания логических элементов) 3) EXP (буфер логического расширения), подключаются ресурсы соседних матриц. 4) GLOBAL ( буфер глобальной цепи распространения управляющего сигнала)
5) LCELL ( не удаляемый буфер размещения макро ячейки), т. е. будет зарезервирована одна макро ячейка . Удалить нельзя. Существенно увеличивает задержку
6) SOFT (удаляемый буфер размещения макро ячейки), для проверки упрощения реализации общих термов, для уменьшения аппаратных затрат. Делает сам компилятор) 7) TRI (тристабильный буфер). Имеет три входа. 8) OPNDNF (буфер выходной с открытым коллектором) Здесь: 1) и 2) — это FPGA (Flex) 3), 4) используются в CPLD.
Примитивы триггеров:
Примитив |
Прототип |
DFF (D- триггер) |
FUNCTION DFF (D, CLK, CREN, PRN) RETURNS (Q) |
DFFE |
FUNCTION DFFE (D, CLK, CREN, PRN, ENA) RETURNS (Q) |
TFF |
FUNCTION TFF (T, CLK, CREN, PRN) RETURNS (Q) |
TFFE |
FUNCTION TFFE (T, CLK, CREN, PRN, ENA) RETURNS (Q) |
JKFF |
FUNCTION JKFF (J, K, CLK, CREN, PRN) RETURNS (Q) |
JKFFE |
FUNCTION JKFFE (J, K, CLK, CREN, PRN, ENA) RETURNS (Q) |
SRFF |
FUNCTION SRFF (S, R, CLK, CREN, PRN) RETURNS (Q) |
SRFFE |
FUNCTION SRFFE (S, R, CLK, CREN, PRN, ENA) RETURNS (Q) |
LATCH |
FUNCTION LATCH (D, ENA) RETURNS (Q) |
Здесь:
CLK- сигнал тактовой частоты;
CREN- сигнал сброса ( установка в ноль);
PRN- установка в единицу;
ENA- сигнал разрешения (включения) работы триггера.
Лекция 22.11.12
Структура текстового описания
Title Statement — оператор заглавного имени;
Include Statement – оператор включения;
Constant – оператор констант;
Define – оператор обозначений;
Parameters Statement – оператор объявления параметров;
Function Prototype Statement – оператор описания прототипов;
Options Statement – оператор задания опций;
Assert Statement – оператор контроля.
Описание модуля (Subdesign Section)
- описание линий (node);
- описание регистров (register);
- состояние автоматов (state machines);
- оператор условия (If Generate Statement);
- (Machine Alice) – относится к автоматам.
Логическая секция (Logic Section)
Раздел описания логики:
- [Default Statement];
- [Assent Statement];
- [Boolean Equation];
- [Boolean Control Equation];
- [Case Statement];
- [For Generate Statement];
- [If Then Statement];
- [If Generate Statement] – реализует один из возможных вариантов проекта;
- [In line Logic Function] – вариант встраивания логических модулей;
- [Truth Table Statement] – таблица истинности.
Модули
Оператор заголовка Title Statement позволяет сгенерировать название файла отчета, создаваемого компилятором.
Пример: Title «Binary Counter»;
Оператор включения: Include Statement.
Этот оператор позволяет включать содержимое файлов.
Пример: Include «Low-level_project.inc»;
Оператор задания констант: Constant Statement.
Пример: 1) Constant upper_LIMIT=H”130”;
2) Constant BAR=1+upper_LIMIT DIV3-LOG2 (256);
3) Constant number = 5.
Вычисляется на этапе трансляции и не требует ресурсов ПЛИС.
Циклическое задание констант не допустимо.
Оператор обозначения: Define Statement. Позволяет обозначить арифметическое выражение символическим именем
PARAMETERS (WIDTH) – ширина;
DEFINE MAX (a, b) = (a > b) ? a:b;
SUBDESIGN DEF
(Data_a [max(width 2)..0]:INPUT;
Data_b [ ]:OUTPUT;
)
BEGIN
Data_b [ ] = Data_a [ ];
END.
Оператор объявления параметров: Parameters Statement. В качестве параметра может выступать символическое имя строки символов, заключенной в двойные кавычки, или числа, заданного либо явно, либо являющегося результатом выполнения арифметического выражения.
Пример:
1. PARAMETERS
(FILENAME = “myfile.nuf”,
WIDTH,
AD_WIDTH,
NUMWORDS = 2^AD_WIDTH;).
2. PARAMETERS (DEVICE FAMILE) – предопределенный параметр языка. Этот параметр задается в окне DEVICE.
Оператор описания прототипа: Function Prototype Statement.
FUNCTION PROTOTYPE STATEMENT. Позволяет описать интерфейс модулей или примитивов, которые будут использоваться в данном текстовом описании.
Примеры:
О
ператор
контроля
позволяет контролировать истинность
арифметического выражения и, в случае
если оно ложно, выдать текстовое сообщение
(уровень ошибки).\
Пример:
Severity error (определение ошибки)
ERROR – ошибка;
WARMING – предупреждение;
INFO – информация.
Раздел описания интерфейса модуля (SUBDESIGN SECTION)
Этот раздел задает имя модуля и перечисляет выводы модуля: входные и выходные. Имя модуля должно совпадать с именем логического файла, в котором хранится его текстовое описание. Если имя модуля является верхним уровнем иерархии, то имя является именем проекта.
Пример: SUBDESIGN list_project
(A, B [4..0]:INPUT = VCC;
D : INPUT = GND;
C [7..1]:OUTPUT
E [3..2]:BIDER
Имя файла, в котором хранится текстовое описание данного модуля: First_project.tdf.
После имени модуля следует заключенный в круглые скобки список его выводов.
Типы выводов:
INPUT;
OUTPUT;
BIDER – двунаправленный вывод;
MACHIN INPUT – машинный вывод (вход импортируемых состояний автомата);
MACHIN OUTPUT – выход экспортируемых состояний автомата.
Выводы перечисляются через “ , ”, а потом записывается слово, указывающее базовое значение.
Раздел переменных (VARIABLE SECTION).
VARIABLE SECTION – секция переменных. Назначение: позволяет задать внутренние переменные модуля, предназначенные для использования в разделе описания логики.
Переменная - это символическое имя: линии связи; линии связи с тремя состояниями; модуля, используемого в текстовом описания в качестве компонента ( примитива или конечного автомата). Пример:
Здесь:
INCLUDE “halfadd.inc”, - подключен текстовый полусумматор
VARIABLE – секция переменных (позволяет задавать внутренние переменные);
tsnode TRI_STATE_NODE - элемент с тремя состояниями выхода или линия с Z- состоянием;
ff: [3..0]:DFF; - четыре переменных: ff3, ff2, ff1, ff0;
DFF – 4D-триггера (примитив);
Описание автоматов:
AA : MACHINE of BITS with states (Q1, Q2, Q3);
где Q1, Q2, Q3 – состояния;
Кодировка состояний: (A0=B”000”)
(A1=B”001”)
(A2=B”011”)
В файле в тексте описания данный раздел может использоваться только 1 раз.
Раздел описания уровней (Logic Section):
В этом разделе могут быть использованы:
- оператор умалчивания (задание исходных значений) -Default Statement;
- логические уравнения:
Boolean Eguation
- логические уравнения для управляющих сигналов:
Boolean Control Eguation
- оператор выбора:
Case Statement
- оператор IF-THEN (если, то):
If then Statement
- оператор:
If Generate
- оператор непосредственного обращения к модулю нижнего уравнения:
In line Logic Funct Refrance
- таблица истинности:
Truth Table
Пример: F=a*c+a*b*d+a*d
SUBDESIGN
a, b, c, d: INPUT;
F: OUTPUT;
[логическая секция]: начинается со слова:
Begin
F=!a8!c#!a8b8d#a8!d;
End.
Можно сделать по-другому:
f1=ac;
f2=abd; F= f1+ f2+ f3.
f3=ad;
Перепишем программу:
SUBDESIGN
a, b, c, d: INPUT
F: OUTPUT
VARIABLE
f1, f2, f3: NODE
Begin
f1=!a8!c;
f2=!a8b8d;
f3= a8!d;
F= f1#f2#f3;
End.
Уравнения в логической секции выполняются одновременно, поэтому их можно писать в любом порядке. Если хотим наблюдать каждую линию, то f1, f2, f3 необходимо записать в OUTPUT, тогда это будут не внутренние линии, а выходы. Тогда:
Другой прием: использование неудаляемого буфера: LCELL.
Begin
f1=: LCELL(!a8!c);
f2=: LCELL(!a8b8d);
f3= : LCELL(a8!d);
F= f1#f2#f3;
End.
Пример 2:
SUBDESIGN : GR1
A[3..0]: INPUT;
B[4..1]: INPUT;
c, d, e, f: INPUT;
OUT[5..2]: OUTPUT;
Begin
OUT[5..2]=(A[3..0]≠ B[4..1])8!( c, d, e, f);
End.
Обработка идей поразрядно (то, что в скобках):
Пример 3:
SUBDESIGN : GR2
A[2..1]: INPUT;
R[1:0][2:1]: OUTPUT;
Begin
R[1:0][2:1]=(A[1..R],A[2..1]);
End.
Пример в виде таблицы истинности:
Приоритетный шифратор
К
лассический
шифратор: на входе унитарный, на выходе
– двоичный позиционный код:
3 |
2 |
1 |
|
||||
0 |
0 |
1 |
0 |
1 |
|||
0 |
1 |
0 |
1 |
0 |
|||
1 |
0 |
0 |
1 |
1 |
Унитарный код: на входе поступает только одна 1 единица, остальные все 0.
0H |
0M |
1L |
0 |
1 |
0 |
1 |
X |
1 |
0 |
1 |
X |
X |
1 |
1 |
Приоритеты( light, middle, high)
Определяем единицу с наивысшим приоритетом
X - неизвестно что придет ( либо 0, либо 1)
Имя проекта: PRCD(priority coder)
SUBDESIGN
H,M,L: INPUT;
BIN CODE[1:0]: OUTPUT;
Begin
Table
H,M,L =» BIN CODE[1:0];
1,X,X =» B”11”;
0,1,X =» B”10”;
0,0,1 =» B”01”;
0,0,0 =» B”00”;
End Table;
End.
Лекция 29.11.12
Оператор IF-THEN.
Структура может быть следующей:
IF – оцениваемое выражение (expression);
THEN – оператор (statement);
оператор (statement);
…
оператор (statement); и т.д.
ELSEIF - оцениваемое выражение (expression);
вложенные операторы
THEN – список операторов (statements);
оператор (statement);
…
оператор (statement); и т. д.
ELSE - оператор (statement);
…
оператор (statement); и т. д.
END IF;
Классическая структура условного оператора:
IF – оцениваемое выражение (expression);
THEN – оператор (statement);
оператор (statement);
…
оператор (statement); и т. д.
ELSE - оператор (statement);
END IF;
либо:
IF – оцениваемое выражение (expression);
THEN – оператор (statement);
…
оператор (statement); и т. д.
END IF;
Рассмотрим использование оператора IF THEN на примере описания Приоритетного шифратора: Н — наивысший приоритет; L – наименьший приоритет.
П
ример:
SUBDESIGN IF THEN
( H,M,L: INPUT
BINCODE [1..0] : OUTPUT
)
BEGIN
IF H==1;
THEN BINCODE [ ]=3;
ELSEIF M==1;
THEN BINCODE [ ]=2;
ELSEIF L==1;
THEN BINCODE [ ]=1;
ELSE BINCODE [ ]=0;
END IF;
END;
Оператор выбора CASE.
Позволяет осуществить выбор по нескольким направлениям (веткам). Может использоваться в одной из следующих форм:
О
ператор
CASE
позволяет оценить группу выводов, в
результате чего осуществить выбор
операторов.
Пример использования оператора CASE:
SUBDESIGN CASE
(H,M,L: INPUT;
BINCODE [1:0] : OUTPUT;
)
BEGIN
CASE (H,M,L) IS
WHEN B”1xx” => BINCODE [ ]=3;
WHEN B”01x” => BINCODE [ ]=2;
WHEN B”001” => BINCODE [ ]=1;
WHEN OTHER => BINCODE [ ]=0;
END CASE;
END;
Ветка WHEN OTHERS означает «для оставшихся» и может отсутствовать.
Базовые значения логических функций.
Необходимость задания базовых значений логических функций возникает тогда, когда они определены не на всех своих наборах аргументов, т. е. на некоторых из наборов (на их выходах) значения переменных появляться не могут.
Существует два способа задания базовых значений логических функций: явно / не явно.
По умолчанию всегда задается базовое значение — логический нуль. Приведем пример неявного задания базовых значений на примере.
Пример:
SUBDESIGN DEFAULT1
(A,B,C: INPUT;
F: OUTPUT;
)
BEGIN
TABLE
X1, X2, X3 => F;
0, 1, 0 => 1;
0, 1, 1 => 1;
1, 0, 0 => 1;
END TABLE;
END
Логические функции определены не на всех наборах аргументов. т. к. нет явного задания их базовых значений, то на оставшихся пяти наборах значение функции F будет равно 0.
Базовые значения могут быть заданы явно с помощью оператора DEFAULTS:
Использование этого оператора иллюстрируется в следующем примере:
Д
ля
оставшихся 12 наборов будет объявлено
значение В”00111111”, явно заданное в
операторе DEFAULTS
Оператор цикла FOR GENERATE.
Позволяет упростить запись последовательности сходных логических уравнений и операторов языка AHDL. Организует повторение операторов в цикле. Имеет следующий вид:
Диапазон (range) задается следующим образом:
IN начальное значение ТО конечное значение.
В качестве примера рассмотрим описание 8-ми разрядного СУММАТОРА.
Здесь: cin – carry in (входной перенос);
cout – carry out (выходной перенос);
i – i-тый разряд.
Лекция 6.12.12
Параметры
Язык AHDL позволяет создать параметризованное описание модуля – описание, адаптирующееся к конкретным условиям применения модуля, т.е. к конкретным значениям параметра.
Значение параметра, в отличие от значения константы, может быть задано вне того текстового описания, в котором этот параметр определен и используется.
Ниже приведено поведенческое (алгоритмическое) описание сумматора, разрядность которого определяется параметром ADD_WIDTH.
Описанный сумматор обеспечивает сложение двух ADD_WIDTH – разрядных операндов и формирование ADD_WIDTH – разрядного результата (SUM[ ]) и переноса в следующий разряд.
При объявлении параметру ADD_WIDTH присваивается исходное значение – восемь. Поэтому, если вне данного текстового описания ему не будет задано иное значение, то компилятор синтезирует восьмиразрядный сумматор.
Оператор IF GENERATE
Оператор IF GENERATE позволяет оценить значение арифметического выражения и по результатам оценки сформировать то или иное описание проектируемого модуля.
Оператор может использоваться в полной, либо в упрощенной форме.
Примитивы
Для использования в текстовом описании модуля примитива необходимо обратиться к встроенному в пакет функциональному описанию данного примитива и сопоставить его выводам числа, константы, переменные или выводы модуля.
В языке AHDL определены два способа обращения к примитиву:
непосредственное обращение (In_line Reference);
присвоение примитиву символического имени, т.е. объявление его переменной, и обращение к нему как к переменной.
Непосредственное обращение к примитиву осуществляется следующим образом:
указывается выход (либо внутренняя переменная) модуля, на который передается сигнал с выхода примитива;
далее ставится знак равенства и имя примитива;
за именем примитива в круглых скобках, через запятую перечисляются передаваемые значения: числа, константы, переменные или выводы модуля, сопоставляемые входам примитива;
за круглыми скобками ставится точка с запятой.
Сопоставление входов примитива с передаваемыми значениями может осуществляться:
позиционно;
по именам.
В качестве примера рассмотрим следующую схему:
Т
екстовое
описание:
При обращении к примитиву в списке передаваемых значений первым указан вход D_in. Поэтому он будет соединен с входом, указанные первым в описании прототипа примитива. Соответственно, вход Enable модуля будет соединен с входом OE примитива TRI.
Е
сли
некоторые из входов примитива не
используются, то соответствующие позиции
в списке передаваемых значений должны
быть оставлены пустыми. Проиллюстрируем
это на примере текстового описания
схемы, приведенной ниже:
Текстовое описание:
При сопоставлении передаваемых значений и входов примитива по именам в списке передаваемых значений через запятую перечисляются пары: вход, передаваемое значение. Формат записи:
Выход модуля (внутренняя переменная)= Имя примитива (.имя выхода = передаваемое значение.. имя выхода = передаваемое значение,…);
Пары могут быть расположены в произвольном порядке, т.е. независимо от того, в какой последовательности перечислены входы в описании прототипа примитива. Неиспользованные входы примитива в списке передаваемых значений не указывается.
Приведенное ниже текстовое описание схемы, логические схемы, логически эквивалентное текстовому описанию модуля Prim_in_line2, иллюстрируют данный способ сопоставления.
Другой способ обращения к примитиву – обращение к нему как к переменной.