Проектирование КИХ-фильтров в САПР ПЛИС Xilinx ISE Design Suite
Рассмотрим простейшие примеры проектирования КИХ-фильтров в базисе ПЛИС фирмы Xilinx с помощью САПР ISE Design Suite версии 14.2. Для ускорения процесса разработки проекта КИХ-фильтра воспользуемся генератором параметризированных ядер XLogiCORE IP — функцией FIR Compiler v6.3. Выберем бюджетную ПЛИС Spartan‑6 XC6SLX4 с поддержкой протокола AXI, содержащую восемь ЦОС-блоков DSP48A1, располагающихся в двух секциях по четыре в каждой.
На рис. 1 показан проект КИХ-фильтра в САПР ПЛИС Xilinx ISE 14.2 с использованием генератора параметризированных ядер XLogiCORE IP FIR Compiler v6.3.
Настройка функции FIR Compiler v6.3 осуществляется в несколько шагов. Задаются варианты считывания значений коэффициентов КИХ-фильтра: из текстового файла (.coe) или представление в виде вектора значений, а также параметры спецификации фильтра (рис. 2).
По известным коэффициентам происходит построение АЧХ КИХ-фильтра в автоматическом режиме. Задаются границы полосы пропускания и задерживания (подавления), неравномерность АЧХ в полосе пропускания и минимальное затухание в полосе задерживания.
Выбирается одноканальная структура фильтра типа Single-Rate FIR (входная частота дискретизации равна выходной частоте дискретизации). Частота дискретизации определяется как fclk/N для несимметричного и как fclk/N+1 для симметричного фильтра, где fclk/N — частота тактирования ядра фильтра; N — разрядность входной шины данных (точность представления входных значений, подлежащих фильтрации). Частота тактирования ядра фильтра установлена в 250 МГц а входная частота дискретизации — 50 МГц.
Проектирование КИХ-фильтра осуществляется в формате с фиксированной запятой. На рис. 3 показан учет эффектов квантования. Коэффициенты фильтра несимметричные, целочисленные со знаком С0 = –2, С1 = –1, С2 = 7 и С3 = 6, разрядность представления коэффициентов — четыре бита. Предполагаем, что на вход фильтра поступают только целые значения, как со знаком, так и без, например –5, 3, 1, 0. Разрядность представления значений входного сигнала, подлежащего фильтрации, — четыре бита, профильтрованного сигнала — восемь бит. Под дробную часть числа в обоих случаях отводим 0 бит (Input Data Fractional Bits и Output Fractional Bits).
На рис. 4 показан выбор структуры фильтра. Используем прямую форму систолического фильтра, в котором операции умножения и сложения выполняются параллельно с конвейеризацией (рис. 5). В каждой секции доступно четыре ЦОС-блока, располагающихся в столбец, а для реализации КИХ-фильтра требуется один ЦОС-блок.
Применение систолических КИХ-фильтров в проектах помогает существенно уменьшить число используемых ресурсов и повысить быстродействие. Поддержка систолических структур также обеспечивается мегафункцией (ALTMULT_ADD) САПР Altera Quartus II для работы с ЦОС-блоками ПЛИС серий Cyclon V, Arria V и Stratix V.
Для симуляции проекта в автоматическом режиме сгенерируем тестбенч (файл теста на языке VHDL для заданий значений входных сигналов, или Test Bench-файл) (пример 1). На рис. 6 показан симулятор ISim САПР ПЛИС Xilinx ISE 14.2. Демонстрируется прохождение единичного импульса по структуре фильтра (импульсная характеристика КИХ-фильтра на четыре отвода, полученная с помощью тестбенча, сгенерированного в автоматическом режиме). Латентность фильтра — 11 тактов синхрочастоты. Для размещения проекта в базис ПЛИС XC6SLX4 требуется 48 триггеров, тактируемых фронтом синхросигнала из общих логических ресурсов ПЛИС, и один ЦОС-блок DSP48A1.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity tb_fir_compiler_v6_3 is end tb_fir_compiler_v6_3; architecture tb of tb_fir_compiler_v6_3 is ------------------------------------- -- Timing constants ------------------------------------- constant CLOCK_PERIOD : time := 100 ns; constant T_HOLD : time := 10 ns; constant T_STROBE : time := CLOCK_PERIOD - (1 ns); ------------------------------------- -- DUT signals ------------------------------------- General signals signal aclk : std_logic := '0'; -- the master clock -- Data slave channel signals signal s_axis_data_tvalid : std_logic := '0'; -- payload is valid signal s_axis_data_tready : std_logic := '1'; -- slave is ready signal s_axis_data_tdata : std_logic_vector(7 downto 0) := (others => '0'); -- data payload -- Data master channel signals signal m_axis_data_tvalid: std_logic := '0'; -- payload is valid signal m_axis_data_tdata : std_logic_vector(7 downto 0) := (others => '0'); -- data payload ---------------------------------------- -- Aliases for AXI channel TDATA and TUSER fields -- These are a convenience for viewing data in a simulator waveform viewer. -- If using ModelSim or Questa, add "-voptargs=+acc=n" to the vsim command -- to prevent the simulator optimizing away these signals. ----------------------------------------- -- Data slave channel alias signals signal s_axis_data_tdata_data: std_logic_vector(3 downto 0) := (others => '0'); -- Data master channel alias signals signal m_axis_data_tdata_data: std_logic_vector(7 downto 0) := (others => '0'); begin ----------------------------------------- -- Instantiate the DUT ----------------------------------------- dut : entity work.fir_compiler_v6_3 port map ( aclk => aclk, s_axis_data_tvalid => s_axis_data_tvalid, s_axis_data_tready => s_axis_data_tready, s_axis_data_tdata => s_axis_data_tdata, m_axis_data_tvalid => m_axis_data_tvalid, m_axis_data_tdata => m_axis_data_tdata ); ------------------------------------------ -- Generate clock ------------------------------------------ clock_gen : process begin aclk <= '0'; wait for CLOCK_PERIOD; loop aclk <= '0'; wait for CLOCK_PERIOD/2; aclk <= '1'; wait for CLOCK_PERIOD/2; end loop; end process clock_gen; ------------------------------------------ -- Generate inputs ------------------------------------------ stimuli : process -- Procedure to drive a number of input samples with specific data -- data is the data value to drive on the tdata signal -- samples is the number of zero-data input samples to drive procedure drive_data ( data : std_logic_vector(7 downto 0); samples : natural := 1 ) is variable ip_count : integer := 0; begin ip_count := 0; loop s_axis_data_tvalid <= '1'; s_axis_data_tdata <= data; loop wait until rising_edge(aclk); exit when s_axis_data_tready = '1'; end loop; ip_count := ip_count + 1; wait for T_HOLD; -- Input rate is 1 input each 5 clock cycles: drive valid inputs at this rate s_axis_data_tvalid <= '0'; wait for CLOCK_PERIOD * 4; exit when ip_count >= samples; end loop; end procedure drive_data; -- Procedure to drive a number of zero-data input samples -- samples is the number of zero-data input samples to drive procedure drive_zeros ( samples : natural := 1 ) is begin drive_data((others => '0'), samples); end procedure drive_zeros; -- Procedure to drive an impulse and let the impulse response emerge on the data master channel -- samples is the number of input samples to drive; default is enough for impulse response output to emerge procedure drive_impulse ( samples : natural := 11 ) is variable impulse : std_logic_vector(7 downto 0); begin impulse := (others => '0'); -- initialize unused bits to zero impulse(3 downto 0) := "0001"; drive_data(impulse); if samples > 1 then drive_zeros(samples-1); end if; end procedure drive_impulse; begin -- Drive inputs T_HOLD time after rising edge of clock wait until rising_edge(aclk); wait for T_HOLD; -- Drive a single impulse and let the impulse response emerge drive_impulse; -- Drive another impulse, during which demonstrate use and effect of AXI handshaking signals drive_impulse(2); -- start of impulse; data is now zero s_axis_data_tvalid <= '0'; wait for CLOCK_PERIOD * 25; -- provide no data for 5 input samples worth drive_zeros(2); -- 2 normal input samples s_axis_data_tvalid <= '1'; wait for CLOCK_PERIOD * 25; -- provide data as fast as the core can accept it for 5 input samples worth drive_zeros(2); -- back to normal operation -- End of test report "Not a real failure. Simulation finished successfully." severity failure; wait; end process stimuli; ---------------------------------- -- Check outputs ---------------------------------- check_outputs : process variable check_ok : boolean := true; begin -- Check outputs T_STROBE time after rising edge of clock wait until rising_edge(aclk); wait for T_STROBE; -- Do not check the output payload values, as this requires the behavioral model -- which would make this demonstration testbench unwieldy. -- Instead, check the protocol of the master DATA channel: -- check that the payload is valid (not X) when TVALID is high if m_axis_data_tvalid = '1' then if is_x(m_axis_data_tdata) then report "ERROR: m_axis_data_tdata is invalid when m_axis_data_tvalid is high" severity error; check_ok := false; end if; end if; assert check_ok report "ERROR: terminating test with failures." severity failure; end process check_outputs; ------------------------------------- -- Assign TDATA / TUSER fields to aliases, for easy simulator waveform viewing ------------------------------------- -- Data slave channel alias signals s_axis_data_tdata_data <= s_axis_data_tdata(3 downto 0); -- Data master channel alias signals: update these only when they are valid m_axis_data_tdata_data <= m_axis_data_tdata(7 downto 0) when m_axis_data_tvalid = '1'; end tb;
Пример 1. Тестбенч КИХ-фильтра на четыре отвода, сгенерированный в автоматическом режиме для моделирования импульсной характеристики
Рассмотрим случай, когда проект представлен единственным vhdl-файлом (пример 2) и тестбенчем (fir4_test_bench) (пример 3). На вход КИХ-фильтра будут поступать входные отсчеты –5, 3, 1 и 0 (метка tb в файле fir4_test_bench, пример 3).
По VHDL-коду (файл filter4_4.vhd) создаем символ (рис. 7), добавляем порты ввода/вывода и делаем верхним уровнем иерархии проекта схемный файл (.sch). На рис. 8 показаны временные диаграммы работы КИХ-фильтра на четыре отвода. Латентность фильтра — один такт синхрочастоты.
Для размещения проекта в базис Virtex‑4 XC4VFX12 требуется 16 триггеров, тактируемых фронтом синхросигнала, и восемь 4‑входовых LUT из общих логических ресурсов ПЛИС и четыре ЦОС-блока DSP48.
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity filter_4 is port (din : in std_logic_vector(3 downto 0); reset, clk : in std_logic; Sout : out std_logic_vector(7 downto 0)); end filter_4; ARCHITECTURE a OF filter_4 IS constant С0: std_logic_vector(3 downto 0) :="1110"; constant С1: std_logic_vector(3 downto 0) :="1111"; constant С2: std_logic_vector(3 downto 0) :="0111"; constant С3: std_logic_vector(3 downto 0) :="0110"; signal x0,x1,x2,x3:std_logic_vector(3 downto 0); signal m0,m1,m2,m3:std_logic_vector(7 downto 0); BEGIN m0<=(signed(x0)*signed(C0)); m1<=(signed(x1)*signed(C1)); m2<=(signed(x2)*signed(C2)); m3<=(signed(x3)*signed(C3)); Sout<=(signed(m0)+signed(m1)+ signed(m2)+signed(m3)); process(clk,reset) begin if reset='1' then x0<=(others=>'0'); x1<=(others=>'0'); x2<=(others=>'0'); x3<=(others=>'0'); elsif (clk'event and clk='1') then x0(3 downto 0) <=din(3 downto 0); x1(3 downto 0) <=x0(3 downto 0); x2(3 downto 0) <=x1(3 downto 0); x3(3 downto 0) <=x2(3 downto 0); end if; end process; END a;
Пример 2. VHDL-код КИХ-фильтра на четыре отвода
LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY fir4_test_bench IS END fir4_test_bench; ARCHITECTURE behavior OF fir4_test_bench IS COMPONENT filter_4 PORT( din : IN std_logic_vector(3 downto 0); Sout : OUT std_logic_vector(7 downto 0); reset, clk : IN std_logic ); END COMPONENT; signal din : std_logic_vector(3 downto 0) := "1011"; signal reset : std_logic := '1'; signal clk : std_logic := '0'; signal Sout : std_logic_vector(7 downto 0); BEGIN uut: filter_4 PORT MAP ( din => din, Sout => Sout, reset => reset, clk => clk ); clk_process :process begin clk <= '0'; wait for 50 ns; clk <= '1'; wait for 50 ns; end process; process begin wait for 80 ns; reset <= '0'; end process; tb : process begin wait for 100 ns; din <= "1011"; wait for 100 ns; din <= "0011"; wait for 100 ns; din <= "0001"; wait for 100 ns; din <= "0000"; wait; END process; END;
Пример 3. Тестбенч КИХ-фильтра на четыре отвода для моделирования прохождения сигнала по структуре фильтра
Рассмотрим применение синтезатора Synplicity Synplify для переноса проектов из САПР печатных плат OrCad в САПР ПЛИС Xilinx ISE Design Suite. В этом случае проект КИХ-фильтра в САПР Xilinx ISE будет представлен единственным edif-файлом. САПР Xilinx ISE допускает использование средств синтеза сторонних разработчиков САПР на этапе компиляции проекта. Компиляция представляет собой процесс преобразования описания проекта в его структурную реализацию на выбранном кристалле ПЛИС. Составной частью процесса компиляции проекта является этап анализа и синтеза.
Созданные проектировщиком файлы описания проекта на языке VHDL могут быть преобразованы средствами синтеза логики в технологически специфицируемый (Technology-specific netlist) файл соединений или список связей в формате EDIF (Electronic design interchange format, формат для обмена электронными проектами между различными САПР) (.edf), который затем используется в САПР ПЛИС Xilinx ISE 14.2 на этапах размещения и трассировки.
Иерархическая структура edif-формата включает библиотечные модули, модули ячеек, программу просмотра, интерфейсный модуль, информационный модуль и схемные представления.
Программа синтеза логики Synplicity транслирует и оптимизирует VHDL-проекты на уровне RTL-представления в список соединений в формате EDIF, эквивалентный уровню примитивных логических элементов (уровень вентилей), то есть осуществляет переход с RTL-уровня на уровень вентилей. Комбинационные функции при этом отображаются в таблицы соответствий (LUT) ПЛИС. Этот формат затем компилируется в различный технологический базис ПЛИС. Доступны технологические базисы различных производителей ПЛИС: Xilinx, Altera, Actel, Lattice, QuickLogic и Silicon Blue.
Предположим, что иерархический проект (файл fir4.dsn) КИХ-фильтра на четыре отвода разработан в САПР (release 16.6) печатных плат orCAD версии 16.6 (рис. 9 и 10) с использованием схемного редактора Capture CIS для последующей реализации в базисе ПЛИС Xilinx серии Virtex. Проект состоит из схемных символов‑примитивов САПР orCAD (интерфейс — порты ввода/вывода, шины, сигналы) и объекта на языке VHDL (файл filter_4, поведенческое описание).
С помощью меню Create Netlist сформируем edn-файл, который представляет собой файл в формате EDIF200 (рис. 11). САПР ПЛИС Quartus II читает edn-файлы (пример 4, рис. 12), созданные в САПР OrCad, «своими» средствами синтеза, а САПР Xilinx ISE — нет. В этом случае проект в САПР ПЛИС Quartus II состоит из двух файов: FIR4.EDN и filter_4.vhd.
(edif fir4 (edifVersion 2 0 0) (edifLevel 0) (keywordMap (keywordLevel 0)) (status (written (timeStamp 2014 08 05 18 41 27) (program "EXPRESS.EXE" (Version "16.6.0.d001")) (comment "Original data from OrCAD/CAPTURE schematic")) (external OrCAD_LIB (edifLevel 0) (technology (numberDefinition (scale 1 1 (unit distance)))) (cell filter_4 (cellType generic) (comment "From OrCAD library ") (view NetlistView (viewType netlist) (interface (port (array (rename din "din[3..0]") 4) (direction INPUT)) (port reset (direction INPUT)) (port clk (direction INPUT)) (port (array (rename Sout "Sout[7..0]") 8) (direction OUTPUT)))))) (library MAIN_LIB (edifLevel 0) (technology (numberDefinition (scale 1 1 (unit distance)))) (cell fir4 (cellType generic) (view NetlistView (viewType netlist) (interface (port (array (rename din "din[3..0]") 4) (direction INPUT)) (port (array (rename Sout "Sout[7..0]") 8) (direction OUTPUT)) (port reset (direction INPUT)) (port clk (direction INPUT))) (contents …
Пример 4. Фрагмент edn-файла проекта КИХ-фильтра
Поэтому для перевода проекта из САПР печатных плат orCAD в САПР Xilinx ISE будем использовать сторонние средства синтеза. Вначале с помощью меню Create Netlist (рис. 13) схемного редактора Capture извлечем из файла проекта (fir4.dsn) vhdl-код, который представляет собой структурное описание проекта (пример 5).
LIBRARY IEEE; USE IEEE.std_logic_1164.all; ENTITY fir4 IS PORT ( din : IN std_logic_vector(3 DOWNTO 0); Sout : OUT std_logic_vector(7 DOWNTO 0); reset : IN std_logic; clk : IN std_logic ); END fir4; ARCHITECTURE STRUCTURE OF fir4 IS -- COMPONENTS COMPONENT filter_4 PORT ( din : IN std_logic_vector(3 DOWNTO 0); reset : IN std_logic; clk : IN std_logic; Sout : OUT std_logic_vector(7 DOWNTO 0) ); END COMPONENT; BEGIN fir : filter_4 PORT MAP( din(3) => DIN(3), din(2) => DIN(2), din(1) => DIN(1), din(0) => DIN(0), reset => RESET, clk => CLK, Sout(7) => SOUT(7), Sout(6) => SOUT(6), Sout(5) => SOUT(5), Sout(4) => SOUT(4), Sout(3) => SOUT(3), Sout(2) => SOUT(2), Sout(1) => SOUT(1), Sout(0) => SOUT(0) ); END STRUCTURE;
Пример 5. Структурное описание проекта на языке VHDL (vir4.vhd)
Далее в программе синтеза логики Synplicity Synplify (рис. 14) разработаем проект КИХ-фильтра на четыре отвода, состоящий из двух файлов .vhdl: верхнего vir4.vhd (пример 5) и нижнего filter_4.vhd уровня (пример 2).
На рис. 15 показан выбор технологического базиса для реализации проекта. В настройках синтезатора Synplicity заказываем выходной файл .edf (пример 6) и выбираем для реализации проекта ПЛИС типа ППВМ серии Virtex-II XC2V40. На рис. 16 представлена структурная схема КИХ-фильтра (линия задержки, умножители, дерево сумматоров) на RTL-уровне, синтезированная по VHDL-коду средствами Synplicity, подготовленная для реализации в технологический базис ПЛИС Virtex-II XC2V40. А на рис. 17 приведен фрагмент схемы КИХ-фильтра на уровне логических элементов, размещенный в этот базис.
После генерации edif-файла разработаем проект в САПР ПЛИС Xilinx ISE 14.2. Назначим верхним уровнем иерархии проекта файл filter_4.edf, сгенерированный в Synplicity. Для реализации проекта будем использовать ПЛИС серии Virtex‑4 XC4VFX12, выполненную в другом технологическом базисе в отличие от ПЛИС Virtex-II XC2V40.
Для размещения проекта в базис Virtex‑4 XC4VFX12 требуется 16 триггеров, тактируемых фронтом синхросигнала, и тридцать пять 4‑входовых LUT из общих логических ресурсов ПЛИС. Аппаратные ЦОС-блоки DSP48 при этом не используются.
(edif (rename filter_4 "fir4") (edifVersion 2 0 0) (edifLevel 0) (keywordMap (keywordLevel 0)) (status (written (timeStamp 2014 8 13 12 8 52) (author "Synopsys, Inc.") (program "Synplify" (version "E-2010.09-1, mapper maprc, Build 142R")) ) ) (library VIRTEX (edifLevel 0) (technology (numberDefinition )) (cell IBUFG (cellType GENERIC) (view PRIM (viewType NETLIST) (interface (port O (direction OUTPUT)) (port I (direction INPUT)) ) ) ) (cell IBUF (cellType GENERIC) (view PRIM (viewType NETLIST) (interface (port O (direction OUTPUT)) (port I (direction INPUT)) ) ) ) (cell OBUF (cellType GENERIC) (view PRIM (viewType NETLIST) (interface (port O (direction OUTPUT)) (port I (direction INPUT)) ) ) ) (cell LUT4 (cellType GENERIC) (view PRIM (viewType NETLIST) (interface (port I0 (direction INPUT)) (port I1 (direction INPUT)) (port I2 (direction INPUT)) (port I3 (direction INPUT)) (port O (direction OUTPUT)) ) ) )
Пример 6. Фрагмент edf-файла КИХ-фильтра, полученный с помощью синтезатора Synplicity
Разработаем тестбенч (fir4_test_bench) для симуляции и подключим его к проекту. Имя компоненты в файле тестбенча необходимо изменить на fir4 (пример 7) в отличие от имени компоненты в тестбенче примера 3. Тестбенч описывает моделирование импульсной характеристики фильтра (рис. 18). Латентность фильтра также составляет один такт синхрочастоты.
LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY fir4_test_bench IS END fir4_test_bench; ARCHITECTURE behavior OF fir4_test_bench IS COMPONENT fir4 PORT( din : IN std_logic_vector(3 downto 0); Sout : OUT std_logic_vector(7 downto 0); reset : IN std_logic; clk : IN std_logic ); END COMPONENT; signal din : std_logic_vector(3 downto 0) := "0001"; signal reset : std_logic := '0'; signal clk : std_logic := '0'; signal Sout : std_logic_vector(7 downto 0); BEGIN uut: fir4 PORT MAP ( din => din, Sout => Sout, reset => reset, clk => clk ); clk_process :process begin clk <= '0'; wait for 50 ns; clk <= '1'; wait for 50 ns; end process; process begin wait for 30 ns; reset <= '0'; end process; tb : process begin wait for 100 ns; din <= "0001"; wait for 100 ns; din <= "0000"; wait for 100 ns; din <= "0000"; wait for 100 ns; din <= "0000"; wait; END process; END;
Пример 7. Тестбенч импульсной характеристики КИХ-фильтра на четыре отвода
Выводы
Проекты КИХ-фильтров на четыре отвода, разработанные в САПР ПЛИС Xilinx ISE с применением генератора параметризированных ядер XLogiCORE и представленные с помощью единственных файлов .vhdl и .edf, работают корректно. Файлы .vhdl, извлеченные из проекта, созданного в САПР печатных плат OrCAD, могут быть преобразованы в edif-формат c помощью программы синтеза логики Synplicity, который может быть прочитан САПР ПЛИС Xilinx ISE 14.2. Использование средств синтеза логики сторонних разработчиков позволяет осуществить переход от одного технологического базиса к другому, например переход от Virtex к Virtex-II и далее к Virtex‑4, для повторной переработки проектов пользователя. Недостатком использования edf-формата является то, что не задействуются аппаратные ЦОС-блоки ПЛИС.
- Тарасов И. Возможности FPGA фирмы Xilinx для цифровой обработки сигналов // Компоненты и технологии. 2007. № 5.
- Зотов А. Проектирование встраиваемых микропроцессорных систем на базе расширяемых процессорных платформ семейства Zynq‑7000 AP SoC в САПР Xilinx ISE Design Suite // Компоненты и технологии. 2014. № 9 (цикл статей, начало в № 4).
- Литвинов А. Быстрая разработка устройств ЦОС в системе Xilinx System Generator // Современная электроника. 2013. № 1.
- Ефремов Н. В. Введение в систему автоматизированного проектирования Quartus II: учебное пособие. — М.: ГОУ ВПО МГУЛ, 2011.
- Synplify Reference Manual. APPENDIX B. Designing with Altera, April 2002 // synplicity.com
- Суворова Е. А., Шейнин Ю. Е. Проектирование цифровых систем на VHDL. — СПб: БХВ‑Петербург, 2003.
- Кузнецова С. Новые возможности OrCAD 10.0 // EDA_Expert. 2003. № 6 (79).