Прикидка на VHDL, которая у меня получилась:
Код:
-- version of 12 april 2010
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_unsigned.all;
--Minimal instruction Forth Computer
--
--MIFC16
--
--0 NOP выборка следующей команды (нет операции)
--1 ?BRANCH (IFNZ) переход, если на стеке не ноль
--2 LIT загрузка непосредственного литерала на стек ( --> data )
--3 @ извлечь данное по адресу из стека ( addr --> data=mem[addr])
--4 ! сохранить даное в памяти по адресу ( data, addr --> )
--5 CALL вызов попрограммы ( вызов адресного интерпретатора)
--6 RET возврат из подпрограммы
--7 DUP дублирование данного с вершины стека ( d --> d d)
--8 DROP удаление данного с вершины стека ( d --> )
--9 SWAP перестановка двух элементов на вершине стека ( d1 d2 --> d2 d1)
--10 OVER копирование второго элемента стека ( d1 d2 --> d2 d1 d2)
--11 AR> переместить данное со стека данных на стек возвратов ( adr --> )
--12 A>R переместить данное со стека возвратов на стек данных ( --> adr)
--13 NAND поразрядное логическое "И-НЕ" двух верхних элементов стека ( d1 d1 --> d1 nand d2)
--: NOT DUP NAND ; поразрядное логическое инвертирование верхнего элемента стека (d --> not d)
--: OR NOT SWAP NOT NAND ; поразрядное логическое "ИЛИ" двух верхних элементов стека ( d1 d1 --> d1 or d2 )
--: AND NAND DUP NAND ; поразрядное логическое "И" ( d1 d1 --> d1 and d2 )
--: XOR OVER OVER NAND DUP >R NAND SWAP R> NAND NAND ; поразрядное "Исключающее ИЛИ" ( d1 d1 --> d1 xor d2)
--14 ADD сложить два верхних элемента стека (d1 d1 --> d1+d2)
--15 2/ разделить верхний элемент стека на 2 ( d --> d/2)
--: 2* DUP ADD ;
entity mifc16 is
GENERIC ( widtX : integer :=16 );
Port(
clk : in std_logic;
ready : in std_logic := '1';
reset : in std_logic := '1';
di : in std_logic_vector (WidtX-1 downto 0);
adr : out std_logic_vector (WidtX-1 downto 0);
do : out std_logic_vector (WidtX-1 downto 0);
test_Cmd : out std_logic_vector (3 downto 0);
test_Trigg : out std_logic;
test_DStDo : out std_logic_vector (WidtX-1 downto 0);
test_RStDo : out std_logic_vector (WidtX-1 downto 0);
cs_RAM,wr_RAM,rd_RAM,Out_ena : out std_logic
);
END mifc16;
ARCHITECTURE RTL OF mifc16 IS
type wait_mashine is (Work1, Wait1, Wait2);
subtype T_data is std_logic_vector (WidtX-1 downto 0);
signal RStcmd : std_logic_vector (1 downto 0);
signal RStDi : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal RStDo : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal DStcmd : std_logic_vector (1 downto 0);
signal DStDi : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal DStDo : T_data; -- std_logic_vector (WidtX-1 downto 0);
constant STnop : std_logic_vector (1 downto 0) := "00";
constant STpush : std_logic_vector (1 downto 0) := "01";
constant STpop : std_logic_vector (1 downto 0) := "10";
constant STswap : std_logic_vector (1 downto 0) := "11";
signal STM : wait_mashine;
signal ENA : std_logic;
signal stw : std_logic_vector (3 downto 0);
signal rst1 : std_logic;
signal cmdS : std_logic_vector (3 downto 0);
signal cmdr : T_data;
signal NEWcmdr : T_data;
signal zero : T_data;
signal CMD4shr : T_data;
signal WrRAM : std_logic;
signal RdRAM : std_logic;
signal CsRAM : std_logic;
signal PC : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal newPC : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal TR : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal newTR : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal alux : T_data; -- std_logic_vector (WidtX-1 downto 0);
signal mul_res : std_logic_vector (WidtX+WidtX-1 downto 0);
signal Trigg,NewTrigg : std_logic;
-- внутренний WAIT - '0' - команда исполняется за один такт, иначе - не меньше 3-х
signal IntWait : std_logic;
COMPONENT Stack IS
GENERIC ( WidtX : integer :=16; depth : integer :=3);
Port ( clk : in std_logic;
cmd : in std_logic_vector (1 downto 0);
di : in std_logic_vector (widtX-1 downto 0);
do : out std_logic_vector (widtX-1 downto 0);
ena : in std_logic
);
END COMPONENT;
BEGIN
stack_dd: stack
GENERIC MAP ( widtX => WidtX, depth => 8 )
PORT MAP (clk,DSTcmd,DSTdo,DSTdi,ENA);
stack_rr: stack
GENERIC MAP ( widtX => WidtX, depth => 8 )
PORT MAP (clk,RSTcmd,RSTdo,RSTdi,ENA);
zero <= (others => '0');
-- command register 4-bit shifted
CMD4shr(widtX-5 downto 0) <= (cmdr(widtX-1 downto 4));
CMD4shr(widtX-1 downto widtX-4)<=zero(widtX-1 downto widtX-4);
-- REGISTERS and RESET SHEME
process (clk,ena) begin
if (CLK'event and CLK='1' and ENA='1' ) then
if rst1 = '0' then
cmdr <= zero;
PC <= zero;
TR <= newTR;
Trigg <= '0';
else
cmdr <= NEWcmdr;
PC <= newPC;
TR <= newTR;
Trigg <= NewTrigg;
end if;
end if;
end process;
-- !!! WAIT MACHINE !!!
process (clk,STM) begin
if (CLK'event and CLK='1' ) then
if reset = '0' then
STM <= Work1; ENA <= '1'; stw <= (others => '0');
rst1 <= '0';
else
rst1 <= '1';
case STM is
when Work1 => if (IntWait = '1') then STM <= Wait1; ENA <= '0'; stw <= zero (3 downto 0) + 1; else
STM <= Work1; ENA <= '1'; stw <= zero (3 downto 0); end if;
when Wait1 => if (stw = 1) then stw <= zero (3 downto 0) + 1; else stw <= stw - 1; end if; ENA <= '0';
if ((stw = 1) and ready = '1') then STM <= Wait2; else STM <= Wait1; end if;
when Wait2 => STM <= Work1; ENA <= '1'; stw <= (others => '0');
end case;
end if;
end if;
end process;
CmdS <= cmdr (3 downto 0);
-- MAIN COMMAND CASE
process (NEWcmdr(3 downto 0)) begin
case conv_integer(NEWcmdr(3 downto 0)) is
when 0 => IntWait <= '1';
when 1 => IntWait <= '1';
when 2 => IntWait <= '1';
when 5 => IntWait <= '1';
when 3 => intWait <= Trigg;
when 4 => intWait <= Trigg;
when others => IntWait <= '0';
end case;
end process;
process (cmdr (3 downto 0)) begin
case conv_integer(cmdr (1 downto 0)) is
when 1 => alux <= TR nand DSTdi;
when 2 => alux <= TR + DSTdi;
when 3 => alux <= TR(WidtX-1)&TR(WidtX-1 downto 1);
when others => alux <= TR;
end case;
case conv_integer(cmdr (3 downto 0)) is
-- NOP
when 0 => NEWcmdr <= di; newPC <= PC + 1; RStcmd <= STnop;
NewTrigg <= '0';
RStdo <= RStdi; newTR <= TR; DStcmd <= STnop; DStdo <= DStdi;
CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0';
-- LIT
when 1 => NEWcmdr <= cmd4shr; newPC <= PC + 1; RStcmd <= STnop;
NewTrigg <= '0';
DStdo <= TR; newTR <= di; DStcmd <= STpush; RStdo <= RStdi;
CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0';
-- CALL
when 2 => NEWcmdr <= cmd4shr;
NewTrigg <= '0';
newPC <= di; RStDo <= PC + 1; RStcmd <= STpush;
newTR <= TR; DStcmd <= STnop; DStdo <= DStdi;
CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0';
-- @
when 3 =>
newTrigg <= not Trigg;
if Trigg = '0' then
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NEWcmdr <= cmdr;
RStcmd <= STpush; newPC <= TR; RStdo <= PC;
newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi;
else
CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0';
NEWcmdr <= cmd4shr;
RStcmd <= STpop; newPC <= RSTdi; RStdo <= RStdi;
newTR <= di; DStcmd <= STpush; DStdo <= TR;
end if;
-- !
when 4 =>
newTrigg <= not Trigg;
if Trigg = '0' then
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NEWcmdr <= cmdr;
RStcmd <= STpush; newPC <= TR; RStdo <= PC;
DStcmd <= STpop; newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi;
else
CsRAM <= '0'; WrRAM <= '0'; RdRAM <= '1';
NEWcmdr <= cmd4shr;
RStcmd <= STpop; newPC <= RSTdi; RStdo <= RStdi;
DStcmd <= STpop; newTR <= DStdi; DStcmd <= STpop; DStdo <= DStdi;
end if;
-- ?BRANCH
when 5 => NEWcmdr <= cmd4shr; RStdo <= RStdi;
NewTrigg <= '0';
newTR <= TR; DStcmd <= STnop; DStdo <= DStdi;
CsRAM <= '0'; WrRAM <= '1'; RdRAM <= '0';
if (TR = 0) then
newPC <= PC + 1; RStcmd <= STnop;
else
newPC <= di; RStcmd <= STnop;
end if;
-- RET
when 6 => NEWcmdr <= cmd4shr;
NewTrigg <= '0';
newPC <= RStDi; RStcmd <= STpop;
RStdo <= RStdi; newTR <= TR; DStcmd <= STnop; DStdo <= DStdi;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
-- DUP
when 7 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= RStdi;
newTR <= TR;
DStcmd <= STpush;
DStdo <= TR;
-- DROP
when 8 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= RStdi;
newTR <= DSTdi;
DStcmd <= STpop;
DStdo <= TR;
-- SWAP
when 9 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= RStdi;
-- swap*
newTR <= DSTdi;
DStcmd <= STswap;
DStdo <= TR;
-- OVER
when 10 => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= RStdi;
-- dup*
newTR <= DSTdi;
DStcmd <= STpush;
DStdo <= TR;
-- R>
when 11 => NEWcmdr <= cmd4shr; RStcmd <= STpop; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= RStdi; newTR <= RStdi; DStcmd <= STpush; DStdo <= TR;
-- >R
when 12 => NEWcmdr <= cmd4shr; RStcmd <= STpush; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= TR; newTR <= DStdi; DStcmd <= STpop;
DStdo <= DStdi;
-- NAND
when 13 =>
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
NewTrigg <= '0';
RStdo <= RStdi;
newTR <= alux; -- TR nand DSTdi;
DStcmd <= STpush;
DStdo <= TR;
-- ADD
when 14 =>
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
RStdo <= RStdi;
-- dup*
newTR <= alux; -- TR + DSTdi;
DStcmd <= STpush;
DStdo <= TR;
-- 2/
when 15 =>
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
RStdo <= RStdi;
newTR <= alux; -- TR(WidtX-1)&TR(WidtX-1 downto 1);
DStcmd <= STpush;
DStdo <= TR;
when others => NEWcmdr <= cmd4shr; RStcmd <= STnop; newPC <= PC;
CsRAM <= '1'; WrRAM <= '1'; RdRAM <= '1';
NewTrigg <= '0';
RStdo <= RStdi; DStdo <= DStdi; DStcmd <= STnop; DStdo <= DStdi;
newTR <= TR;
end case;
end process;
do <= TR;
adr <= PC;
test_cmd <= CmdS;
Out_ena <= ENA;
cs_RAM <= csRAM or ENA;
rd_RAM <= rdRAM or ENA;
wr_RAM <= wrRAM or ENA;
test_Trigg <= Trigg;
test_RStDo <= RSTdo;
test_DStDo <= DSTdo;
END RTL;
--
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_unsigned.all;
ENTITY stack IS
GENERIC ( WidtX : integer := 16;
depth : integer := 3
);
Port (
clk : in std_logic;
cmd : in std_logic_vector (1 downto 0);
di : in std_logic_vector (WidtX-1 downto 0);
do : out std_logic_vector (WidtX-1 downto 0);
ena : in std_logic
);
END stack;
ARCHITECTURE SRTL OF stack IS
attribute altera_attribute : string;
attribute altera_attribute of SRTL: architecture is "-name AUTO_SHIFT_REGISTER_RECOGNITION OFF";
TYPE Tstack IS array (depth-1 downto 0) OF std_logic_vector (WidtX-1 downto 0);
constant nop : std_logic_vector (1 downto 0) := "00";
constant push : std_logic_vector (1 downto 0) := "01";
constant pop : std_logic_vector (1 downto 0) := "10";
constant swap : std_logic_vector (1 downto 0) := "11";
signal st : Tstack;
BEGIN
process (clk,cmd) begin
if (clk'event and clk='1' and ena = '1') then
case cmd is
when nop => st <= st;
when pop => st(depth-2 downto 0) <= st(depth-1 downto 1); st(depth-1) <= (others => '0');
when push => st(depth-1 downto 1) <= st(depth-2 downto 0); st(0) <= di;
when swap => st(depth-1 downto 1) <= st(depth-1 downto 1); st(0) <= di;
end case;
end if;
end process;
do <= st(0);
END ARCHITECTURE;
На CYCLONE-II эта штучка вытягивает до 180MHz
При условии, что обращение к внутренней памяти занимает 3 такта - получается 60MIPS