URL
https://opencores.org/ocsvn/tisc/tisc/trunk
Subversion Repositories tisc
[/] [tisc/] [web_uploads/] [TISC.VHD] - Rev 6
Compare with Previous | Blame | View Log
-- Tiny Instruction Set (TISC) VHDL CPU Core-- Copyright Vincent Crabtree, 15th Nov 2001---- My first attempt at processor design, thanks to :--- Tim Boscke - CPU8BIT2, Rockwell - 6502, Microchip - Pic-- Jien Chung Lo - EL405 , Steve Scott - Tisc,-- Giovanni Moretti - Intro to Asm-- Uses 12 bit program word, and 8 bit data memory-- 2 reg machine,accumulator based, with akku and index regs-- Harvard architecture, uses return x so as to eliminate need of pmem-- indirect instructions like 8051.-- pc is 10 bits, akku and idx are 8 bit.-- Has carry and zero flags,-- three addressing modes:- immediate, indirect and reg.-- seperate program and data memory for pipelining later...-- Instructions coded as thus:--- Long instructions first - program jump.-- Both store return address for subroutine calls, 1 deep stack.-- 0 0 xxxxxxxxxx jc pmem10 ; if c==1, stack = pc, pc <- pmem10, fi-- 0 1 xxxxxxxxxx jz pmem10 ; if z==1, stack = pc, pc <- pmem10, fi-- Immediate ops-- bits 9 and 8 select what to do-- 1 00 0 xxxxxxxx lda #imm8 ; a= imm8, c=0,-- 1 00 1 xxxxxxxx ret #imm8 ; a= imm8, pc = stack-- 1 01 0 xxxxxxxx adc #imm8 ; add with carry imm8, cy and z set-- 1 01 1 xxxxxxxx adx #imm8 ; add imm8 to idx reg, z=(a==0)-- Indirect and alu ops-- bit 9 selects indirect or alu ops-- Indirect - bits 7 and 8 select what to do-- 1 10 0 0 xxxxxxx lda [ix] ; load a indirect data mem-- 1 10 0 1 xxxxxxx sta [ix] ; store a indirect data mem-- register register-- 1 10 1 0 xxxxxxx tax ; x = a,-- 1 10 1 1 xxxxxxx txa ; a = x-- Arithmetic ops use indirect addressing-- all alu ops indirect, bits 7 and 8 select alu op.-- 1 11 00 xxxxxxx add a,[ix] ; add with carry-- 1 11 01 xxxxxxx sub a,[ix] ; a = a + ~[idx], inc a after for proper subtract-- 1 11 10 xxxxxxx and a,[ix] ; and mem contents into a-- 1 11 11 xxxxxxx nor a,[ix] ; nor-- States.-- 000 instruction decode-- 010 load a indirect - lda [ix]-- 011 stor a indirect - sta [ix]-- 100 add a,[ix]-- 101 sub a,[ix[-- 110 and a,[ix]-- 111 nor a,[ix]library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all; -- has adder built inentity tisc isport(-- bus-- db only 8 bits wide on dmem side, 12 on pmem side.data : inout std_logic_vector(11 downto 0);address : out std_logic_vector(9 downto 0);-- control - active lowrd : out std_logic; -- dramwr : out std_logic; -- drampsen : out std_logic; -- pmem-- machine controlclock : in std_logic;reset : in std_logic);end;architecture cpu_arch of tisc is-- Program controlsignal stack : std_logic_vector(9 downto 0); -- stack, 1 deepsignal pc : std_logic_vector(9 downto 0); -- program counter-- Registerssignal akku : std_logic_vector(8 downto 0); -- accumulator, cy is bit 8signal idx : std_logic_vector(7 downto 0); -- index regsignal z : std_logic; -- zero flag-- ALU controlssignal aluout : std_logic_vector(9 downto 0); -- alu resultsignal temp : std_logic_vector(8 downto 0); -- temp storage for alusignal aludest : std_logic_vector(1 downto 0); -- output mux alusignal aluop : std_logic_vector(1 downto 0); -- alu operationsignal aluinput : std_logic_vector(9 downto 0); -- input to alu-- machine controlsignal states : std_logic_vector(2 downto 0); -- state controllerbegin -- start logic declerationprocess(clock,reset) -- sequential sectionbegin-- check if reset or notif(reset = '0' ) then -- async reset parameters-- how do I stop the annoying async error?pc <= (others => '0');-- resetstates <= (others => '0'); -- decode sub statealudest <= "01"; -- reset destination destelsif rising_edge(clock) then -- actual machine-- check state machine for indirect alu opsif( states(2) = '1') thenif( states(1 downto 0) = "01") then --sub add indtemp <= "0" & (Not data(7 downto 0));elsetemp <= "0" & data(7 downto 0);end if;aluop <= states(1 downto 0); -- 00 adc indirect-- 01 not add ind-- 10 and indirect-- 11 nor indirect-- sort out muxers for alualudest <= "00"; -- akku destinationstates <= "000"; -- decodeelse-- States decodecase states(1 downto 0) is -- action dependent on stateswhen "00" => -- instruction decode-- increment pc firsttemp <= "000000001"; -- incaludest <= "10"; -- pc and increment and idlepc <= aluout; -- get result-- Now decode instr on data bus-- sort out jz or jcif( (data(11) = '0') and -- top bit nought, sio a jump...( ((akku(8) = '1') and (data(10) = '0')) or -- JC((z='1') and (data(10)='1'))) ) then -- Jzstack <= pc; --return stackpc <= data(9 downto 0);-- states already at decodeelse -- top bit is one, so not a jump instruction...case data(10 downto 9) iswhen "01" => -- adc #imm/adx #immtemp <= "0" & data(7 downto 0);aluop <= "01"; -- addaludest <= data(8) & data(8) ; --00 is akku, 11 is idx-- states already at decodewhen "00" => -- lda #imm/ret #imm clear cyif( data(8) = '1' ) then -- ret ##immpc <= stack;end if;akku <= "0" & data(7 downto 0);-- states already at decodewhen "10" => -- lda/store or reg/regif( data(8) = '1') then -- ld ind /store indstates <= "01" & data(7);-- "010";-- reg/regelsif( data(7) = '0') then -- taxidx <= akku(7 downto 0);else -- txaakku <= "0" & idx(7 downto 0);end if;-- states already at decodewhen "11" => -- add ind, andstates <= "1" & data(8 downto 7); -- "100"; -- add/sub ind-- "110"; -- and/nor indwhen others =>states <= "000"; -- if non of above, decode/nopend case; -- end of instruction decodeend if; -- jump ifwhen "10" => -- lda [ix] - buses should be setupakku <= "0" & data(7 downto 0);states <= "000"; -- decodewhen "11" => -- sta [ix]-- akku placed on data bus nowstates <= "000"; -- decodewhen others =>states <= "000"; -- decodeend case; -- end of state decodeend if; -- end of alu indirect ifend if; -- rising edge if-- Sort out alu ops and source/destination regscase aludest iswhen "00" => -- destination is aluakku <= aluout(8 downto 0);when "11" => -- alu destination is idxidx <= aluout(7 downto 0);when others => null;end case; -- end of dest decodeend process; -- end sequential section-- concurrent sectionz <= '1' when akku = "000000000" and reset='1' else '0'; -- nice nand here-- alu input muxerwith aludest selectaluinput <= ("0" & akku) when "00",("00" & idx) when "11",pc when "10",("0" & temp) when others;-- Decode and perform arithmetic opswith aluop selectaluout <= aluinput + ("0" & temp) when "01", -- addaluinput and ("0" & temp) when "10", -- andaluinput nor ("0" & temp) when "11", -- nornot ("0" & temp) when others; -- any use?-- assign pinsaddress <= pc when states = "000" else "00"&idx;data <= ("000" & akku) when states = "011" else "ZZZZZZZZZZZZ";psen <= '0' when states="000" else '1'; -- pmem readrd <= '0' when (states(2)='1') or (states="010") else '1'; -- dmem readwr <= '0' when states="011" else '1'; -- dmem writeend cpu_arch;
