OpenCores
URL https://opencores.org/ocsvn/tiny64/tiny64/trunk

Subversion Repositories tiny64

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/ALU.vhd
0,0 → 1,151
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
use work.TinyXconfig.ALL;
 
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity ALU is
Port ( opa : in cpuWord;
opb : in cpuWord;
res : out cpuWord;
cin : in std_logic;
cout : out std_logic;
zero : out std_logic;
sign : out std_logic;
over : out std_logic;
what : in std_logic_vector(3 downto 0));
end ALU;
 
architecture Behavioral of ALU is
 
constant alu_mov : std_logic_vector(3 downto 0) := "0000";
constant alu_and : std_logic_vector(3 downto 0) := "0001";
constant alu_or : std_logic_vector(3 downto 0) := "0010";
constant alu_xor : std_logic_vector(3 downto 0) := "0011";
constant alu_add : std_logic_vector(3 downto 0) := "0100";
constant alu_sub : std_logic_vector(3 downto 0) := "0101";
constant alu_ror : std_logic_vector(3 downto 0) := "0110";
constant alu_lsr : std_logic_vector(3 downto 0) := "0111";
constant alu_lsra : std_logic_vector(3 downto 0) := "1000";
constant alu_swap : std_logic_vector(3 downto 0) := "1001";
constant alu_swapb : std_logic_vector(3 downto 0) := "1010";
constant alu_inc : std_logic_vector(3 downto 0) := "1011";
constant alu_dec : std_logic_vector(3 downto 0) := "1100";
constant alu_rorb : std_logic_vector(3 downto 0) := "1101";
 
begin
 
assert XLEN > 31 report "XLEN must at least 32 and multiple of 8";
assert (XLEN rem 8) = 0 report "XLEN must at least 32 and multiple of 8";
 
process(opa, opb, cin, what)
variable temp : std_logic_vector(XLEN downto 0);
variable ctr : integer;
variable help : std_logic_vector((XLEN-1) downto 0);
variable helper : std_logic_vector(XLEN downto 0);
begin
case what is
when alu_mov =>
res <= opb;
temp := ("0" & opb);
cout <= cin;
over <= '0';
when alu_and =>
res <= opa and opb;
temp := ("0" & opa) and ("0" & opb);
cout <= cin;
over <= '0';
when alu_or =>
res <= opa or opb;
temp := ("0" & opa) or ("0" & opb);
cout <= cin;
over <= '0';
when alu_xor =>
res <= opa xor opb;
temp := ("0" & opa) xor ("0" & opb);
cout <= cin;
over <= '0';
when alu_add =>
res <= opa + opb + (getStdLogicVectorZeroes(XLEN-1) & cin);
temp := ("0" & opa) + ("0" & opb) + (getStdLogicVectorZeroes(XLEN-1) & cin);
cout <= temp(XLEN);
over <= (opa(XLEN-1) and opb(XLEN-1) and not temp(XLEN-1)) OR (not opa(XLEN-1) and not opb(XLEN-1) and temp(XLEN-1));
when alu_sub =>
res <= opa - opb - (getStdLogicVectorZeroes(XLEN-1) & cin);
temp := ("0" & opa) - ("0" & opb) - (getStdLogicVectorZeroes(XLEN-1) & cin);
cout <= temp(XLEN);
over <= (opa(XLEN-1) and opb(XLEN-1) and not temp(XLEN-1)) OR (not opa(XLEN-1) and not opb(XLEN-1) and temp(XLEN-1));
when alu_ror =>
res <= opa(0) & opa((XLEN-1) downto 1);
temp := "0" & opa(0) & opa((XLEN-1) downto 1);
cout <= opa(0);
over <= '0';
when alu_lsr =>
res <= cin & opa((XLEN-1) downto 1);
temp := "00" & opa((XLEN-1) downto 1);
cout <= opa(0);
over <= '0';
when alu_lsra =>
res <= opa(XLEN-1) & opa((XLEN-1) downto 1);
temp := "0" & opa(XLEN-1) & opa((XLEN-1) downto 1);
cout <= opa(0);
over <= '0';
when alu_swap =>
res <= opa((XLEN/2-1) downto 0) & opa((XLEN-1) downto (XLEN/2));
temp := "0" & opa((XLEN/2-1) downto 0) & opa((XLEN-1) downto (XLEN/2));
cout <= cin;
over <= '0';
when alu_swapb =>
ctr := XLEN / 8;
help := opa(7 downto 0) & getStdLogicVectorZeroes(XLEN-8);
swb: for index in 1 to ctr-2 loop
help := help or (getStdLogicVectorZeroes(index*8) & opa(((index+1)*8-1) downto (index*8)) & getStdLogicVectorZeroes((ctr-index-1)*8));
end loop;
help := help or (getStdLogicVectorZeroes(XLEN-8) & opa((XLEN-1) downto (XLEN-8)));
res <= help;
helper := "0" & opa(7 downto 0) & getStdLogicVectorZeroes(XLEN-8);
swt: for index in 1 to ctr-2 loop
helper := helper or ("0" & getStdLogicVectorZeroes(index*8) & opa(((index+1)*8-1) downto (index*8)) & getStdLogicVectorZeroes((ctr-index-1)*8));
end loop;
helper := helper or ("0" & getStdLogicVectorZeroes(XLEN-8) & opa((XLEN-1) downto (XLEN-8)));
temp := helper;
--res <= opa(7 downto 0) & opa(15 downto 8) & opa(23 downto 16) & opa(31 downto 24);
--temp := "0" & opa(7 downto 0) & opa(15 downto 8) & opa(23 downto 16) & opa(31 downto 24);
cout <= cin;
over <= '0';
when alu_inc =>
res <= opa + "1" + cin;
temp := opa + "1" + cin;
cout <= temp(XLEN);
over <= '0';
when alu_dec =>
res <= opa - "1" - cin;
temp := opa - "1" - cin;
cout <= temp(XLEN);
over <= '0';
when alu_rorb =>
res <= opa(7 downto 0) & opa((XLEN-1) downto 8);
temp := "0" & opa(7 downto 0) & opa((XLEN-1) downto 8);
cout <= cin;
over <= '0';
when others =>
res <= getStdLogicVectorZeroes(XLEN);
temp := getStdLogicVectorZeroes(XLEN);
cout <= cin;
over <= '0';
end case;
sign <= temp(XLEN-1);
if temp((XLEN-1) downto 0) = 0 then
zero <= '1';
else
zero <= '0';
end if;
end process;
end Behavioral;
 
