240 likes | 365 Vues
This document details the design of a 32x16 stack module implemented in VHDL for FPGA applications. It covers the architecture, control signals, and core stack operations such as DUP, SWAP, DROP, and OVER, among others. The module incorporates control logic for stack management, including handling empty and full conditions. Additionally, it outlines the behavior of various stack instructions and their corresponding hex opcodes. This framework enables efficient data manipulation in embedded systems and FPGA-based applications.
E N D
Data Stack Lecture 8.2 A VHDL Forth Core for FPGAs: Sect. 3
FC16 Forth Core
stack_ctrl32 entity stack_ctrl is port ( clr: in STD_LOGIC; clk: in STD_LOGIC; push: in STD_LOGIC; pop: in STD_LOGIC; we: out STD_LOGIC; amsel: out STD_LOGIC; wr_addr: out STD_LOGIC_VECTOR (4 downto 0); rd_addr: out STD_LOGIC_VECTOR (4 downto 0); full: out STD_LOGIC; empty: out STD_LOGIC ); end stack_ctrl; 00000 wr_addr rd_addr 11111
stack_ctrl32 architecture stack_ctrl_arch of stack_ctrl is signal full_flag, empty_flag: STD_LOGIC; begin stk: process(clr, clk, push, pop, full_flag, empty_flag) variable push_addr, pop_addr: STD_LOGIC_VECTOR(4 downto 0); begin if clr = '1' then push_addr := "11111"; pop_addr := "00000"; empty_flag <= '1'; full_flag <= '0'; wr_addr <= "11111"; rd_addr <= "00000"; full <= full_flag; empty <= empty_flag;
00000 wr_addr rd_addr 11111 stack_ctrl32 elsif clk'event and clk = '1' then if push = '1' then if pop = ‘0' then if full_flag = '0' then push_addr := push_addr - 1; pop_addr := push_addr + 1; empty_flag <= '0'; if push_addr = "11111” then full_flag <= '1'; push_addr := "00000"; end if; end if; else –- write to top of stack (pop_addr) without pushing -- don’t change push_addr and pop_addr end if;
00000 wr_addr rd_addr 11111 stack_ctrl32 elsif pop = '1' then if empty_flag = '0' then pop_addr := pop_addr + 1; if full_flag = '0' then push_addr := push_addr + 1; end if; full_flag <= '0'; if pop_addr = "00000" then empty_flag <= '1'; end if; end if; end if; wr_addr <= push_addr; rd_addr <= pop_addr; end if;
00000 wr_addr rd_addr 11111 stack_ctrl full <= full_flag; empty <= empty_flag; if push = '1' and full_flag = '0' then we <= '1'; else we <= '0'; end if; if push = '1' and pop = ‘1' then amsel <= '1'; else amsel <= '0'; end if; end process stk; end stack_ctrl_arch;
WHYP Data Stack Instructions DUP ( n -- n n ) SWAP ( a b -- b a ) DROP ( a -- ) OVER ( a b -- a b a ) ROT ( a b c -- b c a ) -ROT ( a b c -- c a b ) NIP ( a b -- b ) TUCK ( a b -- b a b ) ROT_DROP ( a b c -- b c ) ROT_DROP_SWAP ( a b c -- c b ) 2DUP ( a b -- a b a b ) Note: 2DUP = OVER OVER
Hex Opcode Name Function Data Stack Instructions 0000 NOP No operation 0001 DUP Duplicate T and push data stack. N <= T; N2 <= N; 0002 SWAP Exchange T and N. T <= N; N <= T; 0003 DROP Drop T and pop data stack. T <= N; N <= N2; 0004 OVER Duplicate N into T and push data stack. T <= N; N <= T; N2 <= N; 0005 ROT Rotate top 3 elements on stack clockwise. T <= N2; N <= T; N2 <= N; 0006 -ROT Rotate top 3 elements on stack counter-clockwise. T <= N; N <= N2; N2 <= T; 0007 NIP Drop N and pop rest of data stack. T is unchanged. N <= N2; 0008 TUCK Duplicate T into N2 and push rest of data stack. N2 <= T; 0009 ROT_DROP Drop N2 and pop rest of data stack. T and N are unchanged. Equivalent to ROT DROP 000A ROT_DROP_SWAP Drop N2 and pop rest of data stack. T and N are exchanged. Equivalent to ROT DROP SWAP
DUP ( n -- n n ) Duplicate T and push data stack. N <= T; N2 <= N; when dup => nload <= '1'; dpush <= '1';
SWAP ( a b -- b a ) Exchange T and N. T <= N; N <= T; when swap => tload <= '1'; nload <= '1'; tsel <= "111";
DROP ( a -- ) Drop T and pop data stack. T <= N; N <= N2; when drop => tload <= '1'; nload <= '1'; tsel <= "111"; nsel <= "01"; dpop <= '1';
OVER ( a b -- a b a ) Duplicate N into T and push data stack. T <= N; N <= T; N2 <= N; when over => tload <= '1'; nload <= '1'; tsel <= "111"; dpush <= '1';
ROT ( a b c -- b c a ) Rotate top 3 elements on stack clockwise. T <= N2; N <= T; N2 <= N; when rot => tload <= '1'; nload <= '1'; tsel <= "110"; dpush <= '1'; dpop <= '1';
-ROT ( a b c -- c a b ) Rotate top 3 elements on stack counter-clockwise. T <= N; N <= N2; N2 <= T; when mrot => tload <= '1'; nload <= '1'; tsel <= "111"; nsel <= "01"; ssel <= '1'; dpush <= '1'; dpop <= '1';
NIP ( a b -- b ) Drop N and pop rest of data stack. T is unchanged. N <= N2; when nip => nload <= '1'; nsel <= "01"; dpop <= '1';
TUCK ( a b -- b a b ) Duplicate T into N2 and push rest of data stack. N2 <= T; when tuck => ssel <= '1'; dpush <= '1';
ROT_DROP ( a b c -- b c ) Drop N2 and pop rest of data stack. T and N are unchanged. Equivalent to ROT DROP when rot_drop => dpop <= '1';
ROT_DROP_SWAP ( a b c -- c b ) Drop N2 and pop rest of data stack. T and N are exchanged. Equivalent to ROT DROP SWAP when rot_drop_swap => tload <= '1'; nload <= '1'; tsel <= "111"; dpop <= '1';