[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [oc] Open Core Forth Processor
----- Original Message -----
From: "Don Golding" <dgolding@a... >
To: <cores@o... >
Date: Thu, 24 Feb 2000 09:39:23 -0000
Subject: [oc] Open Core Forth Processor
> -- Don Golding
>
> -- Angelus Research Corp.
>
> -- dgolding@a...
>
> -- Version 3
>
> -- Forth Processor Design
>
> --
>
> -- This code represents my current thoughts on designing a Forth
> Processor in VHDL.
>
> -- Please review it and email me with your input on either Forth
> design issues or
>
> -- VHDL design issues.
>
> --
>
> -- The goal is to build a generic Forth processor that can be
> included in VHDL designs.
>
> -- If it could fit into a Xilinx 4005 or 4010 it would be ideal!
>
> -- Forth is really a virtual microprocessor implemented on other
> various processors
>
> -- from 68HC11 to VAX machines and supercomputers. You will
> currently find Forth used
>
> -- as the driver for PCI hardware in high end Macintosh's and Sun
> Workstations.
>
> --
>
> -- This is an attempt to create a real Forth Processor on an FPGA
> or ASIC using VHDL.
>
> -- Previous real Forth Microprocessors include: Harris RTX2000,
> SHABOOM, F21,etc.
>
> -- The current attempts F21, etc. are trying to make 500mips
> screamers.
>
> -- There are also people like Dr. Ting using the Schematic editor
> to create Forth
>
> -- processors. I wonder how a Schematic designed Forth processor
> will compare to a VHDL
>
> -- based design in speed and the number of gates used.
>
>
>
> -- I think a straight forward simple design will have considerable
> applications
>
> -- when you need a processor included in your FPGA/ASIC design.
>
> -- FPGA operate at 200mhz, I don't know how fast this design will
> be, but it's speed
>
> -- should be limited to the external RAM speed when memory access
> is required.
>
> -- Internal register to register operations should be 50-200mhz
> range.
>
> --
>
> -- The preliminary specifications are:
>
> --
>
> -- 16 bit data bus (to save space, could be 8 bit but it would take
> more statements)
>
> -- 16 bit address bus
>
> -- by editing the code in the Entity declariations, you implement
> 32, 64, ? designs
>
> --
>
> -- Return Stack levels=16
>
> -- Data Stack levels=16 (could be smaller, 4 items could be ok)
>
> -- Output port A is 8 lines
>
> -- Output port B is 8 lines
>
> -- Motorola SPI compatible port (SPI_In,SPI_Out,SPI_Ck,SS/)
>
> --
>
> -- By editing the code in the Entity declariations, you can add
> serial ports, parallel
>
> -- ports, adc's or just about anything you can imagine.
>
> --
>
>
>
> library IEEE;
>
> use IEEE.std_logic_1164.all;
>
>
>
> entity Proc is
>
> port (
>
> DataBus: inout STD_LOGIC_VECTOR (15 downto 0);
>
> OutPortA: out STD_LOGIC_VECTOR (7 downto 0);
>
> OutPortB: out STD_LOGIC_VECTOR (7 downto 0);
>
> OutputA: out STD_LOGIC_LOGIC;
>
> OutputB: out STD_LOGIC_LOGIC;
>
> AddressBus: out STD_LOGIC_VECTOR (15 downto 0);
>
> Reset: in STD_LOGIC;
>
> SPI_In: in STD_LOGIC;
>
> SPI_Out: out STD_LOGIC;
>
> SS: in STD_LOGIC;
>
> SPI_Ck: in STD_LOGIC;
>
> clock: in STD_LOGIC;
>
> rd: out STD_LOGIC;
>
> );
>
> end Proc;
>
>
>
> architecture Proc_arch of Proc is
>
>
>
> --define op codes, only 25 so far...
>
> type op_code is(abort, depth, dup, pick, over, swap, >r, r>,
> r@, drop,
>
> rot, equal, zero_equal, greater, greater_than,
>
> less_than, store, +store, fetch, plus, minus, times
>
> divide, branch, Obranch );
>
>
>
> -- check these for correct sizes
>
> type data_word is array(15 downto 0) of STD_ULOGIC; --16 bit wide
>
> type Return_stack is array (15 downto 0) of data_word; --16 bits
> wide, 16 deep
>
> type Data_stack is array (15 downto 0) of data_word; --16 bits
> wide, 16 deep
>
> type memory_size is range (15 downto 0); --64K max?
>
>
>
> constant stack_depth: integer:=16; --16 items max
>
>
>
> variable rp of stack_depth; -- return stack pointer
>
> variable dp of stack_depth; -- data stack pointer
>
> variable mp of memory_size; -- memory pointer
>
> variable temp1 of data_word; -- reg:Temp1 internal
>
> variable error of data_word; -- reg:Error code
>
> variable sucessful of bit; -- Flag:operation sucessful
>
>
>
> constant dstack_start:integer:=0;
>
> constant write:bit:=0;
>
> constant read:bit:=1;
>
> constant dstack_overflow:integer:=1; --Errorcodes are defined here
>
> constant dstack_underflow:integer:=2;
>
> constant rstack_overflow:integer:=3;
>
> constant rstack_underflow:integer:=4;
>
> constant invalid_instruction:integer:=5;
>
>
>
> --Forth stack manipulation primitives
>
> --I think we should implement a circular que here.
>
> --data_stack(dp) points to next available location, can use as
> temp variable
>
> --before using push_dp_stack or pop_dp_stack procedures.
>
> --each stack are really 16 registers! Stack operations should be
> real fast!
>
>
>
> procedure reset_proc is
>
>
>
> begin
>
>
>
> dp <= '0';
>
> rp <= '0';
>
> mp <= '0';
>
>
>
> end reset_proc;
>
>
>
> procedure push_dp_stack is
>
> -- dp points the the next stack element not the current one after
> operation is completed.
>
>
>
> begin
>
>
>
> if dp = stack_depth then
>
> error<=dstack_overflow;
>
> reset_proc;
>
> else dp <= dp+1;
>
> end if
>
> end push_dp_stack;
>
>
>
> procedure pop_dp_stack is
>
> -- dp points the the next stack element not the current one after
> operation is completed.
>
> begin
>
>
>
> if dp = dstack_start then
>
> error<=dstack_underflow;
>
> reset_proc;
>
> else dp <= dp-1;
>
> end if
>
> end pop_dp_stack;
>
>
>
> procedure push_rp_stack is
>
> -- dp points the the next stack element not the current one after
> operation is completed.
>
>
>
> begin
>
>
>
> if rp = 16 then
>
> error<=rstack_overflow;
>
> reset_proc;
>
> else rp <= rp+1;
>
> end if
>
> end push_rp_stack;
>
>
>
> procedure pop_rp_stack is
>
> -- dp points the the next stack element not the current one after
> operation is completed.
>
>
>
> begin
>
>
>
> if rp = 0 then
>
> error<=rstack_underflow;
>
> reset_proc;
>
> else rp <= rp-1;
>
> end if
>
> end pop_rp_stack;
>
>
>
> procedure proc_code(sucessful) is --is the parameter list ok?
>
>
>
> begin
>
>
>
> sucessful<=true;
>
> case data_bus is
>
>
>
> when abort => --reset processor
>
>
>
> reset_proc;
>
>
>
> when depth => --put the depth of the stack on the top
>
>
>
> data_stack(dp) <= dp;
>
> up_data_stack;
>
>
>
> when dup => --duplicate the top item on data stack
>
>
>
> data_stack(dp)<=data_stack(dp+1);
>
> up_data_stack;
>
>
>
> when pick => --get on data stack pointed to by TOS
>
>
>
> data_stack(dp)<=data_stack(data_stack(dp+1);
>
> up_data_stack;
>
>
>
> when over => --duplicate the second number on data stack
>
>
>
> data_stack(dp) <= data_stack(data_stack(dp+2);
>
> up_data_stack;
>
>
>
> when swap => --swap top two numbers on data stack
>
>
>
> return_stack(rp) <= data_stack(dp+1);
>
> data_stack(dp+1) <= data_stack(dp+2);
>
> data_stack(dp+2) <= return_stack(rp);
>
>
>
> when >r => --move top of data stack to return stack
>
>
>
> return_stack(rp) <= data_stack(dp+1);
>
> pop_data_stack;
>
> push_return_stack;
>
>
>
> when r> => --move top of return stack to data stack
>
>
>
> data_stack(dp+1) <= return_stack(rp+1);
>
> pop_return_stack;
>
> push_data_stack;
>
>
>
> when r@ => --move top of return stack to data stack
>
>
>
> data_stack(dp) <= return_stack(rp+1);
>
> push_data_stack;
>
>
>
> when drop => --drop top number from data stack
>
>
>
> pop_dp_stack;
>
>
>
> when rot => --rotate 3rd numbr to 1st on data stack
>
>
>
> return_stack(rp) <= data_stack(dp+1);
>
> data_stack(dp+1) <= data_stack(dp+3);
>
>
>
> when equal => -- if tos and second are equal then true
>
>
>
> if data_stack(dp+1)=data_stack(dp+2) then
>
> pop_data_stack;
>
> data_stack(dp+1)<='1';
>
> end if;
>
>
>
> when zero_equal => -- if tos=0 then tos=true
>
>
>
> if data_stack(dp+1)='0' then
>
> data_stack(dp+1)<='1';
>
> end if;
>
>
>
>
>
> when greater_than => -- if tos is greater then the sec then
> tos=true
>
>
>
> if data_stack(dp+1)>data_stack(dp+2) then
>
> pop_data_stack;
>
> data_stack(dp+1)<='1';
>
> end if;
>
>
>
> when less_than => -- if tos is less than the second item then
> tos=true
>
>
>
> if data_stack(dp+1)<data_stack(dp+2) then
>
> pop_data_stack;
>
> data_stack(dp+1)<='1';
>
> end if;
>
>
>
> when store => -- store 16 bit value to memory
>
>
>
> rd<=write;
>
> addressBus <= data_stack(dp+1);
>
> dataBus <= data_stack(dp+2)
>
> rd<=read; -- probably need a delay here
>
> pop_data_stack;
>
> pop_data_stack;
>
>
>
> when +store => -- increment 16 bit value in memory
>
>
>
> rd<=read;
>
> addressBus <= data_stack(dp+1);
>
> data_bus <= data_bus+data_stack(dp+1);
>
> rd<=write;
>
> pop_data_stack;
>
> pop_data_stack;
>
> rd<=read; -- probably need a delay here
>
>
>
> when fetch => -- get 16 bit value from memory
>
> rd<=read;
>
> data_stack(dp) <= dataBus;
>
> push_data_stack;
>
>
>
> when plus => --add two 16 bit numbers
>
> data_stack(dp+1) <= data_stack(dp+2) + data_stack(dp+1);
>
> pop_data_stack;
>
>
>
> when minus => --subtract two 16 bit numbers
>
> data_stack(dp+2) <= data_stack(dp+1) - data_stack(dp+2);
>
> pop_data_stack;
>
>
>
> when times => --multiply two 16 bit numbers
>
> data_stack(dp+2) <= data_stack(dp+1) * data_stack(dp+2);
>
> pop_data_stack;
>
>
>
> when divide => --divide two 16 bit numbers
>
> data_stack(dp+2) <= data_stack(dp+1) / data_stack(dp+2);
>
> pop_data_stack;
>
>
>
> when branch => --branch unconditionally
>
> mp=mp+1;
>
> rd<=read;
>
> mp=DataBus;
>
>
>
> when Obranch => --branch if tos = 0
>
> if data_stack(dp+1)='0' then
>
> mp=mp+1;
>
> rd<=read;
>
> mp=DataBus;
>
> end if;
>
>
>
> when others => -- not an opcode
>
> sucessful<=false;
>
> end case;
>
> end proc_code;
>
>
>
> synch: process(clock)
>
>
>
> begin
>
> if clock'event and clock='1' then
>
> clock<= not clock; -- need a delay here?
>
> end if;
>
> end process;
>
>
>
> code: process(clock,reset,mp,rp)
>
> begin
>
>
>
> if reset ='0' then
>
> reset_proc;
>
>
>
> else --get and process instruction
>
>
>
> rd<=read; --set read/write line to read
>
> addressBus<=mp; --output address
>
>
>
> proc_code;
>
>
>
> --Forth's inner interpreter(next)
>
> if sucessful=true then -- it was a valid instruction
>
> mp <= mp+1;
>
> sucessful<=false;
>
> else -- it wasn't a valid instruction
>
> error<=invalid_instruction;
>
> reset_proc;
>
> --
>
> end if;
>
>
>
> end if;
>
>
>
> end process;
>
> end Proc_arch;
>
>
>
>
>
>
>
>
>
--
To unsubscribe from cores mailing list please visit http://www.opencores.org/mailinglists.shtml