|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
|
Page 1 of 1
|
[ 7 posts ] |
|
Микросхема троичного микроконтроллера Triador3000
Author |
Message |
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
В декабре 2017 я уже начал было рассуждать как же нам затолкать TRIADOR в микросхему DIP48: Чтобы не мешаться в основном топике про TRIADOR, создаю новую тему
|
10 May 2020 21:58 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
Предполагается, что память программ будет снаружи, а дополнительная память данных - внутри (теоретически до 729 трайтов, но на самом деле вряд ли будет больше 243 и скорее всего эта память будет обычной двоичной статической памятью - можно скажем в названии чипа указывать сколько трайтов памяти данных есть на борту - Triador3243, Triador3081 и т.д.).
Считаем ноги: 1 питание (1); 1 уровень для третьего состояния 2.5 В (2); 2 уровни 1.666 В и 3.333 В для компараторов (4); 1 вход резистора для токового зеркала (5); 1 вход сигнала сброса/прерывания (6); 1 тактирование синусоидой (7); 6 вывод адреса внешней памяти программ (13); 5 ввод командного слова из внешней памяти программ (18); 3 вывод тестовой триады для выдачи состояния регистров и т.д. (21); 6 ввод тестового адреса для выдачи тестовой триады (27); 6 выход виртуальной ячейки памяти OOO OOO для листания памяти программ и скажем для организации клавиатуры (33); 6 вход для чтения виртуальной ячейки памяти OOO OOO - для простоты может быть замкнуто на выходы (39); 1 выход запроса EX на внешнюю схему из диапазона CUSTOM CIRCUITS (40); 4 вход для новых значений C и R1 после выполнения внешней команды EX (44); 3 возможно выходы флагов A,B,C для связи с внешним миром (47); 1 земля (48).
Внешняя схема обработки EX получив сигнал, что есть запрос на исполнение внешней команды EX, останавливает тактирование чипа и, подавая на тестовый адрес некоторые значения, читает нужную информацию (содержимое регистров, защёлок PEX, памяти данных и т.д.), затем выполняет некие действия и пишет обратно новые значения для C,R1, возобновляя тактирование (чип при продолжении работы первым делом читает эти 4 трита и записывает C,R1). Сигнал EX можно совместить с индикацией состояния HLT (например P может означать, что есть запрос на обработку внешней команды EX, а N - что чип вошёл в состояние HLT). Вход сброса/прерывания просто может означать разные способы старта - P может означать полный сброс с обнулением регистров и защёлок и старт с адреса OOO OOO (причём в этом случае в адресном пространстве программ Nxx xxx отображается память данных для того, чтобы была возможность динамически подгружать и запускать подпрограммы), а N - вход в прерывание с адреса NNN NNN с сохранением состояния всех регистров и защёлок (в этом случае вся работа идёт с внешним ПЗУ программ - хотя прерывания можно отложить на будущее и пока ограничиться одним способом рестарта).
P.S. Возможная адресация триад тестовым адресом: Nxxxxx - младшие триады памяти данных из адресов NNNNNN...NPPPPP Pxxxxx - старшие триады памяти данных из адресов NNNNNN...NPPPPP ONxxxx - все триады защёлок PEX (читая их снаружи можно организовать экран 9x13) OOOxxx - регистры R1-R13 плюс ещё 14 тестовых триад (например значения R1-1 и R1+1) остальные тестовые адреса могут покрывать другие тестовые точки внутри чипа
P.P.S. Раз уж память программ в области Nxx xxx уже смотрит на ОЗУ, то может попробовать "захардкодить" внутрь области Oxx xxx простую программу, которая при старте будет читать из последовательной флешины прошивку? Управлять режимом бута можно скажем путём заземления некоторых входов пока вход сброса активен - один из режимов будет означать загрузку прошивки из флеша через входы-выходы флагов...
P.P.P.S. В первой версии Triador3000 можно память данных вывести наружу (соответственно команды MWW, MRL, MRH станут внешними EX-командами по типу CUSTOM CIRCUITS) - количество ног при этом уменьшится на 12, т.к. ввод-вывод виртуальной ячейки OOO OOO уже будет ненужен (вся обработка памяти данных будет снаружи, включая виртуальную ячейку) - так можно уместиться в DIP40, но возможность простого ввода-вывода исчезнет. С другой стороны в 2017 году у меня была идея использовать R13 для ввода-вывода - это ещё 3 входа и 3 выхода т.е. 48-12+6=42...
P.P.P.P.S. В будущем возможно также придётся разрешить внешним EX-командам менять PC (скажем для реализации "железных" CALL и RET с независимым стеком возвратов), соответственно надо будет ещё 6 входов предусмотреть и 1 тритик про что мы меняем по итогам выполнения внешней EX-инструкции - [A,B,]C,R1 (N) или ничего (O) или PC (P). Так что возможно придётся уходить в PLCC68 хотя входы C,R1 и PC можно совместить, если одновременно их менять не предвидится - в этом случае количество ног увеличится только на 3...
|
10 May 2020 22:31 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
Почти случайно с помощью ручного подгона и DDT удалось составить на редкость компактную преобразовалку из 4-тритного адреса (81 разных адресов) в 7-битный адрес (128 ячеек): | | | | Code: /* Generated by DDTc v0.5 Solution is 10 x DG403 See www.ternary.info */
#include "ddt.h"
int ddt_bin81a(int f, DDT i1, DDT i2, DDT i3, DDT i4, DDT* o1, DDT* o2, DDT* o3, DDT* o4, DDT* o5, DDT* o6, DDT* o7) { DDT r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15; int f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15; f1 = ddt_e21(f,i4,N,P,&r1); if(f1 < 0) return f1; f2 = ddt_e12(f,i4,P,N,&r2); if(f2 < 0) return f2; f3 = ddt_e12(f,i1,P,N,&r3); if(f3 < 0) return f3; f4 = ddt_e21(f,i2,N,r3,&r4); if(f4 < 0) return f4; f5 = ddt_e21(f,i3,r4,P,&r5); if(f5 < 0) return f5; f6 = ddt_e12(f,i3,P,r4,&r6); if(f6 < 0) return f6; f7 = ddt_e21(f,i2,r3,P,&r7); if(f7 < 0) return f7; f8 = ddt_mux(f,i2,P,r3,N,&r8); if(f8 < 0) return f8; f9 = ddt_e12(f,i2,P,r3,&r9); if(f9 < 0) return f9; f10 = ddt_mux(f,i3,r8,r9,r8,&r10); if(f10 < 0) return f10; f11 = ddt_e21(f,i1,N,P,&r11); if(f11 < 0) return f11; f12 = ddt_mux(f,i1,P,N,P,&r12); if(f12 < 0) return f12; f13 = ddt_mux(f,i2,r11,r12,r11,&r13); if(f13 < 0) return f13; f14 = ddt_e12(f,i2,r11,r12,&r14); if(f14 < 0) return f14; f15 = ddt_e12(f,i3,r13,r14,&r15); if(f15 < 0) return f15; if(o1) *o1 = r1; if(o2) *o2 = r2; if(o3) *o3 = r5; if(o4) *o4 = r6; if(o5) *o5 = r7; if(o6) *o6 = r10; if(o7) *o7 = r15; return f1+f2+f3+f4+f5+f6+f7+f8+f9+f10+f11+f12+f13+f14+f15; }
| | | | |
Я не поленился и вручную набрал эту схему в логисиме, проверив каждый троичный адрес перебором - работает: В этой схеме 10 блоков E12 и 9 блоков E21, что означает, что её можно смакетировать используя 10 микросхем DG403 (и ещё одна свободная половинка останется). В покрытии по понятным причинам присутствуют дырки (т.к. не для каждой двоичной комбинации есть соответствующая троичная), но я наверное знаю как их заделать хотя бы частично Такую преобразовалку можно использовать для обращения к двоичной памяти данных из троичного процессора - используется 81 ячейка из 128 (63%) но я как минимум могу добавить ещё 27 немного схитрив (можно взять шестой трит адреса и если он P складывать по ИЛИ младший бит двоичного адреса с логической единичкой - в результате удастся захватить ещё 27 ячеек помеченных <) - тогда будет уже 108 из 128 (84%). Поясню - преобразовалка преобразует адрес NOOO в бинарное число 0000010. Соответственно перебирая всю память по 6-тритным адресам в одну и туже ячейку обратятcя адреса NNNOOO, NONOOO, NPNOOO, ONNOOO и т.д., а если добавить хитрость со старшим тритом P, то обратившись по адресам PNNOOO, PONOOO и PPNOOO мы уже полезем не в бинарную ячейку 0000010, а в 0000011. По идее такой подход - расширяемый. Можно взять три таких блока двоичной памяти по 128 байт каждый и обращаться к ним через 5-тритный адрес, используя туже самую преобразовалку для младших 7 бит, а старшие 2 бита выбирать в зависимости от состояния старшего трита (N->10, O->00, P->01) ну и пользуясь 6м тритом можно точно также схитрить, чтобы получить доступ к дополнительным 27*3=81 ячейкам по некоторым специфическим адресам. P.S. Если триты переставить в обратном порядке, то конверсия будет чуть более логичной - как минимум для Oxxx и Pxxx адресов (а Nxxx я уже втыкал где было свободно). P.P.S. Можно хитрость расширить ещё одним битом - номер 4. Тогда для троичных адресов: Nxx xxx - ничего не менять; Oxx xxx - сбрасывать бит 4 в 0 (либо инвертировать); Pxx xxx - устанавливать бит 0 в 1 (либо дополнительно проверить, что бинарный адрес заканчивается на 10 и только тогда превращать его в 11 - в этом случае другие ячейки не переназначатся). С двойным трюком покрываются уже 117 ячеек (на 9 ячеек больше, чем с одинарным трюком), что составляет уже 91%
|
11 May 2020 03:13 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
Вот текст программки, прогоняющей вышеизложенную схемку по всем адресам из 6-тритного адресного пространства с переставленными в обратном порядке тритами и применением чуть более навороченных трюков: tstbin.c | | | | Code: #include <stdio.h> #include <stdlib.h> #include <string.h>
#include "ddt_bin81a.c"
//#define TWO //#define THREE
int main(int argc, char** argv) { int k = 0; int i,j,l; char s[8] = "NNNNNN"; float f; DDT o[7]; int cover[400],value[400]; for(i=0;i<400;i++) { cover[i] = 0; value[i] = -999; } l = -364; for(j=0;j<729;j++) { ddt_bin81a(DDT_SIM,s[2],s[3],s[4],s[5],&o[0],&o[1],&o[2],&o[3],&o[4],&o[5],&o[6]);
i = ((o[6]=='P')?64:0)| ((o[5]=='P')?32:0)| ((o[4]=='P')?16:0)| ((o[3]=='P')?8:0)| ((o[2]=='P')?4:0)| ((o[1]=='P')?2:0)| ((o[0]=='P')?1:0); #if 1 if(s[0]=='P') { if(s[1]!='P' && o[1]=='P') i|=1; if(s[1]=='O' && o[4]=='P') i-=16; } else if(s[0]=='O') { if(o[4]=='P') i-=16; if(s[1]=='P' &&o[6]=='P') i-=64; } #endif #ifdef THREE if(s[1]=='P') i+=128; if(s[1]=='N') i+=256; #endif #ifdef TWO if(s[1]=='N') i+=128; #endif if(value[i]==-999) value[i] = l; #ifdef THREE printf("%s=%i%i%i%i%i%i%i%i%i (0x%3.3X or %i)\t[%i] %c\n",s, (i&0x100)>>8, #else printf("%s=%i%i%i%i%i%i%i%i (0x%2.2X or %i)\t[%i] %c\n",s, #endif (i&0x80)>>7, (i&0x40)>>6, (i&0x20)>>5, (i&0x10)>>4, (i&0x08)>>3, (i&0x04)>>2, (i&0x02)>>1, (i&0x01),i,i,value[i], cover[i]?' ':'*'); cover[i]++;
if(++s[5]=='Q') { s[5] = 'N'; if(++s[4]=='Q') { s[4] = 'N'; if(++s[3]=='Q') { s[3] = 'N'; if(++s[2]=='Q') { s[2] = 'N'; if(++s[1]=='Q') { s[1] = 'N'; ++s[0]; } } } } } l++; }
printf("\n"); k = 0; #ifdef THREE f = 3.84; for(i=0;i<384;i++) #else #ifdef TWO f = 2.56; for(i=0;i<256;i++) #else f = 1.28; for(i=0;i<128;i++) #endif #endif { if(cover[i]) k++; else printf("0x%2.2X (%i) not covered\n",i,i); } printf("\nCovered %i cells (%2.2f%%)\n\n",k,k/f);
return 0; }
| | | | |
Это работает лучше всего, когда у нас есть один блок с 128 ячейками (там не байты на самом деле, а 12-битные слова): 1блок Покрыто 123 ячейки из 128 (96.09%)(звёздочкой помечены ячейки, встречающиеся первый раз - мне важно было убедиться, что они идут последовательно и не перемешиваются в начале памяти и в последних 81 словах)
|
11 May 2020 19:50 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
2 блока с 128 ячейками (всего 256): 2блока Покрыто 225 ячеек из 256 (87.89%)
|
11 May 2020 19:52 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
3 блока с 128 ячейками (всего 384): 3блока Покрыто 309 ячеек из 384 (80.47%)
|
11 May 2020 21:49 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22586 Location: Silicon Valley
|
В последнем случае у меня получалось поднять покрытие до 333, однако тогда последние 81 слов превращались в мешанину из копий разных ячеек, а мне хотелось сохранить тот же порядок в последних 81 словах, что и в конце первой трети памяти, чтобы стек (растущий от PPP PPP в сторону уменьшения адресов) шёл последовательно через какую бы зону мы туда ни обратились. Вобщем алгоритм такой: в зоне Nxx xxx ничего не трогаем, как конвертер выдал, так и есть; в зонах ONx xxx и OOx xxx - если бит 4 получился 1, то сбрасываем его в 0; в зоне OPx xxx - если бит 4 получился 1, то сбрасываем его в 0 и если бит 6 получился 1, то сбрасываем его в 0; в зоне PNx xxx - если бит 1 получился 1, то бит 0 тоже делаем 1; в зоне POx xxx - если бит 1 получился 1, то бит 0 тоже делаем 1 и если бит 4 получился 1, то сбрасываем его в 0; в зоне PPx xxx - ничего не трогаем (последние 81 слово повторяет конец зоны Nxx xxx). Ещё момент, что в 1-блочном варианте все зоны смотрят в один и тот же блок, в 2-блочном варианте (макрос TWO) зона Nxx xxx уходит во втрой блок, а в 3-блочном варианте (макрос THREE) зона Pxx xxx уходит во второй блок, а зона Nxx xxx - в третий. Интересно, что в результате раскладки получаются совместимыми друг с другом во всех трёх вариантах - всё что есть в 1-блочном варианте, есть в 2-блочном (с расширениями) и в 3-блочном (с ещё большими расширениями) - например во всех трёх вариантах есть отдельно стоящий блок из 9 ячеек с адресами -103...-95, куда скажем можно переместить стек возвратов для программ использующих всю остальную память, а в зоне Pxx xxx появляются отдельно стоящие ячейки (с шагом 3 начиная с адреса 122) где можно хранить отдельные внешние переменные...
|
11 May 2020 21:49 |
|
|
|
Page 1 of 1
|
[ 7 posts ] |
|
Who is online |
Users browsing this forum: Google [Bot] and 51 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|