/trunk/TinyXconfig.vhd
0,0 → 1,39
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
package TinyXconfig is
constant XLEN : integer := 32;
subtype cpuWord is std_logic_vector(XLEN -1 downto 0);
constant ccModeLeft : integer := XLEN - 1;
constant ccModeRight : integer := XLEN - 4;
constant aluModeLeft : integer := XLEN - 5;
constant aluModeRight : integer := XLEN - 8;
constant memmuxBit : integer := XLEN - 9;
constant dstClkLeft : integer := XLEN - 10;
constant dstClkRight : integer := XLEN - 12;
constant writeCycleBit : integer := XLEN - 13;
constant opamuxLeft : integer := XLEN - 14;
constant opamuxRight : integer := XLEN - 16;
constant valmuxBit : integer := XLEN - 17;
constant opbmuxLeft : integer := XLEN - 18;
constant opbmuxRight : integer := XLEN - 20;
constant flagUpdateBit : integer := XLEN - 21;
constant carryUseBit : integer := XLEN - 22;
-- two bits unused
constant immediateLeft : integer := XLEN - 25;
 
function getStdLogicVectorZeroes(int : in integer) return std_logic_vector;
end TinyXconfig;
 
package body TinyXconfig is
function getStdLogicVectorZeroes(int : in integer) return std_logic_vector is
variable result : std_logic_vector(int -1 downto 0);
begin
for index in result'range loop
result(index) := '0';
end loop;
return result;
end getStdLogicVectorZeroes;
end TinyXconfig;
/trunk/mux8.vhd
0,0 → 1,38
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
use work.TinyXconfig.ALL;
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity mux8 is
Port ( ina : in cpuWord;
inb : in cpuWord;
inc : in cpuWord;
ind : in cpuWord;
ine : in cpuWord;
inf : in cpuWord;
ing : in cpuWord;
inh : in cpuWord;
mout : out cpuWord;
sel : in std_logic_vector(2 downto 0));
end mux8;
 
