Міністерство освіти і науки України
Національний університет „Львівська політехніка”
Кафедра ЕОМ
Звіт
з лабораторної роботи №2
на тему:
„ VHDL- проект 8-бітного мікроконтролера Xilinx Picoblaze”
Підготував: ст. гр. СКС-1
Львів 2007
Мета: Ознайомитись з архітектурою мікроконтролера Xilinx Picoblaze, освоїти основні принципи його конфігурування.
Теоретичні відомості:
Сучасні програмовані логічні матриці та інтегральні схеми створюються переважно з вбудованими мікропроцесорними ядрами. Зокрема, фірми Xilinx та Altera випускають ПЛМ та ПЛІС з 32-розрядними процесорними ядрами Microblaze та NIOS відповідно. Однак, право на використання цих ядер обійдеться користувачу приблизно в 1000 доларів США.
Тому, користуючись відомими правилами маркетингової політики у сфері високих технологій, фірма Xilinx випустила безкоштовне 8-розрядне мікропроцесорне ядро Picoblaze. Даний процесор та різні його модифікації є 8-розрядним програмованим процесором, що підтримує 49 різних 16- та 18-бітних інструкцій, від 8 до 32 8-бітних регістрів загального призначення, 256 портів з прямою та непрямою адресацією, функцією скиду та маскованим перериванням.
Огляд структури мікроконтролера
Структура мікроконтролера Picoblaze має наступний вигляд:
Рисунок 1 Структура мікроконтролера Picoblaze
Інструкції мікропроцесора містяться у блоку пам’яті розміром 256х16, яка ініціалізується вбудованим програмним забезпеченням. Коли виконуються асемблерні команди, результат їх виконання надходить до VHDL-пакувальника, який містить інструкції ініціалізації Xilinx, які приховують усі порти, за виключенням портів ADDRESS, CLK, INSTRUCTION OUT.
Ввід\вивід у Picoblaze здійснюється через вхідні та вихідні порти. Для вибору різних портів використовується мультиплексор та демультиплексор. Сигнали Wr та Rd використовуються для стробування процесів запису та читання (використання сигналу Rd є необов’язковим). Вхід переривання є чутливим до рівня, але перед використанням він має бути активований внутрішнім ПЗ.
Демонстраційна програма
Демонстраційна програма для Picoblaze створює простий двійковий лічильник. Його значення буде збільшуватися на 1 при кожному натисканні перемикача Test Switch, використовуючи підпрограму обробки переривання, тоді як основна програма буде виконувати вивід результату на індикатор кожен раз, коли значення лічильника змінюється.
З метою покращення організації проекту він розділений на 3 директорії.
VHDL – містить файл Pocoblaze - kcpsm.vhd та vhdl-пакувальник, що під’єднує його до пам’яті інструкцій.
SW - директорія, в якій асемблерний файл (picocode.psm) з допомогою пакувальника перетворюється у vhdl-файл - (picocode.vhd).
XILINX – директорія, в якій містяться результати синтезу на Xilinx WebPack та файл програмування ПЛІС.
Порядок виконання роботи:
1. Підготовка проекту
Скопіюйте файл kcpsm.vhd (ядро Picoblaze) у директорію VHDL, та kcpsm.exe (файл асемблера), ROM_foem.coe та ROM_form.vhd - у директорію SW.
При розгляді коду, який міститься у файлі picocode.psm, бачимо, що код починається з оголошення двох номерів портів та іменування двох регістрів у count та old_count . Також задані початкові значення для регістрів та дозволені переривання.
В головному циклі виконується перевірка чи відбулося інкрементування лічильника шляхом постійного віднімання значень count та old_count та повернення на початок, якщо результат віднімання вийшов нульовий. Якщо результат порівняння ненульовий – виконується вивід нового значення на індикатор, нове значення count лічильника зберігається у змінній old_count, після чого знову відбувається повернення на початок. Адреса початку підпрограми обробки переривання встановлюється командою Address B0 (однак, це є необов’язковим, оскільки якщо адресу не буде встановлено, підпрограма обробки буде розміщена одразу після коду основної програми). Перше, що робить підпрограма обробки – це інкрементування лічильника. Це супроводжується програмною затримкою з метою уникнення генерування багатократних переривань через явище «мигтіння контактів» на перемикачі Test Switch до моменту повернення з підпрограми. Дане повернення знову виконує дозвіл на переривання.
2. Генерування vhdl-коду
Відкрийте сеанс MS-DOS у SW-директорії проекту. Наберіть у командній стрічці kcpsm picocode та натисніть ENTER. В результаті крім кількох додаткових файлів має з’явитися файл picocode.vhd, згенерований з використанням ROM_form.coe та ROM_form.vhd. Дана операція при успішному виконанні має завершитися повідомленнями «KCPSM Successful» та «KCPSM Complete».
У директорії VHDL ми можемо бачити файл верхнього рівня picotest.vhd, який виконує з’єднання Picoblaze (файл kcpsm.vhd) з файлом програми picocode.vhd. Він також генерує сигнал скиду, переривання по спадаючому фронту на вході intrpt_n та керує виводами будь-якого порта за виключенням порта, який виводить дані на індикатор.
Нижче наведено асемблерний код файлу: PICOCODE.PSM
;Interrupt example
CONSTANT test_led_port, 02
CONSTANT leds_port, 04
NAMEREG sA, count
NAMEREG SB, old_count
;
;
start: ENABLE INTERRUPT
LOAD count, 01
LOAD old_count, count
loop: SUB old_count, count
JUMP Z, loop
OUTPUT count, leds_port
LOAD old_count, count
JUMP loop
;
ADDRESS B0
int_routine: ADD count, 01 ;increment count
LOAD S5, 10
delay3: LOAD S4, 7F
delay2: LOAD S3, FF
delay1: SUB S3, 01
JUMP NZ, delay1
SUB S4, 01
JUMP NZ, delay2
SUB S5, 01
JUMP NZ, delay3
;
RETURNI ENABLE
;
ADDRESS FF ;set interrupt vector
JUMP int_routine
Код файлу: PICOCODE.VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--
library unisim;
use unisim.vcomponents.all;
--
--
entity picocode is
Port ( address : in std_logic_vector(7 downto 0);
instruction : out std_logic_vector(15 downto 0);
clk : in std_logic);
end picocode;
--
architecture low_level_definition of picocode is
--
-- Attributes to define ROM contents during implementation synthesis.
-- The information is repeated in the generic map for functional simulation
--
attribute INIT_00 : string;
attribute INIT_01 : string;
attribute INIT_02 : string;
attribute INIT_03 : string;
attribute INIT_04 : string;
attribute INIT_05 : string;
attribute INIT_06 : string;
attribute INIT_07 : string;
attribute INIT_08 : string;
attribute INIT_09 : string;
attribute INIT_0A : string;
attribute INIT_0B : string;
attribute INIT_0C : string;
attribute INIT_0D : string;
attribute INIT_0E : string;
attribute INIT_0F : string;
--
-- Attributes to define ROM contents during implementation synthesis.
--
attribute INIT_00 of ram_256_x_16 : label is "000000000000000000000000000000008103CBA0EA049103CBA6CBA00A018030";
attribute INIT_01 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_02 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_03 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_04 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_05 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_06 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_07 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_08 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_09 of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0A of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0B of ram_256_x_16 : label is "0000000000000000000080F095B2650195B3640195B4630103FF047F05104A01";
attribute INIT_0C of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0D of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0E of ram_256_x_16 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0F of ram_256_x_16 : label is "81B0000000000000000000000000000000000000000000000000000000000000";
--
begin
--
--Instantiate the Xilinx primitive for a block RAM
ram_256_x_16: RAMB4_S16
--translate_off
--INIT values repeated to define contents for functional simulation
generic map (INIT_00 => X"000000000000000000000000000000008103CBA0EA049103CBA6CBA00A018030",
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B => X"0000000000000000000080F095B2650195B3640195B4630103FF047F05104A01",
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F => X"81B0000000000000000000000000000000000000000000000000000000000000",
--translate_on
port map( DI => "0000000000000000",
EN => '1',
WE => '0',
RST => '0',
CLK => clk,
ADDR => address,
DO => instruction(15 downto 0));
--
end low_level_definition;
Код файлу: ROM_form.VHDL
Даний файл не належить до вхідного файлу синтезу або симуляції. Асемблерний код прочитає чей шаблон і вставить дані, які вимагаються для завершення визначення ПЗП і записує його в новий .vhdl файл пов’язаний з ім’ям оригіналу асемблерного файла .psm
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--
library unisim;
use unisim.vcomponents.all;
--
--
entity {name} is
Port ( address : in std_logic_vector(7 downto 0);
instruction : out std_logic_vector(15 downto 0);
clk : in std_logic);
end {name};
--
architecture low_level_definition of {name} is
--
-- Attributes to define ROM contents during implementation synthesis.
-- The information is repeated in the generic map for functional simulation
--
attribute INIT_00 : string;
attribute INIT_01 : string;
attribute INIT_02 : string;
attribute INIT_03 : string;
attribute INIT_04 : string;
attribute INIT_05 : string;
attribute INIT_06 : string;
attribute INIT_07 : string;
attribute INIT_08 : string;
attribute INIT_09 : string;
attribute INIT_0A : string;
attribute INIT_0B : string;
attribute INIT_0C : string;
attribute INIT_0D : string;
attribute INIT_0E : string;
attribute INIT_0F : string;
--
-- Attributes to define ROM contents during implementation synthesis.
--
attribute INIT_00 of ram_256_x_16 : label is "{INIT_00}";
attribute INIT_01 of ram_256_x_16 : label is "{INIT_01}";
attribute INIT_02 of ram_256_x_16 : label is "{INIT_02}";
attribute INIT_03 of ram_256_x_16 : label is "{INIT_03}";
attribute INIT_04 of ram_256_x_16 : label is "{INIT_04}";
attribute INIT_05 of ram_256_x_16 : label is "{INIT_05}";
attribute INIT_06 of ram_256_x_16 : label is "{INIT_06}";
attribute INIT_07 of ram_256_x_16 : label is "{INIT_07}";
attribute INIT_08 of ram_256_x_16 : label is "{INIT_08}";
attribute INIT_09 of ram_256_x_16 : label is "{INIT_09}";
attribute INIT_0A of ram_256_x_16 : label is "{INIT_0A}";
attribute INIT_0B of ram_256_x_16 : label is "{INIT_0B}";
attribute INIT_0C of ram_256_x_16 : label is "{INIT_0C}";
attribute INIT_0D of ram_256_x_16 : label is "{INIT_0D}";
attribute INIT_0E of ram_256_x_16 : label is "{INIT_0E}";
attribute INIT_0F of ram_256_x_16 : label is "{INIT_0F}";
--
begin
--
--Instantiate the Xilinx primitive for a block RAM
ram_256_x_16: RAMB4_S16
--translate_off
--INIT values repeated to define contents for functional simulation
generic map (INIT_00 => X"{INIT_00}",
INIT_01 => X"{INIT_01}",
INIT_02 => X"{INIT_02}",
INIT_03 => X"{INIT_03}",
INIT_04 => X"{INIT_04}",
INIT_05 => X"{INIT_05}",
INIT_06 => X"{INIT_06}",
INIT_07 => X"{INIT_07}",
INIT_08 => X"{INIT_08}",
INIT_09 => X"{INIT_09}",
INIT_0A => X"{INIT_0A}",
INIT_0B => X"{INIT_0B}",
INIT_0C => X"{INIT_0C}",
INIT_0D => X"{INIT_0D}",
INIT_0E => X"{INIT_0E}",
INIT_0F => X"{INIT_0F}",
--translate_on
port map( DI => "0000000000000000",
EN => '1',
WE => '0',
RST => '0',
CLK => clk,
ADDR => address,
DO => instruction(15 downto 0));
--
end low_level_definition
Висновок: на дані лабораторній роботі я ознайомився з архітектурою мікроконтролера Xilinx Picoblaze, та освоїв основні принципи його конфігурування.