nedoPC.org

Community of electronics hobbyists established in 2002

...
Atom Feed | View unanswered posts | View active topics It is currently 26 Nov 2020 07:07



Reply to topic  [ 43 posts ]  Go to page Previous  1, 2, 3
Использование двоичного FPGA для реализации троичного компа 
Author Message
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Добавил компонент ternary_clock, который из двоичного клока получает троичную последовательность NOPONOPONOPO:

Code:
-- Entity ternary_clock

USE ternary.ALL;

ENTITY ternary_clock IS
        PORT (
              B_C : IN BIT;
              T_C : OUT FakeTrit
        );
END ternary_clock;

ARCHITECTURE Behavioral OF ternary_clock IS
signal flag : bit;
BEGIN
    PROCESS (B_C)
    BEGIN
        IF (B_C'event AND B_C = '1') THEN
            IF (flag = '0') THEN
                flag <= '1';
            ELSE
                flag <= '0';
            END IF;
        END IF;
        IF (B_C = '1' AND flag = '0') THEN
            T_C(0) <= '1';
        ELSE
            T_C(0) <= '0';
        END IF;
        IF (B_C = '1' AND flag = '1') THEN
            T_C(1) <= '1';
        ELSE
            T_C(1) <= '0';
        END IF;
    END PROCESS;
END Behavioral;


Вроде работает. Правда результирующие формулы показывают, что на считающий триггер FTCPE подан 0, т.е. он считать не должен, но вроде бы считает:

Quote:
********** Mapped Logic **********
FTCPE_mem1/flag: FTCPE port map (mem1/flag,'0',clk,'0','0','1');
s1(0) <= NOT ((clk AND NOT mem1/flag));
s1(1) <= NOT ((clk AND mem1/flag));
s2(0) <= b(0);
s2(1) <= b(1);
s3(0) <= c(0);
s3(1) <= c(1);
Register Legend:
FDCPE (Q,D,C,CLR,PRE,CE);
FDDCPE (Q,D,C,CLR,PRE,CE);
FTCPE (Q,D,C,CLR,PRE,CE);
FTDCPE (Q,D,C,CLR,PRE,CE);
LDCP (Q,D,G,CLR,PRE);


Теперь у нас есть всё, чтобы загнать TRIADOR в CPLD/FPGA :mrgreen:


Attachments:
ternary.vhd [7.04 KiB]
Downloaded 383 times

_________________
:eugeek: https://twitter.com/Shaos1973
06 Jul 2018 02:46
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
И вот так можно подключать CPLD/FPGA в троичную систему:

Attachment:
ternary-fpga-interface.jpg
ternary-fpga-interface.jpg [ 37.32 KiB | Viewed 4703 times ]


Получается в среднем один корпус DG403 на каждый троичный вход и на каждый троичный выход

_________________
:eugeek: https://twitter.com/Shaos1973


06 Jul 2018 03:05
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Взял из интернета делитель частоты на что угодно - он занял 38 макроячеек (т.к. счётчик 32-битный):
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
 
entity Clock_Divider is
port ( clk,reset: in std_logic;
clock_out: out std_logic);
end Clock_Divider;
 
architecture bhv of Clock_Divider is
signal count: integer:=1;
signal tmp : std_logic := '0';
begin
process(clk,reset)
begin
if(reset='1') then
count<=1;
tmp<='0';
elsif(clk'event and clk='1') then
count <=count+1;
if (count = 1000000) then
tmp <= NOT tmp;
count <= 1;
end if;
end if;
clock_out <= tmp;
end process;
end bhv;

Теперь вот задействовал тактовый сигнал 1.8432 МГц, что на плате, и делю его на миллион (см.выше), чтобы глазами видеть NOPONOPONOPO после ternary_clk :)

Пора заталкивать в CPLD троичный счётчик :mrgreen:

Image

P.S. bln (block negative) это e21(s,O,P) или mux(s,O,O,P),
а blp (block positive) это e12(s,N,O) или mux(s,N,O,O).

_________________
:eugeek: https://twitter.com/Shaos1973


06 Jul 2018 19:40
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Троичный счётчик вроде считает - интересный момент, что каждый новый троичный разряд счётчика добавляет только 2 макроячейки, что несколько неожиданно, т.к. я рассчитвал на 4 потому что в каждом разряде у нас по 2 блока MEM

Вот исходный текст главного модуля:
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

use ternary.all;

entity main is
    Port ( clk : in bit;
           res : in bit;
           a : in FakeTrit;
           b : in FakeTrit;
           c : in FakeTrit;
           s1 : out FakeTrit;
           s2 : out FakeTrit;
           s3 : out FakeTrit;
           led : out bit);
end main;

architecture Behavioral of main is
signal a1,b1,c1,ss0,ss1,ss2,ss3,ss4 : FakeTrit;
signal pclk,pclk1,nclk,nclk1,res0,res1,m1,m2,m3,m4,h1,h2,h3,h4,g1,g2,g3 : FakeTrit;
signal tmp_clk_std, tmp_iclk_std : STD_LOGIC;
signal tmp_clk : BIT;

COMPONENT Clock_Divider
PORT(
clk : IN std_logic;
reset : IN std_logic;
clock_out : OUT std_logic
);
END COMPONENT;

COMPONENT Half_Adder
Port ( a : in FakeTrit;
       b : in FakeTrit;
       s : out FakeTrit;
       c : out FakeTrit
      );
END COMPONENT;      

FUNCTION io_invert(T: FakeTrit) RETURN FakeTrit IS
begin
                case T is
                when N =>
                        return P;
                when O =>
                        return X;
                when P =>
                        return N;
                when others =>
                        return O;
                end case;
end;
      
begin

a1 <= io_invert(a);
b1 <= io_invert(b);
c1 <= io_invert(c);

tmp_iclk_std <= to_stdulogic(clk);
div1: Clock_Divider port map( clk => tmp_iclk_std, reset => '0', clock_out => tmp_clk_std );
tmp_clk <= to_bit(tmp_clk_std);

res0(0) <= '0';
res0(1) <= res;
res1 <= res0;

clk1: ternary_clock port map( B_C => tmp_clk, T_C => ss0 );
mux1: ternary_mux port map( T_S => ss0, T_N => O, T_O => O, T_P => P, T_C => pclk );
mux2: ternary_mux port map( T_S => res1, T_N => pclk, T_O => N, T_P => N, T_C => pclk1 );
mux3: ternary_mux port map( T_S => ss0, T_N => N, T_O => O, T_P => O, T_C => nclk );
mux4: ternary_mux port map( T_S => res1, T_N => nclk, T_O => P, T_P => P, T_C => nclk1 );
mem1: ternary_mem port map( T_S => pclk1, T_N => O, T_P => ss1, T_Q => m1 );
ha1: Half_Adder port map( a => P, b => m1, s => h1, c => g1 );
mem2: ternary_mem port map( T_S => nclk1, T_N => h1, T_P => O, T_Q => ss1 );
mem3: ternary_mem port map( T_S => pclk1, T_N => O, T_P => ss2, T_Q => m2 );
ha2: Half_Adder port map( a => g1, b => m2, s => h2, c => g2 );
mem4: ternary_mem port map( T_S => nclk1, T_N => h2, T_P => O, T_Q => ss2 );
mem5: ternary_mem port map( T_S => pclk1, T_N => O, T_P => ss3, T_Q => m3 );
ha3: Half_Adder port map( a => g2, b => m3, s => h3, c => g3 );
mem6: ternary_mem port map( T_S => nclk1, T_N => h3, T_P => O, T_Q => ss3 );

s1 <= io_invert(ss1);
s2 <= io_invert(ss2);
s3 <= io_invert(ss3);

led <= to_bit(tmp_clk_std);

end Behavioral;


Исходный текст модуля полусумматора:
Code:
use ternary.all;

entity Half_Adder is
    Port ( a : in FakeTrit;
           b : in FakeTrit;
           s : out FakeTrit;
           c : out FakeTrit
          );
end Half_Adder;

architecture Behavioral of Half_Adder is
signal r1,r2,r3,r4,r5,r6 : FakeTrit;
begin
process (a,b)
begin
    r1 <= mux(a,P,N,O);
    r2 <= mux(a,O,P,N);
    r3 <= mux(b,r1,a,r2);
    r4 <= e12(a,N,O);
    r5 <= e21(a,O,P);
    r6 <= mux(b,r4,O,r5);
    s <= r3;
    c <= r6;
end process;
end Behavioral;


Привязка ног:
Code:
NET "clk" LOC = "P38" | IOSTANDARD = LVTTL ;
NET "res" LOC = "P143" | IOSTANDARD = LVTTL ;
NET "a<0>"  LOC = "P140" | IOSTANDARD = LVTTL ;
NET "a<1>"  LOC = "P142" | IOSTANDARD = LVTTL ;
NET "b<0>"  LOC = "P138" | IOSTANDARD = LVTTL ;
NET "b<1>"  LOC = "P139" | IOSTANDARD = LVTTL ;
NET "c<0>"  LOC = "P136" | IOSTANDARD = LVTTL ;
NET "c<1>"  LOC = "P137" | IOSTANDARD = LVTTL ;
NET "s3<0>"  LOC = "P82" | IOSTANDARD = LVTTL ;
NET "s3<1>"  LOC = "P83" | IOSTANDARD = LVTTL ;
NET "s2<0>"  LOC = "P85" | IOSTANDARD = LVTTL ;
NET "s2<1>"  LOC = "P86" | IOSTANDARD = LVTTL ;
NET "s1<0>"  LOC = "P87" | IOSTANDARD = LVTTL ;
NET "s1<1>"  LOC = "P88" | IOSTANDARD = LVTTL ;
NET "led"  LOC = "P92" | IOSTANDARD = LVTTL ;


Плюс ещё использовался модуль делителя частоты, что я приводил чуть выше, но в данном случае я делю на 460800, чтобы счётчик считал секунды (тактовая частота при преобразовании в троичную синхру делится на 4).

P.S. На этом этапе VHDL код постепенно начинает превращаться в месиво - думаю пора браться за автоматизацию...

P.S.S. Видосик :roll:


https://youtu.be/H9YdG00UXx4

На видео запечетлено, как оно после сброса кнопкой (вход res) считает от OOO (0) до PPP (+13) и далее NNN (-13) и вверх до OOO (0) с периодом в 1 секунду (частоту двоичного такта, которая выше в 4 раза, можно пронаблюдать на бортовом красном светодиодике)

_________________
:eugeek: https://twitter.com/Shaos1973


08 Jul 2018 02:56
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Shaos wrote:
Троичный счётчик вроде считает - интересный момент, что каждый новый троичный разряд счётчика добавляет только 2 макроячейки, что несколько неожиданно, т.к. я рассчитвал на 4 потому что в каждом разряде у нас по 2 блока MEM

В этот CoolRunner-II с 256 макроячейками можно выходит затолкать 128-тритный счётчик :)