architecture Behavioral of mux8 is
begin
mx8: for i in ina'range generate
mout(i) <= (ina(i) and (not sel(2)) and (not sel(1)) and (not sel(0))) or
(inb(i) and (not sel(2)) and not sel(1) and ( sel(0))) or
(inc(i) and (not sel(2)) and sel(1) and (not sel(0))) or
(ind(i) and (not sel(2)) and sel(1) and sel(0) ) or
(ine(i) and sel(2) and (not sel(1)) and (not sel(0))) or
(inf(i) and sel(2) and not sel(1) and ( sel(0))) or
(ing(i) and sel(2) and sel(1) and (not sel(0))) or
(inh(i) and sel(2) and sel(1) and sel(0) );
end generate;
end Behavioral;
 
/trunk/cctest.vhd
0,0 → 1,62
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity cctest is
Port ( fN : in std_logic;
fV : in std_logic;
fC : in std_logic;
fZ : in std_logic;
what : in std_logic_vector(3 downto 0);
result : out std_logic);
end cctest;
 
architecture Behavioral of cctest is
 
begin
process(what, fN, fV, fC, fZ)
begin
case what is
when "0000" => -- ever true
result <= '1';
when "0001" => -- carry clear
result <= not fC;
when "0010" => -- carry set
result <= fC;
when "0011" => -- zero set
result <= fZ;
when "0100" => -- greater equal
result <= (fN and fV) or (not fN and not fV);
when "0101" => -- greater than
result <= (fN and fV and not fZ) or (not fN and not fV and not fZ);
when "0110" => -- higher
result <= not fC and not fZ;
when "0111" => -- less equal
result <= fZ or (fN and not fV) or (not fN and fV);
when "1000" => -- less
result <= fC or fZ;
when "1001" => -- less than
result <= (fN and not fV) or (not fN and fV);
when "1010" => -- minus
result <= fN;
when "1011" => -- zero clear
result <= not fZ;
when "1100" => -- plus
result <= not fN;
when "1101" => -- overflow clear
result <= not fV;
when "1110" => -- overflow set
result <= fV;
when "1111" => -- ever false
result <= '0';
when others =>
result <= '0';
end case;
end process;
end Behavioral;
/trunk/irBits.txt
0,0 → 1,83
cctest: 31..28
0000 ever true always
0001 carry clear CC
0010 carry set CS
0011 zero set EQ
0100 greater equal GE
0101 greater than GT
0110 higher HI
0111 less equal LE
1000 less LS
1001 less than LT
1010 minus MI
1011 zero clear NE
1100 plus PL
1101 overflow clear VC
1110 overflow set VS
1111 ever false never
 
alumode: 27..24
0000 mov
0001 and
0010 or
0011 xor
0100 add
0101 sub
0110 ror
0111 lsr
1000 lsra
1001 swap
1010 swapb
1011 inc
1100 dec
1101 rorb
 
memmux: 23
0 use aluresult
1 use memory
 
clkmux: 22..20
000 R0
001 R1
010 R2
011 R3
100 R4
101 R5
110 R6
111 R7
 
drive data bus: 19
0 not drive data bus
1 drive databus from opamux
 
opamux: 18..16
000 R0
001 R1
010 R2
011 R3
100 R4
101 R5
110 R6
111 R7
 
valmux: 15
0 use opbmux
1 use immediate
 
opbmux: 14..12
000 R0
001 R1
010 R2
011 R3
100 R4
101 R5
110 R6
111 R7
 
flagupdate: 11
0 not change flag
1 change flag
 
carry use: 10
0 not use carry
1 use carry
/trunk/TinyX.vhd
0,0 → 1,251
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
use work.TinyXconfig.ALL;
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity TinyX is
Port ( dataout : out cpuWord;
datain : in cpuWord;
adr : out std_logic_vector(15 downto 0);
wrn : out std_logic;
rdn : out std_logic;
clock : in std_logic;
clrn : in std_logic);
end TinyX;
 
architecture Behavioral of TinyX is
 
constant CPU_S0 : std_logic_vector(1 downto 0) := "00";
constant CPU_S1 : std_logic_vector(1 downto 0) := "01";
constant CPU_S2 : std_logic_vector(1 downto 0) := "10";
 
