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 ;)
SHAOS
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
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
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