_________________
:eugeek: https://twitter.com/Shaos1973


08 Jul 2018 12:49
Profile WWW
Doomed
User avatar

Joined: 21 Mar 2017 13:50
Posts: 634
Location: Spb
Reply with quote
Shaos wrote:
можно выходит затолкать 128-тритный счётчик

Больше интереса вызывает вопрос: а сколько ячеек нужно что бы затолкать более-менее функциональный Триадор с его "лимитом" в семь сотен Тримуксов?


08 Jul 2018 13:03
Profile
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
AlexanderZh wrote:
Shaos wrote:
можно выходит затолкать 128-тритный счётчик

Больше интереса вызывает вопрос: а сколько ячеек нужно что бы затолкать более-менее функциональный Триадор с его "лимитом" в семь сотен Тримуксов?

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

_________________
:eugeek: https://twitter.com/Shaos1973


08 Jul 2018 13:28
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Надо чтоли про средства отладки подумать - чтобы можно было сигнал в любой (или почти любой) точке изнутри выдать наружу и померять - либо путём адресации к конкретным точкам в паузе, либо путём потритового сдвига наружу (опять же в паузе) аналогично https://en.wikipedia.org/wiki/JTAG или примерно как тут: Троичный вариант SPI

Первый вариант потребует больше ног (т.к. адрес задаётся параллельно), а для второго можно обойтись одним троичным входом и одним троичным выходом:
Input TMC - ternary mode/clock
Output TDO - ternary data out
Типа подаём на TMC последовательность ONOPOPOPOPOP... по N оно считает значения во внутренний многотритовый регистр, а по P будет эти значения сдвигать в TDO, где мы будем программно их считывать и отображать в отладчике

