На асинхронной логике можно сделать очень много, и особенно на FPGA

Пока что здесь ничего сильно выдающегося нет, за исключением того, что публикация напрямую противоречит «бытующим» (так их называют другие) мнениям и распространяемым сведениям, которые не совсем правдивые. В естественной среде (в реальном мире), вопреки им, на асинхронной логике построено всё, и даже жизнь. Пытаться повторить последнее на FPGA разумеется можно только в виде игры, но и её пока что не будет. Хотя публикация имеет место быть, даже с таким объёмом материала, так как её содержание — мой небольшой опыт работы с FPGA, свидетельствует в пользу того, что материал распространённый ранее в сети, по части асинхронной или статической логики, не то что не точный -, а полностью не соответствует естественному порядку вещей в действительности, это было-бы можно объяснять специфичностью FPGA, но никакой такой специфичности на самом деле нет, не было, и вряд-ли когда будет, поэтому пусть тот материал остаётся сам по себе, и рассматривать его далее не стоит.

Работал над схемой лаунчера, тестировал диодами (дело в том, что в основном я работаю с Ubuntu, а осцилоскоп — именно такую фичу предоставляет компания Gowin, да и то не для всех плат работает только с самой EDA, а не с openFPGALoader-а), потому как если верить стаьям то полноценно запустите его на линуксе, да ещё и фряшном (пока вроде так) — та ещё проблема. Да, мной был приобретён миниПК для работы с осцилоскопом, да там это всё работает и вполне компактно получилось, чтобы таскать с собой по командировкам, но пока с Ubuntu на ноутбуке — диодами на плате.

Порой, во время работы над схемой лаунчера, при оглядке назад на материал в сети, казалось что запустить её — не хватит жизни, ибо правду говорят о ограниченности FPGA да и вообще электронники. Но приобретённый ранее опыт и успешное решение по части алгоритмизации требовали продолжения. В конце концов — лаунчер запустился. Проблему вызвал асинхронный триггер, который я пытался реализовать на базе примитива DLC, казалось он работает успешно, но увы — при наличии на входе сигнала Z он сбрасывался, и хоть у меня есть опыт решения таких поблем — я не стал её решать, отложив этот казус на потом, а просто создал такой асинхронный триггер, по сути слепленный мной из кусков сведений в сети на разных сайтах.

module Trs
(input S, R, output reg Q);
always @(R, S)
  begin
     if(R)
        Q  <= 1'b0;
     else if(S) 
        Q  <= 1'b1;
  end
endmodule

Это работает и не сбоит. Выглядит, во вьювере EDA, схема так

15d2deef6c74df55136e4ebbfddb7818.png

, громоздко немного, хотелось изящнее, но то потом, пока что это не столь важно.

Собственно лаунчер нужен совсем не много — всего лишь для запуска демки конвейера кэша команд, называемого мной теперь так — «Адресный конвейер , или линия автономной дискретной активации ячеек и линия управления дискретностью (асинхронной или статической логики)», но отсутствие опыта подстёгивало желание срочно его приобрести, с учётом того что без него дальше будет и вовсе трудно, а тем более работа в целом противоречит опыту пользователей и специалистов, ну если не опыту — то сведениям ими охотно распространяемым. Поэтому даже на столь незначительной схеме я поупирался, и моё упорство было вознаграждено — все четыре диода зажигались, что было свидетельством получения стабильной схемы, даже при наличии в ней сигнала Z. Все свои схемы я проверяю и отлаживаю в симуляторе Logisim — это удбная программа и её симулятор достаточно точен и имеет необзодимый инстрементарий. Задача лаунчера — зажечь диоды именно поочерёдно, потому что, чтобы привести конвейер в действие в демоварианте (собственно тоже активно создаётся только из-за отсутствия опыта, ну и ранее расбросанных другими сведений), нужно последовательно произвести ряд действий, их хоть для глаза все диоды загораются одновременно — на самом деле это просто поисходит очень быстро.

Итак лаунчер, изначально хотел реализовать каждое звено на двух триггерах, но не смог быстро создать схему генерирующую сигнал повторного запуска цикла управляющих сигналов, которые приходят из блока SetChain (выбран и выделен во вьювере красным контуром, в отличии от остальных элементов схемы) и необходимы для работы активаторов activate . Каждый активатор выдаёт последовательно на, соответствующий действию, контакт сигнал, и потом убирает его, при этом он отправляет на SetChain сигнал повтороный активации, после чего цикл повторяется.

ad41e3f471defad32b0aed66e6189e01.png

Сам активатор (в схеме выше их четыре справа, перед выходящими пинами лаунчера) во вьювере Gowin EDA выглядит так (открывается просто двойным кликом мыши по элементу, возвращаемся выбрав пункт «Pop » в выпадающем списке при нажатии на свободное пространство ПКМ). *Кстати — при каждой правке кода нужно сохранять изменения, иначе компилятор их просто не увидит при запуске компиялции.

fc92eef74bb7b7466855f72079dec284.png

представление не совсем удобное, но чтобы убедиться в правильности расключения всех проводов — этого вполне хватает, разумеется в относительно сложных схемах я тут-же сверяюсь с отлаженной схемой в Logisim. Прежде чем сливать сюда весь код (если что плата у меня tangnano9k, и распиновку солью позднее) — хочется показать то, как работает сам активатор. Выходящим пином out1 он активирует то что нужно лаунчеру (в данном тест варианте лаунчер просто записывает в триггеры за его пределами единицу, шаг за шагом, выходя которых подключены к диодам, на данной платке они инверсные поэтому следуют за элементов not). Выход onActivate отправляет сигнал запуска повторного цикла управляющей пары сигналов, а выход outFurther просто пропускает (out) и актуализирует (further) управляющие сигналы далее по цепи активаторов.

