Декодеры и прочие компараторы на 155РЕ3, 556РТ4, 556РТ5 на языке ABEL
Может быть я напишу щаз страшный баян, который всем известен, но я вот для себя открыл недавно и решил поделиться. Микросхемы 155РЕ3, 556РТ4 и 556РТ5 ставятся как правило в декодерах адресов, в декодерах BCD, и тд. Эти микросхемы представляют из себя быстрое ПЗУ с адресными входами и выходами данных. Прадедушки PLD типа PAL и GAL. Так вот, для создания "прошивки" я раньше сидел, блин, с ручкой в руках и бинарным/хекс калькулятором и редактором, и чуть ли не в ручную считал адреса и биты/байты. Это утомительно. А недавно открыл для себя язык ABEL (пдф с RTFM).
Смотрите, как просто можно создать декодер адреса для 556РТ4 на нем:
Код:
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
Вначале идет служебка - module, title. Думаю понятно. Коментарии начинаются с двойных кавычек ("). Затем идет важная секция DEVICE. Это как раз целевая платформа, для которой будет создан файл прошивки. PROMB в данном случае - это имя файла-прошивки. RA8P4 - это и есть целевое устройство. В данном случае 8 - обозначает 8 адресных линий (входов) а 4 - 4 выхода данных. Что соответствует нашей отечественной 556РТ4. Еще бывают например, RA5P8 - пять входов, восемь выходов - это 155РЕ3; RA9P8 - это 556РТ5.
Дальше идет описание пинов. название_сигнала 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.
https://habrastorage.org/webt/vr/gs/...ouo-3ti2hy.png
Запускается просто - ABEL4.EXE. Дальше немножко ждем и читаем заставку, что это не шаровара и тд и тп и попадаем в редактор. Обычный для тех лет - открыть файл, сохранить и тд. Основное меню доступно по Alt+подсвеченная буква меню, например Alt+F - откроет меню файлов. Можно компилировать по шагам - сначала откомпилировать, потом оптимизировать, потом создать файл, а можно сделать это все сразу - нужно перейти в меню View и выбрать JEDEC/PROM Fuse File. Создастся файл с прошивкой, который имеет расширение по умолчанию .p83. Это вообщем-то обычный hex формат Intel, применяемый до сих пор много где (например прошивки для stm32, pic, atmega и тд). Но для наглядности его можно перевести в .bin с помощью утилиты hex2bin. Интересен так же пункт в меню View - PLDmap Report. Это отчет о проделанной работе. Там видно, во какие именно логические выражения преобразовались сравнения, видно сколько пинов входных и выходных занято, а также распиновка микросхемы:
Код:
==== 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
| |
| |
`---------------------------'
И прочая интересная информация. Еще есть полезная штуковина, как test_vectors. Это тестирование нашей логики. Например, добавив в конец исходного кода перед словом end такую конструкцию:
Код:
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 ];
Мы описываем сигналы, на которые подаем значение (Address) и сигналы, которые меняются в соответствие с входным значением. Здесь нужно самому написать, что мы хотим увидеть на выходных сигналах, а программа проверит, соответствуют ли наши ожидания получившемуся результату. Увидеть результаты симуляции можно в меню View - Simulation Results.
Код:
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