Работа с VHDL в Sublime Text 3
Редактор Sublime Text существенно экономит время при работе с vhdl и verilog файлами. Для тех, кто не работал с редакторами типа Sublime Text, Notepad++ и т.п. опишу основные полезные функции данных редакторов:
- множественное выделение/редактирование строк кода (нажатие средней кнопки мыши или при зажатой клавише Ctrl)
- установка меток (закладок) в коде, помогает ориентироваться в больших файлах. (Ctrl + F2 или через пункт меню Goto> Bookmarks)
- возможность разделения рабочей области на несколько окон (Alt + Shift + 2 или из меню View> Layout)
- открытие одного файла несколько раз (File> New View into File)
- комментирование выделенных строк кода (Ctrl + /)
- поиск и замена (Ctrl + h)
- поиск по всем открытым файлам (Ctrl+Shift+f)
- вставка сниппетов (шаблонов кода) (написать ключевое слово + клавиша Tab)
- написание и использование функций на языке python
- возможность установки различных дополнений
- гибкая настройка
Интеграция Sublime Text
Для начала состыкуем САПР для работы с ПЛИС и редактор Sublime.
- Интеграция Sublime Text с Xilinx ISE:
в ISE идем в меню Edit > Preferences > Editors: Text Editor > Editor = Custom
Вставляем строку в окно «Command line syntax»:
{C:\Program Files\Sublime Text 3\sublime_text.exe} $1
- Интеграция Sublime Text с Xilinx Vivado:
Tools > Options > Text Editor > Current Editor: Sublime
или
Tools > Options > Text Editor > Current Editor: Custom Editor
Указываем путь до редактора, например:
C:\Program Files\Sublime Text 3\sublime_text.exe [file name]
Плагины
Различные плагины (packages) расширяют функциональность редактора. Packages можно
устанавливать как в онлайн так и оффлайн-режиме.
Для установки плагинов в офлайн-режиме нужно проделать нехитрые манипуляции:
- Скачиваем нужный плагин с GitHub
- Извлекаем из архива
- Переименовываем папку, например, «Sublime-HDL-master» в «Sublime HDL»
- Полученные папки копируем в папку Packages (расположение данной папки легко найти, выбрав в Sublime Text пункт меню Preferences > Browse Packages)
SyncViewScroll — плагин для синхронизации вертикальной и горизонтальной прокрутки при работе в нескольких окнах. Для работы плагина надо для каждого окна выбрать в меню View> Sync Scroll.
Text Pastry – плагин для автоматической множественной нумерации. Очень помогает при работе с большим количеством нумерованных сигналов/портов.
Как работать с Text Pastry
- Выделяем нужные участки строк
- Вызываем меню Ctrl+Shift+P
- Ищем пункт “Text Pasty Command Line”
- В появившемся окне, расположенном в нижней части экрана, вводим:
- 0 — нумерация от 0
- \i(1,10) — нумерация от 1 с инкрементом 10
- 1 end=4 — нумерация 1, 2, 3, 4, 1, 2, 3, 4 и т.д.
- letters a-c upper — A, B, C, A, B, C, и т.д.
- letters a-c upper x3 — A, A, A, B, B, B, C, C, C и т.д.
- 1 x3 — 1, 1, 1, 2, 2, 2, 3, 3, 3, и т.д.
- x y z — x, y, z, x, y, z, x, y, z, и т.д.
Sublime Verilog — поддержка синтаксиса языка Verilog
Verilog Gadget – набор функций и сниппетов для работы с Verilog файлами.
SmartVHDL — поддержка синтаксиса языка VHDL. Также при наведении на сигнал или порт в коде появится окно с подсказкой о типе (количество бит) данного сигнала/порта. При наведении на сигнал в контекстном меню появится пункт “Goto Definishion” — переход к месту объявления сигнала.
VHDL Mode – набор функций и сниппетов для работы с VHDL файлами. Основная часть функций запускается, например, сочетанием клавиш Atl+K, C, P, где C и P нажимаются поочередно. Основные функции:
- Копирование данных портов (названия портов, типы данных)
- Вставка данных портов как объявление сигналов
- Вставка данных портов как объявление компонента
- Генерация тестбенча по скопированным данным портов
- Автоформатирование кода (выравнивание табуляции и т.п.)
Поддержка ucf файлов
По умолчанию редактор Sublime не у меет работать с ucf-файлами. Разметка ucf эквивалентна разметке языка tcl. Осталось только объяснить это редактору:
- Создадим в папке Packages новый файл Tcl.sublime-settings
- Заполним файл строкой
{"extensions" : ["ucf"]}
- Сохраним файл
Создание шаблонов кода (snippets)
Пусть нам надо вставить шаблон кода:
My_proc : Process(clk, rst, data_in)
begin
if(clk'event and clk = '1') then
if(rst = '1') then
else then -- rst = 0
end if; -- data_in
end if;--clk
end process My_proc;
Причем нам бы хотелось, чтобы после вставки текста по нажатию Tab курсор устанавливался на позиции My_proc, clk, rst, data_in, для быстрого изменения значений этих данных. Для этого создадим новый сниппет:Tools > Developer > New Snippet. Редактируем данные:
<snippet>
<description>process rst</description>
<content><![CDATA[
${1:<PROCESS_NAME>} : Process(${2:clk}, ${3:rst}, ${4:data_in})
begin
if($2'event and $2 = '1') then
if($3 = '1') then
${5}
else then -- $3 = 0
$0
end if; -- $4
end if;--$2
end process $1;
]]></content>
<tabTrigger>procrst</tabTrigger>
<scope>source.vhdl</scope>
</snippet>
Сохраняем данный сниппет. Теперь при написании ключевого слова procrst в текущую позицию курсора будет вставлен наш шаблон.
Подробнее о создании шаблонов читайте в статье «Как создать сниппет?».
Написание собственных функций на языке python
Подробно о создании функций (плагинов) описывалось в статьях «Как написать простой плагин», «Как написать сложный плагин».
Вставка сниппетов это, конечно хорошо, но хотелось бы, например, чтобы тот же шаблон создания процесса заполнялся автоматически в зависимости от входных сигналов, а также чтобы процесс модифицировался при наличии таких сигналов как rst и ce. Еще обычно после процесса идет присвоение внешним портам модуля значений внутренних сигналов, пусть тоже делается автоматически.
Для парсинга данных файла VHDL воспользуемся функциями плагина Vhdl mode.
Примерный алгоритм наших действий:
- Получить данные о всех портах модуля
- Все порты типа «in» включить в шапку процесса
- Если есть порты с названием ce и/или rst, то добавить соответствующие условия if else в процесс
- За процессом вставить строки присвоения выходным портам значений внутренних сигналов (обычно такие сигналы называют также как и порт, добавляя приставку «s_» или "_net")
Для начала создадим новый сниппет:
<snippet>
<tabTrigger>procclk</tabTrigger>
<scope>source.vhdl</scope>
<content><![CDATA[
${DATAINPORTS}
${OUTPORTS}
]]></content>
<description>process clk</description>
</snippet>
Здесь ${DATAINPORTS} – метка, куда будет вставлено описание процесса,
${OUTPORTS} — метка, где будет присвоение внешним выходным портам значений внутренних сигналов.
Сохраним его под именем, например, test.sublime-snippet в папку VHDL Mode/Snippets.
Воспользуемся написанными функциями в папке VHDL Mode. Так как знания языка python у меня начальные, то будем модифицировать функции плагина, по аналогии с уже описанными в нем.
Создадим в файле vhdl_lang.py новые функции в классе Interface(), назовем их in_port и out_port:
Функции
def in_port(self):
"""
Generate Process depending on the input ports
"""
lines = []
bus_index = ""
max_data = ""
my_ports = ""
is_clk = False
is_ce = False
is_rst = False
if self.if_ports:
for port in self.if_ports:
if port.mode.lower() == 'in':
if port.name.lower() == ('clk'):
is_clk = True
my_ports = port.name
else:
if port.name.lower() == ('ce'):
is_ce = True
elif port.name.lower() == ('rst'):
is_rst = True
my_ports = my_ports + ", " + port.name
lines.append("Process("+ my_ports +')' )
lines.append("begin")
if is_clk:
lines.append(" if(clk'event and clk = '1') then")
lines.append("")
if is_rst and is_ce:
lines.append("if(rst = '1') then")
lines.append("")
lines.append("elsif (ce = '1') then")
lines.append("")
lines.append("end if; -- rst")
elif is_rst:
lines.append("if(rst = '1') then")
lines.append("")
lines.append("else -- working body ")
lines.append("")
lines.append("end if; -- rst")
elif is_ce:
lines.append("if (ce = '1') then")
lines.append("")
lines.append("end if; --
lines.append(" end if;--clk")
lines.append("end process;")
# lines.append(str(testind
indent_vhdl(lines, 1)
return '\n'.join(lines)
else:
return None
def out_port(self):
"""
Generate data after Process
"""
lines = []
if self.if_ports:
for port in self.if_ports:
if port.mode.lower() == 'out':
lines.append("{} <= {}_net;".format(port.name, port.name))
indent_vhdl(lines, 1)
return '\n'.join(lines)
else:
return None
Функция out_port вставляет за процессом строки, например:
data_out1 <= data_out1_net;
data_out2 <= data_out2_net;
Создадим в папке VHDL Mode новый файл, назовем его my_func.py, вставим текст:
import sublime
import sublime_plugin
from.import vhdl_interface as face
class PasteAsProcess(sublime_plugin.TextCommand):
def run(self, edit):
snippet_clk = "Packages/VHDL Mode/Snippets/test.sublime-snippet"
in_port_str = face._interface.in_port()
out_port_str = face._interface.out_port()
self.view.run_command("insert_snippet",
{
"name" : snippet_clk,
"DATAINPORTS" : in_port_str,
"OUTPORTS" : out_port_str
})
print('paste_as_process')
Осталось присвоить горячие клавиши. Так как наш класс называется PasteAsProcess, то команда должна называться paste_as_process (перед символами, кроме первого, написанными в верхнем регистре нужно поставить знак нижнего подчеркивания).
Идем Preferences > Key Bildings. Вставляем строку:
{"keys": ["alt+k", "p", "z"], "command": "paste_as_process", "context": [{"key": "selector", "operand": "source.vhdl"}] },
Теперь для работы нам надо сначала скопировать значения портов vhdl файла сочетанием клавиш «alt+k», «p», «w» (по умолчанию). Затем вызвать нашу функцию клавишами «alt+k», «p», «z».
Вывод
Сниппеты и функции значительно упрощают работу с vhdl файлами.
Даже начальных знаний языка python достаточно для написания простых, но рабочих функций.
P.S.: Оставлю ссылку на папку с моими настройками. Для работы, надо заменить папку Sublime Text 3 по адресу: C:\Users\User\AppData\Roaming\
Мои сниппеты:
- sint (Signal integer), sstd, svector — шаблоны описания сигналов соответствующего типа
- ibuf, ibufds и т.д. — описание буферов
- generichelp — подсказка пример, как правильно применить generic
- teststd, testvector и т.д. — процессы для тестбенча с сответствующими типами данных
- procclk, procce, procrst — процессы с сигналами clk, ce, rst
- clk, net, inst — шаблоны для ucf файлов
Мои функции:
- Cвязка Alt+K,C,P (Copy Ports), Alt+K,P,Z — вставка процесса описанного с этой статье
- Cвязка Alt+K,C,P (Copy Ports), Alt+K,P,T (Paste Testbench) — переделал функцию плагина VHDL MODE, теперь генерируются тестовые процессы для всех входных сигналов
Комментарии (2)
Skryp Автор
21.04.2018 11:39Если нужен процесс только с сигналом clk или ce или rst я использую шаблоны procclk, procce, procrst. Шаблоны для тестбенчей вызываются по ключевым словам teststd, testfor, testvector, testrand, testfile. В ссылке на мои настройки на GitHub можно посмотреть соответствующие сниппеты.
KeisN13
Хорошая статья, доходчиво написано. Может имеет смысл дополнить примерами шаблонов для тестбенчей. Думаю Vivado всем дико доставляет отсутствием возможности автоматической генерации шаблона тестбенча модуля.
Я надеюсь что не заминусуют за это, но при описании синхронного процесса с синхронным сбросом My_proc в листе чувствительности кроме сигнала clk другие сигналы указывать не обязательно.
Сам пользуюсь стандартным редактором Vivado, надеюсь за это тоже не заминусуют.
Ждём новых полезных сниппетов и руководств. Спасибо.