Как работает активатор — именно он демонстирует больше всего возможности асинхронной — статической логики (оная интересна тем, что реализовать её можно на любом носителе, мной используется бинарная, но вот тут в симуляции как раз и показано то, что имея всего два типа сигналов и в данном случае два входящих контакта, расширять логику можно на большее число контактов без каких-либо дешифраторов, может это и не весть какая новость -, но тем не менее очень интересно). Третий триггер может и не нужен, но я не стал ломать сильно голову над идеальностью схемы, так как предназначение лаунчера, сейчас, достаточно такое — опосредованное. В анимации симуляции всего два активатора, чтобы хоть как-то было видны метки возле пинов и элементов, а так можно ставить сколько угодно.

45ca32065e2a4a103828eda0a134d0d0.gif

Во вьювере тест модуль выглядит так

d86305506a59b023ae8bc7d93c7383dc.png

Код проекта

module Trs
(input S, R, output reg Q);//reg
//reg Q;
always @(R, S)
  begin
     if(R)
        Q  <= 1'b0;
     else if(S) 
        Q  <= 1'b1;
  end
endmodule

module Chain (input on, off, output out);
Trs t1(on,off,out1);
Trs t2(out1,off,out2);
Trs t3(out2,off,out3);
Trs t4(out3,off,out4);
Trs t5(out4,off,out5);
Trs t6(out5,off,out6);
Trs t7(out6,off,out7);
Trs t8(out7,off,out8);
Trs t9(out8,off,out9);
Trs t10(out9,off,out);
endmodule

module SetChain (input on, output out,further);
wire reset0,reset1;
Chain Ch1(on,reset0,out);
Chain Ch2(out,further,reset0);
Chain Ch3(reset0,reset1,further);
Chain Ch4(further,on,reset1);
endmodule

module mkick (output led);
wire w4;
wire w0=0;
Trs trs1(w4,w0,wt);
not n0(led, wt);
Trs trs2(led,w0,w2);
Trs trs3(w2,w0,w3);
Trs trs4(w3,w0,w4);
endmodule

module activate (input out, further, output out1, onActivate,OutFurther);
wire wi0=0;
wire wi1,onout2,onTrsReset,outTrsReset;
bufif1 bf1(on,out,wi1);
Trs Tout(on,wi0,onout1);
bufif1 bf2(onFurth,onout1,further);
Trs TFurth(onFurth,wi0,onWi1);
xor xs1(onout2,onout1,onWi1);
bufif1 bf3(out1,out,onout2);
not n1(wi1, onWi1);
bufif1 bf4(OutFurther,out,onWi1);
Trs TrsReset(onout2,onTrsReset,outTrsReset);
and An1(wA1,outTrsReset,onWi1);
not n2(notfurther,further);
bufif1 bf5(onActivate,wA1,notfurther);
bufif1 bf6(onTrsReset,out,wA1);

endmodule

module Launcher (output Limit,Fills, Unit, Run);
wire zero=0;
wire out;
mkick k1(kick);
bufif1 (on,kick,kick);
Trs t1(on,out,on1);
SetChain Sc1(on1,out,further);
activate act1(out,further,Limit,onActivate0,Outfurther1);//activate act1(out,further,Limit,onActivate0,Outfurther1);
bufif1 (on,onActivate0,onActivate0);//onActivate0);
activate act2(Outfurther1,further,Fills,onActivate1,Outfurther2);
bufif1 (on,onActivate1,onActivate1);
activate act3(Outfurther2,further,Unit,onActivate2,Outfurther3);
bufif1 (on,onActivate2,onActivate2);
activate act4(Outfurther3,further,Run,onActivate3,Outfurther4);

endmodule

module Test (output led0, led1, led2, led3);
wire wi0 = 0;
Launcher La1(on0,on1,on2,on3);
Trs t1(on0,wi0,onled0);
Trs t2(on1,wi0,onled1);
Trs t3(on2,wi0,onled2);
Trs t4(on3,wi0,onled3);
not n0(led0,onled0);
not n1(led1,onled1);
not n2(led2,onled2);
not n3(led3,onled3);

endmodule

Распинова для tangnano9k мало чем отличается от распиновке в примере https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-9K/examples/led.html

.

На этом пока всё, на подходе к завершению демка кэша команд процессора, под спойлером тоже вставлю анимацию, проект почти закончен в Verilog, осталось немного.Секундомер для того, чтобы давать описания действий в симуляторе

Скрытый текст

b8098dbcf198362cd993489f3909e5ff.gif

В планах так-же поработать над асинхронным АЛУ для процессора. Вообще планируется полностью отличная архитектура вычислительной машины, основной концепцией которой будет асинхронная (статическая) логика, в которой каждый сигнал будет распространяться с естественной для него скоростью, обусловленной скоростью распространения в среде — носителе. Разумеется плюс-минус обусловленность скоростью срабатывания некоторых элементов, но основной упор в схемах будет на то, что те все будут приведены в нужное состояние перед задействованием. Как минимум архитектура мной будет задействована в планируемом проекте сварочного робота, а там — посмотрим, может ещё где. Началось всё с машинного зрения, потом была алгоритмизация и анализ кода — и потом уже пришёл к выводу, что архитектуру лучше полность делать свою. Делаю по мере возможностей.

На этом пока всё, есть куча дел других — по хозяйству, работе, поэтому проект демки конвейера, или кэша команд, будет готов примерно через пару недель. Делается всё нормальными темпами — каждый день в будние дни по часу-два, в выходные примерно так-же (так как куча других дел), основным тормозом работ было то, что в FPGA я новичок, но это уже постепенно уходит на задний план.

© Habrahabr.ru