P.S. Либо если у нас всё теже MEM-защёлки по уровню, то тактировать их также NOPONOPONOPO имея по 2 MEM на тестовый трит, но тогда придётся иметь отдельный вход на команду записи состояние схемы в защёлки (и тот же трит можно использовать для записи из защёлок в схему для изменения состояния в будущем - тогда ещё их вход TDI добавится)

P.P.S. Чтобы не путаться с JTAG-ом можно назвать сигналы иначе:
TTC - ternary clock (NOPONOPONOPO)
TTS - ternary control (P to read and N to write)
TTO - ternary test output
TTI - ternary test input (optional)
Тогда отладка будет выглядеть так:
- останавливаем глобальный клок (схема в паузе)
- подаём на TTS уровень P и возвращаем обратно (в этом случае все тестовые защёлки запомнят состояние точек)
- подаём на TTC последовательность NOPONOPONOPO одновременно снимая значения с выхода TTO после каждого P

P.P.P.S. На самом деле внутренние тестовые защёлки могут защелкивать текущее состояние постянно сами по глобальному клоку (скажем на P) - в этом случае вход TTS ненужен и в простейшем случае нам надо будет только TTC и TTO

_________________
:eugeek: https://twitter.com/Shaos1973


08 Jul 2018 17:44
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Shaos wrote:
На этом этапе VHDL код постепенно начинает превращаться в месиво - думаю пора браться за автоматизацию...