signal r0 : cpuWord; -- register 0
signal r1 : cpuWord; -- register 1
signal r2 : cpuWord; -- register 2
signal r3 : cpuWord; -- register 3
signal r4 : cpuWord; -- register 4
signal r5 : cpuWord; -- register 5
signal r6 : cpuWord; -- register 6
signal r7 : cpuWord; -- register 7 AND PROGRAM COUNTER !!!
signal imm : cpuWord;
signal abus : cpuWord; -- bus to alu opa and tristate buffer input
signal bbus : cpuWord; -- bus from valmux to alu opb
signal adrbus : cpuWord;
signal dstbus : cpuWord; -- from memmux to register bank
signal result : cpuWord; -- from alu res to memmux
signal carryIn : std_logic; -- carry to alu
signal flagC : std_logic;
signal flagZ : std_logic;
signal flagV : std_logic;
signal flagN : std_logic;
signal regC : std_logic; -- registered carry flag
signal regZ : std_logic; -- registered zero flag
signal regV : std_logic; -- registered overflow flag
signal regN : std_logic; -- registered negaive flag
signal aluMode : std_logic_vector(3 downto 0);
signal ccMode : std_logic_vector(3 downto 0);
signal flagBit : std_logic; -- result of condition code comparision
signal cpuState : std_logic_vector(1 downto 0); -- CPU state counter
signal carryUse : std_logic;
signal flagUpdate : std_logic;
signal writeCycle : std_logic;
signal dstclk : std_logic_vector(2 downto 0);
signal sela : std_logic_vector(2 downto 0);
signal selb : std_logic_vector(2 downto 0);
signal selm : std_logic;
signal selv : std_logic;
 
component cctest port ( fN : in std_logic;
fV : in std_logic;
fC : in std_logic;
fZ : in std_logic;
what : in std_logic_vector(3 downto 0);
result : out std_logic);
end component;
 
component ALU Port ( opa : in cpuWord;
opb : in cpuWord;
res : out cpuWord;
cin : in std_logic;
cout : out std_logic;
zero : out std_logic;
sign : out std_logic;
over : out std_logic;
what : in std_logic_vector(3 downto 0));
end component;
 
component mux2 Port ( ina : in cpuWord;
inb : in cpuWord;
mout : out cpuWord;
sel : in std_logic);
end component;
 
component mux8 Port ( ina : in cpuWord;
inb : in cpuWord;
inc : in cpuWord;
ind : in cpuWord;
ine : in cpuWord;
inf : in cpuWord;
ing : in cpuWord;
inh : in cpuWord;
mout : out cpuWord;
sel : in std_logic_vector(2 downto 0));
end component;
 
begin
 
assert XLEN > 31 report "XLEN must at least 32 and multiple of 8";
assert (XLEN rem 8) = 0 report "XLEN must at least 32 and multiple of 8";
--####### condition code comparison ##################################################
flagger : cctest port map(regN, regV, regC, regZ, ccMode, flagBit);
 
carryIn <= regC and carryUse;
--####### alu processing #############################################################
alucell : ALU port map(abus, bbus, result, carryIn, flagC, flagZ, flagN, flagV, aluMode);
 
--####### multiplexor opamux #########################################################
opamux : mux8 port map(r0, r1, r2, r3, r4, r5, r6, r7, abus, sela);
 
--####### multiplexor opbmux #########################################################
opbmux : mux8 port map(r0, r1, r2, r3, r4, r5, r6, r7, adrbus, selb);
 
--####### multiplexor valmux #########################################################
valmux : mux2 port map(adrbus, imm, bbus, selv);
 
--####### multiplexor memmux #########################################################
memmux : mux2 port map(result, datain, dstbus, selm);
 
adr <= adrbus(15 downto 0); -- drive the address bus asynchronusly
dataout <= abus; -- also the dataout bus
 
process (clock, clrn)
begin
if clrn = '0' then -- reset the CPU
cpuState <= CPU_S0;
r0 <= getStdLogicVectorZeroes(XLEN);
r1 <= getStdLogicVectorZeroes(XLEN);
r2 <= getStdLogicVectorZeroes(XLEN);
r3 <= getStdLogicVectorZeroes(XLEN);
r4 <= getStdLogicVectorZeroes(XLEN);
r5 <= getStdLogicVectorZeroes(XLEN);
r6 <= getStdLogicVectorZeroes(XLEN);
r7 <= getStdLogicVectorZeroes(XLEN); -- set pc to starting address
-- feed the multiplexors
sela <= "111";
selb <= "111";
selv <= '0';
selm <= '0';
carryUse <= '0';
 
