Проектирование учебного процессора
для реализации в базисе ПЛИС с использованием системы MATLAB/Simulink
Целью работы является демонстрация возможностей системы визуальноимитационного моделирования MATLAB/Simulink по проектированию микропроцессорных ядер для реализации в базисе ПЛИС фирмы Altera.
Андрей СТРОГОНОВ, д. т. н.
andreis@hotmail.ru Артем БУСЛОВ
При количестве логических вентилей в проекте свыше 5000 визуализировать выполняемые функции устройства крайне сложно. Гарантировать, что весь проект можно осознать, только взглянув на его схему, практически невозможно.
Разработчики, использующие в своих проектах методологию системного уровня проектирования (Electronic System Level (ESL) Design — проектирование на системном уровне или проектирование «сверху вниз»), получат очевидные преимущества. Во-первых, любой отдельно взятый разработчик может обеспечить решение задачи повышенной (и постоянно увеличивающейся) сложности, обращаясь к более высоким уровням абстракции и реализуя мелкие детали проекта в условиях автоматизированного процесса. Проще и быстрее разрабатывать модели сложнофункциональных устройств на более высоких уровнях абстракции, чем с использованием уровня регистровых передач (RTL-уровень, register transfer level). Самый простой способ понять концепцию RTL-описания — представить сложнофункциональное устройство в виде совокупности регистров, связанных между собой элементами комбинационной логики и управляемых с помощью общего синхросигнала. Симуляция в этом случае выполняется на несколько порядков быстрее, поскольку не симулируются несущественные для данного уровня абстракции детали.
Во-вторых, разработчики могут значительно сократить цикл производства и улучшить качество изделий, благодаря проверке функциональных возможностей, еще на этапе проектирования, когда внести изменения в системы легко и относительно дешево.
Первым этапом в потоке ESL-проектирования является определение требований к проекту. Требования устанавливаются конкретным заказчиком или определяются в результате соответствующих маркетинговых исследований.
Далее проводится системное проектирование и верификация алгоритмов, как правило, с помощью языка программирования C/C++/SystemC или с помощью специальных средств визуально-имитационного моделирования типа MATLAB/Simulink компании The MathWorks или SPW2000 (signal processing worksystem — рабочая среда обработки сигналов) компании Cadence. На этом этапе могут быть использованы и ESL-продукты компании Summit Design, такие как Visual Elite, FastC, System Architect и Virtual CPU. С помощью текстовых или графических средств создаются исполняемые функциональные спецификации, которые описывают поведение проекта в рамках заданных ограничений. Функциональная верификация технологически независима. Такое описание лишено деталей реализации.
Simulink — графическая среда визуальноимитационного моделирования аналоговых и дискретных систем; предоставляет пользователю графический интерфейс для конструирования моделей из стандартных функциональных блоков. Simulink работает с линейными, нелинейными, непрерывными, дискретными и многомерными системами. Система MATLAB/Simulink содержит встроенный генератор кода языка описания аппаратных средств HDL (Simulink HDL Coder) и ориентирована на поддержку симулятора VHDL ModelSim. Simulink HDL Coder — программный продукт для генерации VHDL-кода без привязки к конкретной архитектуре ПЛИС и платформе по Simulink-моделям. Справедливости ради следует заметить, что стиль кодирования может повлиять на производительность проектируемого устройства, особенно на ПЛИС. Логически эквивалентные, но разные RTL-операторы могут выдавать различные результаты.
Покажем возможности системы MATLAB/ Simulink на этапе ESL-проектирования по со-
зданию микропроцессорных ядер. Воспользуемся системой команд синхронного процессора, реализованного с помощью управляющего автомата, с циклом работы в два такта [1,2]. В работе [3] по коду языка VHDL синхронного процессора с управляющим автоматом, представленного в работе [2], с использованием САПР ПЛИС Quartus II была описана разработка проекта с применением мегафункции асинхронного ПЗУ и проекта без использования управляющего автомата с применением мегафункции асинхронного ОЗУ.
Для учебных целей разработаем два проекта с использованием асинхронного и синхронного ПЗУ на языке VHDL, с системой команд из работы [2]. Для ускорения процесса проектирования предлагается использовать возможности Simulink HDL Coder.
Запуск процессора в Simulink следует производить с помощью отладчика (Simulink Debugger). Перед отладкой необходимо зайти в меню Simulation/Configuration Parameters и выбрать диалог Solver («решатели», методы численного решения дифференциальных и дифференциально-алгебраических уравнений). В Solver options выбрать Type: Fixed-step; Solver: discrete (no continuous state); Fixed step size (fundamental sample time) — 1.0.
На рис. 1 показана отладка процессора. Процессор состоит из следующих блоков: ROM — ПЗУ процессора; COP — блок выделения полей команды; ALU — АЛУ процессора; RON — регистры общего назначения, регистры А и B; RSN — регистры специального назначения, регистр R для обеспечения команд обращения к подпрограммам (CALL) и возврата (RET) и регистр-счетчик Ip. На рис. 2 показан файл прошивки ПЗУ. Для построения ПЗУ используется функциональный блок Lookup Table, формирующий таблицу, в строках которой находятся порядковые номера (адреса) команд. Например, строке 1 соответствует команда 1036D (мнемонический код
MOV A,12). Адреса команд (входной порт addr), вещественные числа (Real World Values) G, 1, 2 ... 23, представляются в формате uint8 (Unsigned integer fixed-point data type, целые числа без знака в формате с фиксированной запятой, с 8-битной точностью), а команды (выходной порт) представляются в формате uint16, c 16-битной точностью. Все сигналы в процессоре представлены в формате uint8, кроме сигналов cmd и cmdData, они представлены в формате uint16.
В формате с фиксированной запятой без знака вещественное число V можно считать обозначением полинома [4]:
V=Sx
где Ъ{ — двоичное число, Ъ{ = 1,0; — раз-
мер слова, ответственного за точность представления десятичных чисел с запятой, максимально 128 бит; 5 — масштаб, 5 = 2Е, Е — число битов левее младшего значащего бита (Ь8Б) в слове, обозначающих месторасположение позиционной точки (разделительной точки или разделительной запятой). Для целых чисел 5 = 1. Например, число 0011.0101 при длине слова = 8:
Рис. 2. Файл прошивки ПЗУ в системе MATLAB/Simulink с использованием функционального блока Lookup Table
а>
Vy = Vu * 2А-8 Qy = Qu » 8 Ey = Eu
Shift
Arithmetic
Data Type Conversion
-►CP
OutCmd
Vy = Vu * 2A8 Vy = Vu * 2A-8
Qy = Qu « 8 -► Qy = Qu » 8 -► unite
Ey = Eu Ey = Eu
Shift
Arithmetid
Shift
Arithmetic2
Data Type Conversion!
->03
OutData
Рис. 3. Выделение полей команды с помощью операций арифметического сдвига
3.3125 = 2-4(0х27+0х26+1х25+
+ 1х24+0х23+1х22+0х21+1х2°).
Выделение полей команды осуществляется в блоке COP (рис. 3). Сигнал OutCmd (uint8) — 8 старших битов 16-разрядной команды CmdData (uint16), извлекаемой из ПЗУ. Сигнал OutData (uint8) — 8 младших бит, содержащих данные. Функциональные блоки Shift Arithmetic (арифметический сдвиг) и Data Type Conversion (преобразование типа данных) используются для формирования сигнала OutCmd. Они осуществляют логический сдвиг вправо сигнала CmdData, младшими битами вперед. Для формирования сигнала OutData осуществляется логический сдвиг влево сигнала CmdData, старшими битами вперед, а затем сдвиг вправо, на 8 бит вперед.
В блоках Display (command, Cmd, Data, RegA, RegB, RegR, counter IP) отображается содержимое внутренних узлов процессора. Например, по команде MOV A,12 в регистр А загружается число 12, по команде MOV B,23 в регистр B загружается число 23. А по команде 1540 должно произойти сложение содержимого регистров с сохранением результата в регистре А.
На рис. 4 показан блок АЛУ. Приведем пример M-файла функции АЛУ в системе MATLAB/Simulink:
function [outA, outB, outR, outIp] = a1u(inCmd,inData,inA,inB,inIp,inR) outA = inA; outB = inB; outR = inR; outIp = inIp+1; switch inCmd case 0 %NOP case 1 %JMP outIp = inData; case 2 %JMPZ if inA == 0 outIp = inData; end
case 3 % CALL outR = inIp+1; outIp = inData; case 4 %MOV A,xx outA = inData; case 5 %MOV B,xx outB = inData; case 6
switch inData case 0 %RET outIp = inR; case 1 %MOV A,B outA = inB; case 2 %MOV B,A outB = inA; case 3 %XCHG A,B X = inB; outB = inA; outA = X; case 4 %ADD A,B outA = inA+inB; case 5 %SUB A,B outA = inA-inB; case 6 %AND A,B outA = bitand(inA,inB); case 7 %OR A,B outA = bitor(inA,inB); case 8 %XOR A,B outA = bitxor(inA,inB); case 9 %DEC A outA = inA-1;
end
end
Текст функции начинается с заголовка function, имеющего следующий вид:
function [y1, y2, ...]=fname(x1,x2, ...),
где fname — имя фунции; x1, x2 и т. д. — входные параметры; y1, y2 и т. д. — выходные параметры. В условном операторе switch выбирается одна из возможных альтернатив. Запись оператора выбора производится с помощью ключевых слов switch, case, otherwise. При выполнении оператора switch значение inCmd поочередно сравнивается с 1, 2, 3, . При обнаружении первого совпадения выполняются операторы соответствующей ветви, после чего производится выход из оператора выбора.
На рис. 5 показано построение регистров общего назначения с использованием функциональных блоков Memory. Аналогично формируются и блоки регистров специального назначения.
Далее с помощью Simulink HDL Coder сгенерируем код языка VHDL функциональных блоков проектируемого процессора. При этом необходимо помнить, что САПР ПЛИС Quartus II относится к компиляторам-синтезаторам и имеет привязку к конкретной архитектуре, а сгенерированный код языка VHDL с помощью Simulink HDL Coder в первую очередь предназначен для ModelSim SE (Mentor Graphics HDL simulator). Последняя версия САПР ПЛИС Quartus II (версия 8.1) тодер-жит адаптированный симулятор ModelSim-Altera.
Пример сгенерированного описания прошивки асинхронного ПЗУ на языке VHDL:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY ROM IS
PORT(
addr: IN std_logic_vector(7 DOWNTO 0);
cmd: OUT std_logic_vector(15 DOWNTO 0));
END ROM;
ARCHITECTURE rtl OF ROM IS
SIGNAL Lookup_Table_out1: std_logic_vector(15 DOWNTO 0);
BEGIN
PROCESS(addr)
BEGIN
CASE addr IS
WHEN «00000000» => Lookup_Table_out1 <= «0000010000001100»;
WHEN «00000001» => Lookup_Table_out1 <= «0000010100010111»;
WHEN «00000010» => Lookup_Table_out1 <= «0000011000000100»;
WHEN «00000011» => Lookup_Table_out1 <= «0000011000001001»;
WHEN «00000100» => Lookup_Table_out1 <= «0000010101001110»;
WHEN «00000101» => Lookup_Table_out1 <= «0000011000000011»;
WHEN «00000110» => Lookup_Table_out1 <= «0000011000000101»;
WHEN «00000111» => Lookup_Table_out1 <= «0000011000001001»;
inCmd outA
inData
inA outB
alu
inB outR
inlp
inR outlp
ALU
+CD
outA
-►СИ)
outB
-KJD
outR
-►CD
outIP
Рис. 4. Блок АЛУ
WHEN «00001000 WHEN «00001001 WHEN «00001010 WHEN «00001011 WHEN «00001100 WHEN «00001101 WHEN «00001110 WHEN «00001111 WHEN «00010000 WHEN «00010001 WHEN «00010010 WHEN «00010011 WHEN «00010100 WHEN «00010101 WHEN «00010110 WHEN OTHERS = END CASE;
END PROCESS; cmd <=Lookup_Table_< END rtl;
=> Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < => Lookup_Tab1e_out1 < > Lookup_Table_out1 <=
out1;
=«0000011000000110» «GGGGGG1GGGGG1G11»; =«0000000100000111» «GGGGG1GGGGGG11G1»; «GGGGG1G1G111G1G1»; =«0000011000000111» «GGGGG11GGGGGGG11»; «GGGGG11GGGGG1GGG»; «GGGGGGG1GGG1G1G1»; =«0000010001101111» «GGGGG1G111GG1GGG»; «GGGGG11GGGGGG11G»; «GGGGG11GGGGGGGGG»; «GGGGGG11GGG1GGG1»; «GGGGGGGGGGGGGGGG»; «GGGGGGGGGGGGGGGG»;
Выделение полей команды на языке УИБЬ будет выглядеть следующим образом:
library ieee;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
ENTITY COP IS PORT(
cmdData : IN std_logic_vector(15 DOWNTO 0); OutData : OUT std_logic_vector(7 DOWNTO 0); OutCmd : OUT std_logic_vector(7 DOWNTO 0)); END COP;
ARCHITECTURE rtl OF COP IS BEGIN
OutCmd<=cmdData(15 downto 8); OutData<=cmdData(7 downto 0);
END rtl;
Пример описания асинхронного АЛУ на языке VHDL:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
ENTITY ALU_entity IS PORT (
inCmd : IN std_logic_vector(7 DOWNTO 0); inData : IN std_logic_vector(7 DOWNTO 0); inA : IN std_logic_vector(7 DOWNTO 0); inB : IN std_logic_vector(7 DOWNTO 0); inIp : IN std_logic_vector(7 DOWNTO 0); inR : IN std_logic_vector(7 DOWNTO 0); outA : OUT std_logic_vector(7 DOWNTO 0); outB : OUT std_logic_vector(7 DOWNTO 0); outR : OUT std_logic_vector(7 DOWNTO 0); outIp : OUT std_logic_vector(7 DOWNTO 0)); END ALU_entity;
ARCHITECTURE fsm_SFHDL OF ALU_entity IS BEGIN
PROCESS (inCmd, inData, inA, inB, inIp, inR) BEGIN outA <= inA; outB <= inB; outR <= inR; outIp <= inIp+1;
CASE inCmd IS WHEN «00000000» =>
--NOP NULL;
WHEN «00000001» =>
--JMP
outIp <= inData;
WHEN «00000010» =>
IF inA = 0 THEN --JMPZ
outIp <= inData;
END IF;
WHEN «00000011» =>
-- CALL outR <= inIp+1; outIp <= inData;
WHEN «00000100» =>
--MOV A,xx outA <= inData;
WHEN «00000101» =>
--MOV B,xx outB <= inData;
WHEN «00000110» =>
CASE inData IS WHEN «00000000» =>
--RET
outIp <= inR;
WHEN «00000001» =>
--MOV A,B outA <= inB;
WHEN «00000010» =>
--MOV B,A outB <= inA;
WHEN «00000011» =>
--XCHG A,B outB <= inA; outA <= inB;
WHEN «00000100» =>
--ADD A,B outA <= inA + inB;
WHEN «00000101» =>
--SUB A,B
outA <= inA — inB;
WHEN «00000110» =>
--AND A,B
outA <= inA AND inB; WHEN «00000111» =>
--OR A,B
outA <= inA OR inB;
WHEN «00001000» =>
--XOR A,B
outA <= inA XOR inB; WHEN «00001001» =>
--DEC A
outA <= inA— 1;
WHEN OTHERS =>
NULL;
END CASE;
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
END fsm_SFHDL;
Регистры общего назначения (РОН):
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
ENTITY RON IS
PORT( clk : IN std_logic;
reset: IN std_logic;
enb : IN std_logic;
inA : IN std_logic_vector(7 DOWNTO 0);
inB : IN std_logic_vector(7 DOWNTO 0);
outA : OUT std_logic_vector(7 DOWNTO 0);
outB : OUT std_logic_vector(7 DOWNTO 0));
END RON;
ARCHITECTURE rtl OF RON IS
BEGIN
PROCESS (clk, reset)
BEGIN IF reset = '1' THEN outA <= (OTHERS => '0');
ELSIF clk'event AND clk = '1' THEN IF enb = '1' THEN outA <= inA;
END IF;
END IF;
END PROCESS;
PROCESS (clk, reset)
BEGIN IF reset = '1' THEN outB <= (OTHERS => '0');
ELSIF clk'event AND clk = '1' THEN IF enb = '1' THEN outB <= inB;
END IF;
END IF;
END PROCESS;
END rtl;
С целью сокращения избыточности кода все блоки процессора подверглись ручному редактированию. При генерации кода языка VHDL функциональных блоков процессора Simulink HDL Coder использует только два пакета — std_logic_1164 и numeric_std, так как заранее предполагается, что процессор работает только с целыми положительными двоичными числами (тип unsigned). Добавим в каждый блок следующие пакеты: std_logic_arith и std_logic_unsigned (обязательны в блоке АЛУ). Компилятор-синтезатор наиболее эффективно отображает в ресурсы ПЛИС функции (например, арифметические), которые используются из пакетов std_logic_1164, numer-ic_std, std_logic_arith и std_logic_unsigned.
На рис. 6, 7 показана тестовая схема процессора в графическом редакторе САПР ПЛИС Quartus II и временная диаграмма работы. Анализируя полученные результаты, приходим к выводу, что ПЗУ и АЛУ являются асинхронными блоками. Регистры общего и специального назначения представляют собой 8-разрядные регистры, тактируемые фронтом синхросигнала, с асинхронным сбросом reset и синхронным сигналом ena. Недостатком сгенерированного кода языка VHDL являются нетактируемое АЛУ и ПЗУ.
Сгенерируем файл прошивки ПЗУ, используя M-файл и fi-объекты системы MATLAB. Fi-объекты позволяют представлять числа в формате с фиксированной запятой. Например, по команде а = fi(1536) целое положительное десятичное число 1536 будет представлено в формате M.N, где M — общее число двоичных разрядов, N — число разрядов дробной части. Наиболее распространенный формат — 16.15. Пятнадцать разрядов после запя-
той обеспечивают дискретность представления, равную 2-15«3х10-5. В нашем случае используем следующий формат: a = fi(v, s, w, f), где v — объект со значением, s — знак (0 (false) — для чисел без знака и 1 (true) — для чисел со знаком), w — размер слова в битах (целая часть числа), f — дробная часть числа в битах. Например, по команде а = fi(1536, 0, 16, 0) целое положительное десятичное число 1536 будет представлено в формате 16.0. По команде disp(bin(a)) можно посмотреть десятичное число в двоичной форме: 0000011000000000. Пример M-файл прошивки ПЗУ в системе MATLAB/Simulink:
function rom_out = Memory(addr) persistent data;
data = fi(zeros(1, 256), 0, 16, 0); data(1) = fi(1036, 0, 16, 0); data(2) = fi(1303, 0, 16, 0); data(3) = fi(1540, 0, 16, 0); data(4) = fi(1545, 0, 16, 0); data(5) = fi(1358, 0, 16, 0); data(6) = fi(1539, 0, 16, 0); data(7) = fi(1541, 0, 16, 0); data(8) = fi(1545, 0, 16, 0); data(9) = fi(1542, 0, 16, 0); data(10) = fi(523, 0, 16, 0); data(11) = fi(263, 0, 16, 0); data(12) = fi(1037, 0, 16, 0); data(13) = fi(1397, 0, 16, 0); data(14) = fi(1543, 0, 16, 0); data(15) = fi(1539, 0, 16, 0); data(16) = fi(1544, 0, 16, 0); data(17) = fi(277, 0, 16, 0); data(18) = fi(1135, 0, 16, 0); data(19) = fi(148G, 0, 16, 0); data(20) = fi(1542, 0, 16, 0); data(21) = fi(1536, 0, 16, 0); data(22) = fi(785, 0, 16, 0); data(23) = fi(0, 0, 16, 0); rom_out = data(addr+1);
Отредактированный вариант сгенерированного файла программой Simulink HDL Coder в САПР Quartus II будет выглядеть так:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY rom_syn IS PORT (
clk : IN std_logic; clk_enable : IN std_logic; reset : IN std_logic;
addr : IN std_logic_vector(7 DOWNTO 0); rom_out : OUT std_logic_vector(15 DOWNTO 0));
END rom_syn;
ARCHITECTURE a OF rom_syn IS
TYPE T_UFIX_16_256 IS ARRAY (255 DOWNTO 0) of unsigned (15 DOWNTO 0);
SIGNAL data : T_UFIX_16_256;
SIGNAL data_next : T_UFIX_16_256;
BEGIN
PROCESS (reset, clk)
-- local variables VARIABLE b : INTEGER;
BEGIN IF reset = '1' THEN NULL;
ELSIF clk'EVENT AND clk= '1' THEN IF clk_enable= '1' THEN
FOR b IN 0 TO 255 LOOP data(b) <= data_next(b);
END LOOP;
END IF;
END IF;
END PROCESS;
PROCESS (addr)
-- local variables
VARIABLE data_temp : T_UFIX_16_256;
BEGIN FOR b IN 0 TO 255 LOOP data_temp(b) := to_unsigned(0, 16);
END LOOP;
data_temp(0) := to_unsigned(1036, 16); data_temp(1) := to_unsigned(1303, 16); data_temp(2) := to_unsigned(1540, 16); data_temp(3) := to_unsigned(1545, 16); data_temp(4) := to_unsigned(1358, 16); data_temp(5) := to_unsigned(1539, 16); data_temp(6) := to_unsigned(1541, 16); data_temp(7) := to_unsigned(1545, 16); data_temp(8) := to_unsigned(1542, 16); data_temp(9) := to_unsigned(523, 16); data_temp(10) := to_unsigned(263, 16); data_temp(11) := to_unsigned(1037, 16); data_temp(12) := to_unsigned(1397, 16);
data_temp(13) = to_unsigned(1543, 16);
data_temp(14) = to_unsigned(1539, 16);
data_temp(15) = to_unsigned(1544, 16);
data_temp(16) = to_unsigned(277, 16);
data_temp(17) = to_unsigned(1135, 16);
data_temp(18) = to_unsigned(1480, 16);
data_temp(19) = to_unsigned(1542, 16);
data_temp(20) = to_unsigned(1536, 16);
data_temp(21) = to_unsigned(785, 16);
data_temp(22) = to_unsigned(0, 16);
rom_out <= std_logic_vector(data_temp(to_integer(unsigned(addr))));
END PROCESS;
END a;
........reset
* yy W7-0~
ok.(4M
•ddr(? .0)
Ш
Рис. 8. Фрагмент схемы: а) ПЗУ с использованием М-функции в системе MATLAB/Simulink; б) символ синхронного ПЗУ в Quaгtus II
Рис. 9. Временная диаграмма работы процессора с синхронным ПЗУ
Рис. 10. Тестовая схема процессора в графическом редакторе САПР ПЛИС Quaгtus II (версия 8) с циклом работы в два такта с синхронным ПЗУ
Анализируя этот код, можно сделать вывод, что сгенерировано синхронное ПЗУ с асинхронным сбросом, синхронным сигналом разрешения тактирования clk_enable. Для организации массива памяти используется последовательный оператор for ... loop, выполняющий повторяющиеся операторы.
Оператор for ... loop имеет целую схему итерации, при которой количество повторов определяется целым диапазоном. Цикл повторяется один раз для каждого значения диапазона. После того как будет достигнуто последнее значение диапазона итерации, цикл пропускается, и выполнение программы продолжается, начиная с оператора, стоящего вслед за циклом.
Следует упомянуть про функции преобразования типов to_integer и to_unsigned из пакета Numeric_std, которые используются при проектировании синхронного ПЗУ. Функция to_integer преобразует тип unsigned в подтип natural (встроенный подтип natural используют для объектов, которые не должны принимать отрицательные значения), а функция to_unsigned преобразует подтип natural в тип unsigned, при этом необходимо указывать размер желаемого слова.
На рис. 8 показаны изменения, которые необходимо внести в проект для ПЗУ с использованием М-функции в системе MATLAB/Simulink (рис. 8а) и для синхронного ПЗУ в САПР ПЛИС Quartus II (рис. 8б). На рис. 9 представлена временная диаграмма работы процессора с синхронным ПЗУ.
Проект микропроцессора с синхронным ПЗУ, код языка VHDL которого был получен с использованием Simulink HDL Coder, продемонстрировал работоспособность как на старых, так и на новых сериях ПЛИС фирмы Altera, что не удавалось осуществить с ис-
пользованием встроенных мегафункций ОЗУ и ПЗУ [3]. На рис. 10 показана тестовая схема процессора в графическом редакторе САПР ПЛИС Quartus II (версия 8) с циклом работы в два такта с синхронным ПЗУ. В работе [2] приведен код языка VHDL процессора с циклом работы в два такта. Сравнивая рис. 9 и рис. 11 видим, что два процессора логически работают одинаково. Однако на временной диаграмме (рис. 9) имеется большое количество гличей. Это объясняется разными архитектурными решениями при реализации процессоров.
Система MATLAB/Simulink c Simulink HDL Coder может быть эффективно использована для ускорения процесса разработки моделей микропроцессорных ядер. Проект микропроцессора с асинхронным ПЗУ на языке VHDL может быть успешно размещен в ПЛИС APEX20KE EP20K30ETC144-1, при этом общее
число задействованных ресурсов составляет 22%, с рабочей частотой до 60 МГц.
Недостатком процессора, реализованного в системе MATLAB/Simulink и адаптированного в САПР Quartus II, является отсутствие управляющего автомата. ■
Литература
1. Тарасов И. Проектирование конфигурируемых процессоров на базе ПЛИС. Часть I // Компоненты и технологии. 2006. № 2.
2. Тарасов И. Проектирование конфигурируемых процессоров на базе ПЛИС. Часть II // Компоненты и технологии. 2006. № 3.
3. Строгонов А. Проектирование учебного процессора для реализации в базисе ПЛИС // Компоненты и технологии. 2009. № 3.
4. www.mathworks.com. Simulink fixed point for use with Simulink. User Guide. Version 5.