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; |
|