Можно попробовать продолжать в том же духе, вручную переписывая логисимовскую схему на VHDL - для этого правда придётся вооружиться распечаткой модели, где каждому соединению приписано имя...

Shaos wrote:
Надо чтоли про средства отладки подумать - чтобы можно было сигнал в любой (или почти любой) точке изнутри выдать наружу и померять - либо путём адресации к конкретным точкам в паузе, либо путём потритового сдвига наружу (опять же в паузе) аналогично https://en.wikipedia.org/wiki/JTAG или примерно как тут: Троичный вариант SPI

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

А пока можно просто необходимые точки через VHDL цеплять к свободным ногам микросхемы, которых дофига (118) ;)

_________________
:eugeek: https://twitter.com/Shaos1973


08 Jul 2018 21:43
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
Идея у меня как расширить триадора до возможностей полноценного микроконтроллера не ломая существующую архитектуру

Вобщем суть в том, что самый верх пространства программ (тот что начинается NNNNNN) будет использоваться для переконфигурирования чипа путём передачи туда управления, которое никуда не передастся - например:

R1 -13 ; R1=-13
RR -13 ; R13=R1 (-13)
R1 3 ; R1=3 (for example)
JP -13 ; jump to NNNNNN

Тут на самом деле прыжка не произойдёт - программа пойдёт дальше, но уже в 3й странице программной памяти :)

