Close

Ternary counter on VHDL

A project log for Homebrew ternary computer

TRIADOR: The only ternary computer made for real in the past 50 years.

shaosSHAOS 07/08/2018 at 09:262 Comments

I just literally copied this ternary counter design from 2011 into VHDL:

This is VHDL source code (only 3 trits were used):

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;

Every trit in the counter takes 2 macrocells on CoolRunner-II, so technically CoolRunner-II chip XC2C256 with 256 macrocells may have up to 128-trit counter inside! This is pin assignments for XC2-XL board (a,b,c are not used here):

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 ; 

and this is a video that proves that it's working on Xilinx CoolRunner-II ;) 

Discussions

SHAOS wrote 07/08/2018 at 09:27 point

Counter counts from OOO (0) to PPP (+13) and then NNN (-13) and up to OOO (0) - one increment per second

  Are you sure? yes | no

SHAOS wrote 07/08/2018 at 19:47 point

and Clock_Divider divides onboard clock 1.8432 MHz by 460800 in order to get 4 Hz that then turns into 1 Hz ternary clock NOPONOPONOPO...

  Are you sure? yes | no