Может быть я напишу щаз страшный баян, который всем известен, но я вот для себя открыл недавно и решил поделиться. Микросхемы 155РЕ3, 556РТ4 и 556РТ5 ставятся как правило в декодерах адресов, в декодерах BCD, и тд. Эти микросхемы представляют из себя быстрое ПЗУ с адресными входами и выходами данных. Прадедушки PLD типа PAL и GAL. Так вот, для создания "прошивки" я раньше сидел, блин, с ручкой в руках и бинарным/хекс калькулятором и редактором, и чуть ли не в ручную считал адреса и биты/байты. Это утомительно. А недавно открыл для себя язык ABEL (пдф с RTFM).
Смотрите, как просто можно создать декодер адреса для 556РТ4 на нем:
Вначале идет служебка - module, title. Думаю понятно. Коментарии начинаются с двойных кавычек ("). Затем идет важная секция DEVICE. Это как раз целевая платформа, для которой будет создан файл прошивки. PROMB в данном случае - это имя файла-прошивки. RA8P4 - это и есть целевое устройство. В данном случае 8 - обозначает 8 адресных линий (входов) а 4 - 4 выхода данных. Что соответствует нашей отечественной 556РТ4. Еще бывают например, RA5P8 - пять входов, восемь выходов - это 155РЕ3; RA9P8 - это 556РТ5.Код:module decode title 'memory decode' PROMB device 'RA8P4'; " 8 address lines and 4 data lines "INPUTS PIN # PROM ADDRESS/DATA BIT A15 PIN 15; A14 PIN 7; A13 PIN 6; A12 PIN 5; A11 PIN 4; A10 PIN 3; "OUTPUTS PIN # ROM1 PIN 12; IO PIN 11; ROM2 PIN 10; DRAM PIN 9; "defines H,L,X = 1,0,.X.; Address = [A15,A14,A13,A12, A11,A10,X,X, X,X,X,X, X,X,X,X]; equations !DRAM = (Address <= ^hDFFF); !IO = (Address >= ^hE000) & (Address <= ^hE7FF); !ROM2 = (Address >= ^hF000) & (Address <= ^hF7FF); !ROM1 = (Address >= ^hF800); end
Дальше идет описание пинов. название_сигнала PIN номер_пина.
Затем идет секция присвоений:
H,L,X = 1,0,.X; это можно можно записать как
H = 1;
L = 0;
X = .X.;
Это что-то вроде "соответствий" (в ассемблере EQU) или дефайнов в Си. Так, встретив дальше в коде символ H он будет заменен на 1; L будет заменен на 0. Есть специальный символ языка .X. - обозначает любое значение. Чтоб не писать дальше эти точки мы его подменяем просто на X.
Дальше мы создаем виртуальную 16-битную переменную Address, состоящую из сигналов A15..A10 в старших битах и дальше без разницы в младших.
А потом идут выражения:
!DRAM = (Address <= ^hDFFF); - если Address меньше или равен шестнадцатеричному 0xDFFF, тогда присвоить DRAM единичку. Символ ! перед DRAM - значит что сигнал инверсный, значит единичку инвертируем и получается нолик. Итого, если адрес меньше или равен 0xDFFF, тогда девятый пин РТ4 ложится в ноль. Ну и дальше по аналогии:
!IO = (Address >= ^hE000) & (Address <= ^hE7FF); - если адрес больше или равен 0xE000 и при этом меньше или равен 0xE7FF, то пин IO (11 пин) в нуле и тд.
Все это проделывается в DOS-версии ABEL v4, скачать можно тут: http://old-dos.ru/index.php?page=fil...o=show&id=7056
Надо отметить, что существует современный язык ABEL в программе ispLEVER, но такие древние целевые платформы как PROM в нем уже конечно же выпилены. Поэтому DOS и DosBox.
Запускается просто - ABEL4.EXE. Дальше немножко ждем и читаем заставку, что это не шаровара и тд и тп и попадаем в редактор. Обычный для тех лет - открыть файл, сохранить и тд. Основное меню доступно по Alt+подсвеченная буква меню, например Alt+F - откроет меню файлов. Можно компилировать по шагам - сначала откомпилировать, потом оптимизировать, потом создать файл, а можно сделать это все сразу - нужно перейти в меню View и выбрать JEDEC/PROM Fuse File. Создастся файл с прошивкой, который имеет расширение по умолчанию .p83. Это вообщем-то обычный hex формат Intel, применяемый до сих пор много где (например прошивки для stm32, pic, atmega и тд). Но для наглядности его можно перевести в .bin с помощью утилиты hex2bin. Интересен так же пункт в меню View - PLDmap Report. Это отчет о проделанной работе. Там видно, во какие именно логические выражения преобразовались сравнения, видно сколько пинов входных и выходных занято, а также распиновка микросхемы:
И прочая интересная информация. Еще есть полезная штуковина, как test_vectors. Это тестирование нашей логики. Например, добавив в конец исходного кода перед словом end такую конструкцию:Код:==== RA8P4 Programmed Logic ==== DRAM = ( A15 & A14 & A13 ); IO = ( !A15 # !A14 # !A13 # A12 # A11 ); ROM2 = ( !A15 # !A14 # !A13 # !A12 # A11 ); ROM1 = ( !A15 # !A14 # !A13 # !A12 # !A11 ); ==== RA8P4 Chip Diagram ==== RA8P4 +---------\ /---------+ | \ / | | ----- | | 1 16 | Vcc | | | 2 15 | A15 | | A10 | 3 14 | | | A11 | 4 13 | | | A12 | 5 12 | ROM1 | | A13 | 6 11 | IO | | A14 | 7 10 | ROM2 | | GND | 8 9 | DRAM | | | | `---------------------------'
Мы описываем сигналы, на которые подаем значение (Address) и сигналы, которые меняются в соответствие с входным значением. Здесь нужно самому написать, что мы хотим увидеть на выходных сигналах, а программа проверит, соответствуют ли наши ожидания получившемуся результату. Увидеть результаты симуляции можно в меню View - Simulation Results.Код:test_vectors (Address -> [ROM1,ROM2,IO,DRAM]) ^h0000 -> [ H, H, H, L ]; ^h4000 -> [ H, H, H, L ]; ^h8000 -> [ H, H, H, L ]; ^hC000 -> [ H, H, H, L ]; ^hE000 -> [ H, H, L, H ]; ^hE800 -> [ H, H, H, H ]; ^hF000 -> [ H, L, H, H ]; ^hF800 -> [ L, H, H, H ];
Все работает так, как задумали.Код:Simulate EZ-ABEL 4.30 Date: Fri Sep 28 12:51:49 19;8 Fuse file: 'decode.tt2' Vector file: 'decode.tmv' Part: 'PLA' memory decode R R D A A A A A O O R 1 1 1 1 1 M M I A 5 4 3 2 1 1 2 O M V0001 0 0 0 0 0 H H H L V0002 0 1 0 0 0 H H H L V0003 1 0 0 0 0 H H H L V0004 1 1 0 0 0 H H H L V0005 1 1 1 0 0 H H L H V0006 1 1 1 0 1 H H H H V0007 1 1 1 1 0 H L H H V0008 1 1 1 1 1 L H H H 8 out of 8 vectors passed.
Вообще, там еще полно всяких прикольных штуковин. В меню Help как ни странно есть хелпа, которая тоже рекомендуется к прочтению. Но для быстрого старта наверное все, потому что я и сам только-только познакомился с инструментом.
В завершение еще парочка примеров. Вот, например, декодер BCD для семисегментного светодиодного индикатора с общим анодом на 155РЕ3 с использованием пина OE:
Захотели поменять индикатор с общим анодом на индикатор с общим катодом? Пфф, делов то, меняем строчкуКод:module bcd7 title 'seven segment display decoder' " a " --- BCD-to-seven-segment decoder similar to the 7449 " f| g |b " --- segment identification " e| d |c " --- BCD7 device 'RA5P8'; " 5 address lines and 8 data lines D3,D2,D1,D0,Ena pin 13,12,11,10,15; a,b,c,d,e,f,g pin 1,2,3,4,5,6,7 istype 'com'; bcd = [D3,D2,D1,D0]; led = [a,b,c,d,e,f,g]; ON,OFF = 0,1; " for common anode LEDs L,H,X,Z = 0,1,.X.,.Z.; equations led.oe = !Ena; @dcset truth_table (bcd -> [ a , b , c , d , e , f , g ]) 0 -> [ ON, ON, ON, ON, ON, ON, OFF]; 1 -> [OFF, ON, ON, OFF, OFF, OFF, OFF]; 2 -> [ ON, ON, OFF, ON, ON, OFF, ON]; 3 -> [ ON, ON, ON, ON, OFF, OFF, ON]; 4 -> [OFF, ON, ON, OFF, OFF, ON, ON]; 5 -> [ ON, OFF, ON, ON, OFF, ON, ON]; 6 -> [ ON, OFF, ON, ON, ON, ON, ON]; 7 -> [ ON, ON, ON, OFF, OFF, OFF, OFF]; 8 -> [ ON, ON, ON, ON, ON, ON, ON]; 9 -> [ ON, ON, ON, ON, OFF, ON, ON]; end
ON,OFF = 0,1; " for common anode LEDs
на строчку
ON,OFF = 1,0; " for common cathode LEDs
и всех делов.
Ну и до кучи, 4-битный компаратор на 556РТ5:
Код:module COMP_OR title '4 bit comparator ' " PROMB device 'RA8P4'; " 8 address lines and 8 data lines "INPUTS PIN # PROM ADDRESS/DATA BIT A0 PIN 15; " A0 A1 PIN 7; " A1 A2 PIN 6; " A2 A3 PIN 5; " A3 B0 PIN 4; " A4 B1 PIN 3; " A5 B2 PIN 2; " A6 B3 PIN 1; " A7 "OUTPUTS PIN # AGB PIN 12; " D8 A IS GREATER THAN B ALB PIN 11; " D7 A IS LESS THAN B EQUAL PIN 10; " D6 A IS EQUAL TO B ALL_HIGH PIN 9; " D5 ALL BITS ARE HIGH X = .X.; Declarations A_NIB = [A3,A2,A1,A0]; B_NIB = [B3,B2,B1,B0]; Equations ALL_HIGH = (A_NIB==15) & (B_NIB==15); truth_table ([A3,A2,A1,A0, B3,B2,B1,B0]->[AGB,ALB,EQUAL]) [ 0, 0, 0, 0, 0, 0, 0, 0]->[ 0 , 0 , 1];"A = B CONDITIONS [ 0, 0, 0, 1, 0, 0, 0, 1]->[ 0 , 0 , 1]; [ 0, 0, 1, 0, 0, 0, 1, 0]->[ 0 , 0 , 1]; [ 0, 0, 1, 1, 0, 0, 1, 1]->[ 0 , 0 , 1]; [ 0, 1, 0, 0, 0, 1, 0, 0]->[ 0 , 0 , 1]; [ 0, 1, 0, 1, 0, 1, 0, 1]->[ 0 , 0 , 1]; [ 0, 1, 1, 0, 0, 1, 1, 0]->[ 0 , 0 , 1]; [ 0, 1, 1, 1, 0, 1, 1, 1]->[ 0 , 0 , 1]; [ 1, 0, 0, 0, 1, 0, 0, 0]->[ 0 , 0 , 1]; [ 1, 0, 0, 1, 1, 0, 0, 1]->[ 0 , 0 , 1]; [ 1, 0, 1, 0, 1, 0, 1, 0]->[ 0 , 0 , 1]; [ 1, 0, 1, 1, 1, 0, 1, 1]->[ 0 , 0 , 1]; [ 1, 1, 0, 0, 1, 1, 0, 0]->[ 0 , 0 , 1]; [ 1, 1, 0, 1, 1, 1, 0, 1]->[ 0 , 0 , 1]; [ 1, 1, 1, 0, 1, 1, 1, 0]->[ 0 , 0 , 1]; [ 1, 1, 1, 1, 1, 1, 1, 1]->[ 0 , 0 , 1]; [ 0, 0, 0, 0, X, X, X, 1]->[ 0 , 1 , 0];"A < B CONDS. [ 0, 0, 0, X, X, X, 1, X]->[ 0 , 1 , 0]; [ 0, 0, X, X, X, 1, X, X]->[ 0 , 1 , 0]; [ 0, X, X, X, 1, X, X, X]->[ 0 , 1 , 0]; [ 1, 0, X, X, 1, 1, X, X]->[ 0 , 1 , 0]; [ 1, 0, 0, X, 1, 0, 1, X]->[ 0 , 1 , 0]; [ 1, 0, 0, 0, 1, 0, 0, 1]->[ 0 , 1 , 0]; [ 0, 1, 0, X, 0, 1, 1, X]->[ 0 , 1 , 0]; [ 0, 1, 0, 0, 0, 1, X, 1]->[ 0 , 1 , 0]; [ 0, 0, 1, 0, 0, 0, 1, 1]->[ 0 , 1 , 0]; [ 1, X, X, X, 0, X, X, X]->[ 1 , 0 , 0];"A > B CONDS. [ 0, 1, X, X, 0, 0, X, X]->[ 1 , 0 , 0]; [ 0, 0, 1, X, 0, 0, 0, X]->[ 1 , 0 , 0]; [ 0, 0, 0, 1, 0, 0, 0, 0]->[ 1 , 0 , 0]; [ 1, 1, X, X, 1, 0, X, X]->[ 1 , 0 , 0]; [ 1, 0, 1, X, 1, 0, 0, X]->[ 1 , 0 , 0]; [ 1, 0, 0, 1, 1, 0, 0, 0]->[ 1 , 0 , 0]; [ 0, 1, 1, X, 0, 1, 0, X]->[ 1 , 0 , 0]; [ 0, 1, 0, 1, 0, 1, 0, 0]->[ 1 , 0 , 0]; [ 0, 0, 1, 1, 0, 0, 1, 0]->[ 1 , 0 , 0]; end COMP_OR