Точно также разные адреса для фейковых прыжков могут делать разные другие вещи - например переключать отдельные ноги портов на вход или выход (скажем адреса с NNNNNO для R12 до NNNNPP для R5):

значение +1 включает трит порта на вход
значение 0 включает трит порта на выход (по умолчанию) и при чтении читается трит из регистра
значение -1 оставляет трит порта выходом, передавая туда запомненное до этого состояние, но теперь все дальнейшие обращения к триту регистра (и на чтение, и на запись) идут в теневую память (таким образом мы легко и непринуждённо увеличиваем количество регистров почти в 2 раза)

Прыжки в NNNONN, NNNONO, NNNONP, NNNOON, NNNOOO, NNNOOP, NNNOPN, NNNOPO и NNNOPP могут настраивать соответствующие команды EX

Вобщем как-то так :roll:

_________________
:eugeek: https://twitter.com/Shaos1973


10 Jul 2018 03:33
Profile WWW
Novelist

Joined: 21 Jan 2019 04:36
Posts: 35
Reply with quote
Есть такой HDL, называется Lola-2. По синтаксису похож на Паскаль (точнее - Оберон). Транслируется в Verilog и дальше обрабатывается стандартно для этого языка. Я вот думаю, для создания троичных схем в FPGA стоило-бы сделать некую Lola-3, которая транслировалась-бы в Verilog, а лучше - в SystemVerilog.


21 Jan 2019 11:01
Profile ICQ
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 18968
Location: Silicon Valley
Reply with quote
kvas wrote:
Есть такой HDL, называется Lola-2. По синтаксису похож на Паскаль (точнее - Оберон). Транслируется в Verilog и дальше обрабатывается стандартно для этого языка. Я вот думаю, для создания троичных схем в FPGA стоило-бы сделать некую Lola-3, которая транслировалась-бы в Verilog, а лучше - в SystemVerilog.

Оберон, а тем более Паскаль - это прошлый век :roll:
Надо брать C++ и никаких сусликов :)
http://www.nedopc.org/forum/viewtopic.php?f=81&t=18935

_________________
:eugeek: https://twitter.com/Shaos1973


21 Jan 2019 21:23
Profile WWW
Novelist

Joined: 21 Jan 2019 04:36
Posts: 35
Reply with quote
Shaos wrote:
kvas wrote:
Есть такой HDL, называется Lola-2. По синтаксису похож на Паскаль (точнее - Оберон). Транслируется в Verilog и дальше обрабатывается стандартно для этого языка. Я вот думаю, для создания троичных схем в FPGA стоило-бы сделать некую Lola-3, которая транслировалась-бы в Verilog, а лучше - в SystemVerilog.
Оберон, а тем более Паскаль - это прошлый век :roll:
Надо брать C++ и никаких сусликов :)
http://www.nedopc.org/forum/viewtopic.php?f=81&t=18935
Ну, "прошлый век" это не аргумент. Например, системе размножения млекопитающих уже не одна сотня миллионов лет, но думаю, что большинство читателей форума появилось на свет именно благодаря ей ;)
К тому-же по предложенной ссылке, как я понял, не HDL-синтезатор, а HDL-симулятор, это несколько разные классы ПО. Для моделирования работы предлагаемый там код вполне успешно применим. А вот для синтеза заливаемой в FPGA прошивки уже нужно нечто другое. Проект "Оберон-2013" как раз прекрасный пример того, как с нуля разработать и воплотить на FPGA вычислительную систему нового типа. Это практически то-же самое, что и планируется в этой теме форума. Хотя ЦП я-бы "срисовывал" скорее не с Виртовского, а с J1a (вот тут о его предшественнике J1 http://excamera.com/sphinx/fpga-j1.html есть кое-что).


24 Jan 2019 03:18
Profile ICQ
Display posts from previous:  Sort by  
Reply to topic   [ 43 posts ]  Go to page Previous  1, 2, 3

Who is online

Users browsing this forum: No registered users and 1 guest


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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.