ccMode <= "0000";
aluMode <= "0000";
regN <= '0';
regV <= '0';
regC <= '0';
regZ <= '0';
wrn <= '1'; -- read access
rdn <= '0';
else -- normal operation of CPU
if clock'event and clock = '1' then -- rising clock edge
case cpuState is
when CPU_S0 => --####### S0 #######################################
ccMode <= datain(ccModeLeft downto ccModeRight);
aluMode <= datain(aluModeLeft downto aluModeRight);
selm <= datain(memmuxBit);
dstclk <= datain(dstClkLeft downto dstClkRight);
writeCycle <= datain(writeCycleBit);
sela <= datain(opamuxLeft downto opamuxRight);
selv <= datain(valmuxBit);
selb <= datain(opbmuxLeft downto opbmuxRight);
flagUpdate <= datain(flagUpdateBit);
carryUse <= datain(carryUseBit);
imm <= "000000000000000000000000" & datain(immediateLeft downto 0);
if datain(writeCycleBit) = '0' then
rdn <= '0';
wrn <= '1';
else
rdn <= '1';
wrn <= '0';
end if;
cpuState <= CPU_S1;
when CPU_S1 => --####### S1 #######################################
-- latch the alu result and the flags
if writeCycle = '0' then
if flagUpdate = '1' then
regC <= flagC;
regZ <= flagZ;
regV <= flagV;
regN <= flagN;
end if;
if flagBit = '1' then -- save the alu result, only at read cycle ???
case dstclk is -- select destination register
when "000" =>
r0 <= dstbus;
when "001" =>
r1 <= dstbus;
when "010" =>
r2 <= dstbus;
when "011" =>
r3 <= dstbus;
when "100" =>
r4 <= dstbus;
when "101" =>
r5 <= dstbus;
when "110" =>
r6 <= dstbus;
when "111" =>
r7 <= dstbus;
when others =>
r0 <= dstbus;
end case; -- destination register selection
end if; -- flagBit
end if;
rdn <= '0';
wrn <= '1';
-- drive the adr bus, set read pulse
carryUse <= '0';
ccMode <= "1111";
aluMode <= "1011";
sela <= "111";
selb <= "111"; -- pc to adr bus
selv <= '0';
selm <= '0';
cpuState <= CPU_S2;
when CPU_S2 => --####### S2 #######################################
r7 <= dstbus; -- store incremented pc
-- data bus drives the muxes and enables
ccMode <= datain(ccModeLeft downto ccModeRight);
aluMode <= datain(aluModeLeft downto aluModeRight);
selm <= datain(memmuxBit);
dstclk <= datain(dstClkLeft downto dstClkRight);
writeCycle <= datain(writeCycleBit);
sela <= datain(opamuxLeft downto opamuxRight);
selv <= datain(valmuxBit);
selb <= datain(opbmuxLeft downto opbmuxRight);
flagUpdate <= datain(flagUpdateBit);
carryUse <= datain(carryUseBit);
imm <= "000000000000000000000000" & datain(immediateLeft downto 0);
if datain(writeCycleBit) = '0' then
rdn <= '0';
wrn <= '1';
else
rdn <= '1';
wrn <= '0';
end if;
cpuState <= CPU_S1;
when others =>
cpuState <= CPU_S0;
end case; -- cpuState
end if; -- rising clock edge
end if; -- clrn = 0
end process; -- clock, clrn
end Behavioral;
 
/trunk/mux2.vhd
0,0 → 1,25
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
use work.TinyXconfig.ALL;
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity mux2 is
Port ( ina : in cpuWord;
inb : in cpuWord;
mout : out cpuWord;
sel : in std_logic);
end mux2;
 
architecture Behavioral of mux2 is
begin
mx2: for i in ina'range generate
mout(i) <= (ina(i) and (not sel)) or (inb(i) and sel);
end generate;
end Behavioral;
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.