Copyright c 2003 by Valery Sklyarov and Iouliia
Copyright (c) 2003 by Valery Sklyarov and Iouliia Skliarova: DETUA, IEETA, Aveiro University, Portugal
1. Presenting basic ideas of recursive algorithms and hierarchical finite state machines (HFSM), which enable us to implement these algorithms Three following things will be considered: 1. 1. Description of the considered algorithms with examples 1. 2. C++ program that implements a recursive sorting algorithm. The program can be run and tested 1. 3. Presenting the considered algorithms in form of hierarchical graph schemes 2. ISE 5. 2 projects that demonstrate implementations in FPGA all individual components and entire circuits that carry out recursive constructing of a binary tree, which describes a structure of data and recursive sorting of data taking from the binary tree. Two following things will be considered: 2. 1. VHDL code for individual components, such as stack memory, a number of HFSM, a number of execution units that permit to understand the entire quite complicated example step by step, etc. 2. 2. VHDL code for complete ISE 5. 2 project, which takes (undefined number of data) constructs and extends a binary tree that keeps these data, carries out a sorting procedure on the binary tree. 3. Projects for ISE 5. 2 that might be downloaded and tested
C- program of the recursive sorting algorithm can be found in: 1. B. W. Kernighan and D. M. Ritchie, The C Programming Language. Englewood Cliffs, NJ: Prentice-Hall, 1988. Definition of a HFSM, hierarchical graph-schemes and their use on examples of very simple recursive sorting algorithms can be found in: 2. V. Sklyarov, Hierarchical Finite State Machines and Their Use for Digital Control, IEEE Transactions on VLSI, Vol. 7, No 2, June, 1999, pp. 222 -228. This tutorial includes more complicated examples, more detailed description and a model of HFSM that is different from [2]
Let us assume that we are receiving integers (unsigned) from a channel (example from [2]) 1) 2) 3) 4) 5) 6) 7) 17 6 18 9 5 21 … root of a binary tree left node because right node of the node 18, because 21 > 17 and 21 > 18 17 6 < 17 6 5 18 9 21 left node of the node 6, because 5 < 17 and 5 < 6 right node of the node 6, because 9 < 17 and 9 > 6 se right node becau 18 > 17
size #include <iostream. h> // C++ program, which: #include <string. h> // - constructs a binary tree, using recursive function der *dr(der *kr, char *word) #include <stdlib. h> // - traverses binary tree, using recursive function struct der // template<class T> void drpr(der *kr, STACK<T> &my_stack) char *w; sp increment (push) int c; struct der *l; sp decrement (pop) struct der *r; }; top template <class T> class STACK { // top – pointer to the top; sp – stack pointer T *top, *sp; template for a class // size – the size of the stack int size; STACK public: // STACK class constructor STACK(int n) { top = sp = new T[size=n]; } // STACK class destructor ~STACK() { delete[] top; } // += - push the value of v onto STACK void operator+=(T v) { if (size>sp-top) *sp++ = v; else cerr << "ERRORn"; } T operator--() { if (sp==top) { cerr << "error: t"; return *sp; } // -- - carry out pop operation return *--sp; } int operator~() const { cout << "size = " << (sp-top) << endl; // ~ - return the size of the used STACK return (int)(sp-top); } }; template<class T> void drpr(der *kr, STACK<T> &my_stack) { if(kr!=NULL) { drpr(kr->l, my_stack); cout << "word - " << kr->w << "; repeated - " << kr->c << endl; my_stack+=kr->w; drpr(kr->r, my_stack); } }
#include <iostream. h> // C++ program, which: #include <string. h> // - constructs a binary tree, using recursive function der *dr(der *kr, char *word) #include <stdlib. h> // - traverses binary tree, using recursive function struct der // template<class T> void drpr(der *kr, STACK<T> &my_stack) char *w; int c; struct der *l; number of a binary struct der *r; }; incoming tree node template <class T> class STACK { data with T *top, *sp; this value int size; public: STACK(int n) { top = sp = new T[size=n]; } ~STACK() { delete[] top; } void operator+=(T v) { if (size>sp-top) *sp++ = v; This function will else cerr << "ERRORn"; } be considered T operator--() { if (sp==top) { cerr << "error: t"; return *sp; } later in details return *--sp; } int operator~() const { cout << "size = " << (sp-top) << endl; return (int)(sp-top); } }; template<class T> void drpr(der *kr, STACK<T> &my_stack) { if(kr!=NULL) { drpr(kr->l, my_stack); cout << "word - " << kr->w << "; repeated - " << kr->c << endl; my_stack+=kr->w; drpr(kr->r, my_stack); } }
void main(void) main function // kr and dr are pointers to binary graph nodes { der *kr, *dr(der*, char*); STACK<char*> my_stack=10; // my_stack is stack of size 10 int i; char word[40][21]; kr = NULL; i=0; for(; ; ) { cout << "Enter a wordn"; getting data from a channel cin >> (char*)word[i]; (input stream) if (word[i][0]=='0') break; kr = dr(kr, word[i++]); }; // the function dr adds value drpr(kr, my_stack); // to the binary tree while (~my_stack != 0) cout << --my_stack << endl; // the function drpr sorts data } // from the binary tree and der *dr(der *kr, char *word) // displays sorted data { int sr; if(kr==NULL) { kr = new der; kr->w = word; kr->c = 1; kr->r = kr->l = NULL; } else if((sr=strcmp(word, kr->w))==0) kr->c++; else if(sr<0) kr->l = dr(kr->l, word); else kr->r=dr(kr->r, word); return kr; }
The results of the program input data output results
Z 1 a 0 Begin 0 der *dr(der *kr, char *word) { int sr; if(kr==NULL) { kr = new der; kr->w = word; kr->c = 1; kr->r = kr->l = NULL; } else if((sr=strcmp(word, kr->w))==0) kr->c++; else if(sr<0) kr->l = dr(kr->l, word); else kr->r=dr(kr->r, word); return kr; } 1 1 X 2 0 1 a 3 y 1, y 2, z 1 y 6 y 8 X 4 0 y 9 y 1, y 4, z 1 a 2 y 7 a 4 End (y 5) a 7 a 5 left X 3 right a 6 a 1
See the details in paper [2] (slide 3) y 7 y 6 this output signal will be used in the algorithm Z 2 y 1 - push data onto the local stack y 2 - write an address of the left node y 3 - push data onto the output stack y 4 - write an address of the right node y 5 - pop data from the local stack y 6 - copy address for the left node from the local stack to the register y 7 - copy address for the right node from the local stack to the register y 8 – create a new node in the RAM The effect of outputs y 8, y 9 will be considered in VHDL code for datapath (see the component data_lcd. vhd) y 9 – prepare the local stack for stack unwiding See details in the paper [2] (slide 3)
See the details in paper [2] (slide 3) See details in the paper [2] (slide 3)
This is also a recursive algorithm This output operation is modeled by VHDL code that permits to display sorted (and other necessary) data on LCD Z 2 Begin 0 a 0 x 1 1 template<class T> void drpr(der *kr, STACK<T> &my_stack) { if(kr!=NULL) { drpr(kr->l, my_stack); cout << "word - " << kr->w << "; repeated - " << kr->c << endl; my_stack+=kr->w; drpr(kr->r, my_stack); } } Microoperations y 1, y 2, y 4 and y 5 perform operations that are hidden in software (C++) and have to be implemented in hardware y 1, y 2, z 2 a 1 y 3 a 2 y 1, y 4, z 2 a 3 End, y 5 a 4
See the details in paper [2 (slide 3) See details in the paper [2] (slide 3)
Z 0 The cycle is modeled with the aid of an input X 5 //. . . . . for(; ; ) { cout << "Enter a wordn"; cin >> (char*)word[i]; if (word[i][0]=='0') break; kr = dr(kr, word[i++]); }; drpr(kr, my_stack); while (~my_stack != 0) cout << --my_stack << endl; //. . . . . 0 Begin a 0 z 1 a 1 X 5 1 z 2 a 2 End a 3
Hierarchical specifications Recursi ve specific ations
x 2= 1 when new value is not equal to RAM value written on active address x 3= 1 when pointer is equal to 11… 11, i. e. there is no next node x 4= 1 when new value less than RAM value written on active address s es k dr tac ad l s h ca us lo - p he y 1 to t on 6 ≠ 17 6 < 17 there is a node 17 1. . 1 y 2 - write an address of the left node 1. . 1, i. e. there is no node activate the same module address = 0 address of the left node does not exist address of the right node does not exist
x 2= 1 when new value is not equal to RAM value written on active address x 3= 1 when pointer is equal to 11… 11, i. e. there is no next node x 4= 1 when new value less than RAM value written on active address save address onto the local stack recursive call write 1. . 1, i. e. there is no node 6 1. . 1 17 1. . 1 increment address = 0 return to the node, which follows the previous z 1 call
x 2= 1 when new value is not equal to RAM value written on active address x 3= 1 when pointer is equal to 11… 11, i. e. there is no next node x 4= 1 when new value less than RAM value written on active address Recursive calls 17 stack unwinding 6 This address will be written to the RAM for the left node because the call was done through an exit 1 of the respective rhomboidal node 6 1. . 1 17 1. . 1 0. . 1 1. . 1 increment address = 0 Writes the address of the RAM from the top of the local stack.
x 2= 1 when new value is not equal to RAM value written on active address x 3= 1 when pointer is equal to 11… 11, i. e. there is no next node x 4= 1 when new value less than RAM value written on active address 17 6 18 6 1. . 1 17 1. . 1 0. . 1 18 1. . 1 6 1. . 1 17. . 10 0. . 1 this sequence will finally be activated RAM before RAM after
7 <1 14 17 18 >6 14 6 15 14 10 <1 5 2 >1 14 12 3 3 >1 14 13 14
12 <1 7 17 18 >6 12 12 = 12 3 15 10 13 stack unwinding 14
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 y 1 – push RAM address onto the local stack y 2 – write an address of the left node z 2 – call itself 18 1. . 1 6 1. . 1 17. . 10 0. . 1
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 Local stack y 1 – push RAM address onto the local stack y 2 – write an address of the left node z 2 – call itself 0. 01 0. . 00 address of 17 address of 6
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 1. . 1 Local stack 0. 01 y 3 – record output data 0. . 00 address of 17 y 5 – pop data from the local stack to the address register address of 6
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 Local stack 0. . 01 0. . 00 y 1 – push RAM address onto the local stack y 4 – – write an address of the right node z 2 – call itself
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 1. . 1 Local stack 0. 01 y 3 – record output data y 5 – pop data from the local stack to the address register 0. . 00
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 Local stack 0. . 00 y 1 – push RAM address onto the local stack y 4 – – write an address of the right node z 2 – call itself
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 Local stack y 1 – push RAM address onto the local stack y 2 – write an address of the left node z 2 – call itself 0. . 10 0. . 00
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 1. . 1 Local stack 0. . 10 y 3 – record output data y 5 – pop data from the local stack to the address register 0. . 00
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 Local stack 0. . 10 0. . 00 y 1 – push RAM address onto the local stack y 4 – – write an address of the right node z 2 – call itself
x 1 = 0 when there is no pointer to other nodes (i. e. the pointer is equal to 1. . 1) 17 6 18 18 1. . 1 6 1. . 1 17. . 10 0. . 1 1. . 1 Local stack 0. . 10 0. . 00 y 5 – pop data from the local stack to the address register
Changes that are required in order to change the order: y 1, y 4, z 2 Other examples of modifiability can be found in [2] (slide 3) y 1, y 2, z 2 The algorithm has very compact VHDL description and it is very fast (see the next section)
17 6 18 12 3 15 10 13 14
Adding data to the tree until these data are available Sorting data and recording the sorted data onto the output
set the state a 0 on the top 2 push 1 pop x. L x 1 inputs Combinational circuit (CC) Stack memory active module outputs y 1 y. N 3 if rising_edge(clk) then if push = '1' then stack_counter <= stack_counter + 1; FSM_stack(stack_counter+1) <= a 0; M_stack(stack_counter+1) <= NM; Stack of moduls For this example NM = z 1
x. L x 1 inputs y 1, y 4, z 1 push Stack memory pop Combinational circuit (CC) active module outputs Z 1 a 0 y 1 Begin 0 y. N X 3 1 1 X 2 0 1 a 3 y 1, y 2, z 1 X 4 0 y 9 y 1, y 4, z 1 a 2 y 6 a 4 End (y 5) a 7 a 5 y 7 y 8 a 6 a 1 1) y 1 and y 4 are active 2) Starting from the next rising edge of the clock module z 1 will be executed 3) After terminating the module z 1 an output for the next node (i. e. y 6) will be active Stack of moduls
x. L x 1 inputs push pop 1 Stack memory Z 1 a 0 Begin 0 outputs X 3 y 1 1 1 a 3 y 1, y 2, z 1 0 y 9 a 2 y 6 a 4 End (y 5) a 7 a 5 y 7 y 8 X 4 y 1, y 4, z 1 y. N X 2 0 1 Combinational circuit (CC) active module for example a 6 a 1 2 set return flag in order to avoid repeating outputs that appear in nodes that invoke other nodes if rising_edge(clk) then if pop = '1' then stack_counter <= stack_counter - 1; return_flag <= '1'; Stack of moduls
entity stack is generic ( L : integer : = 3; N : integer : = 7; depth : integer : = 15); clock from pushbutton 2 port ( clk : in std_logic; rst : in std_logic; reset from reset button S 5 - on push : in std_logic; pop : in std_logic; S 4 - on count : out std_logic_vector(3 downto 0); inputs : in std_logic_vector(L downto 0); S 3…S 0 outputs : out std_logic_vector(N downto 0)); end stack; architecture Behavioral of stack is type stack_memory is array(0 to depth) of std_logic_vector(L downto 0); signal stack : stack_memory; signal stack_counter : integer range 0 to depth; begin stack counter value on LCD (top middle number) if pop is active (S 4) then outputs are shown in top left field of LCD
process(clk, rst, push, pop) begin if rst = '1' then stack_counter <= 0; stack(stack_counter) <= (others => '0'); elsif rising_edge(clk) then if stack_counter < depth and push = '1' then stack_counter <= stack_counter + 1; stack(stack_counter) <= inputs; elsif stack_counter > 0 and pop = '1' then stack_counter <= stack_counter-1; outputs <= stack(stack_counter-1); end if; count <= conv_std_logic_vector(stack_counter, 4); end process;
value to push onto the stack (in case of push operation) or value returned from the stack (in case of pop operation) stack counter (stack pointer) value 0 1 4 1 State co u 100 nt DIC clock from stack counter increment decrement S 0 …S 3 S 5 S 0. . . S 7 S 6
x. L x 1 inputs inc dec Stack memory Combinational circuit (CC) This stack for simplicity does not check overflow outputs y 1 y. N process(lpb(2), rst, FSM_stack, stack_counter) begin if rst = '1' then outputs <= (others => '0'); stack_counter <= 0; elsif rising_edge(lpb(2)) then if inc = '1' then stack_counter <= stack_counter + 1; FSM_stack(stack_counter+1) <= (others => '0'); elsif dec = '1' then stack_counter <= stack_counter - 1; else FSM_stack(stack_counter) <= inputs; end if; a 2 end if; outputs <= FSM_stack(stack_counter); end process; For example: y 1, y 4, z 1 For example: End, y 5 For exemple: y 3 a 2
VHDL code for the FSM stack was inserted into VHDL code for LCD Test sequence: • • • • • INPUTS S 0…S 5 = 1000 0 0 Press pushbutton 2 S 0…S 5 = - - 0 1 Press pushbutton 2 S 0…S 5 = 0100 0 0 Press pushbutton 2 S 0…S 5 = - - 0 1 Press pushbutton 2 S 0…S 5 = 0010 0 0 Press pushbutton 2 S 0…S 5 = - - 0 1 Press pushbutton 2 S 0…S 5 = 0001 0 0 Press pushbutton 2 S 0…S 5 = - - 1 0 Press pushbutton 2 OUTPUTS 0 00000 0 10000 0001 0 10000 0101 1 10000 0100 1 10000 1 120000000 0002 1 120000000 0102 2 120000000 0100 2 120000000 2 124000000 0004 2 124000000 0104 3 124000000 0100 3 124000000 3 124800000 0008 3 124800000 1008 2 124800000 1004 1 124800000 1002 0 124800000 1001 stack counter stack value 0 00000 Count s 0000 10 00 tack DIC O stack pointer decrement – stack pointer increment – clock – value extracted from the stack
Divides clock to HFSM stack pointer decrement FSM stack pointer increment HFSM outputs 00000 0 y 1. y 5 x 1 000 SP DIx 1 FSM stack pointer entity Divider is Port ( clk 48 : in std_logic; rst : in std_logic; loc_clk : out std_logic); end Divider; architecture Behavioral of Divider is signal div: unsigned (26 downto 0); begin process(clk 48, rst) begin if rst= '1' then div <= (others=> '0'); elsif rising_edge(clk 48) then div<= div + 1; end if; end process; loc_clk<= div(div'left); end Behavioral;
entity HFSM_test is clock 0. 5 -1 Hz Port ( clk : in std_logic; reset from reset button rst : in std_logic; count : out std_logic_vector(3 downto 0); FSM stack pointer inputs : in std_logic_vector(7 downto 0); inputs(7) = S 7 = x 1 inc dec y 5 y 4 y 3 y 2 y 1 outputs : out std_logic_vector(7 downto 0)); end HFSM_test; architecture Behavioral of HFSM_test is -- FSM module begin type STATE_TYPE is (a 0, a 1, a 2, a 3, a 4); signal NS: STATE_TYPE; HFSM states -- FSM module end ----------------- for stack begin type stack is array(0 to 63) of STATE_TYPE; signal FSM_stack : stack; HFSM stack signal stack_counter : integer range 0 to 63; HFSM stack pointer signal inc : std_logic; HFSM stack pointer increment signal dec : std_logic; HFSM stack pointer decrement ----------------- for stack end signal return_flag : std_logic; begin
----------------- for stack begin process(clk, rst, FSM_stack, stack_counter) begin if rst = '1' then stack_counter <= 0; FSM_stack(stack_counter) <= a 0; return_flag <= '0'; elsif rising_edge(clk) then if stack_counter < 63 and inc = '1' then stack_counter <= stack_counter + 1; FSM_stack(stack_counter+1) <= a 0; elsif stack_counter > 0 and dec = '1' then stack_counter <= stack_counter - 1; return_flag <= '1'; else FSM_stack(stack_counter) <= NS; return_flag <= '0'; end if; count <= conv_std_logic_vector(stack_counter, 4); end process; ----------------- for stack end
-- FSM module begin process (FSM_stack, stack_counter, inputs(7)) begin case FSM_stack(stack_counter) is when a 0 => outputs <= (others => '0'); inc <= '0'; dec <= '0'; if (inputs(7)='0') then NS <= a 4; else NS <= a 1; end if; when a 1 => inc <= '0'; dec <= '0'; NS <= a 2; if return_flag = '0' then inc <= '1'; outputs(4 downto 0) <= "00011"; else inc <= '0'; outputs <= (others => '0'); end if; when a 2 => outputs(4 downto 0) <= "00100"; inc <= '0'; dec <= '0'; NS <= a 3; when a 3 => dec <= '0'; NS <= a 4; if return_flag = '0' then inc <= '1'; outputs(4 downto 0) <= "01001"; else inc <= '0'; outputs <= (others => '0'); end if; Experiments with when a 4 => inc <= '0'; NS <= a 4; this code permit to if stack_counter > 0 then dec <= '1'; outputs(4 downto 0) <= "10000"; test all state else dec <= '0'; outputs <= (others => '0'); transitions and to end if; when others => null; understand end case; hierarchical calls, outputs(5) <= dec; recursivity and outputs(6) <= inc; hierarchical outputs(7) <= inputs(7); returns end process; -- FSM module end Behavioral;
Z 0 Begin a 0 z 2 a 1 End a 2
This circuit sorts and displays data from a given binary tree This block is a datapath that is controlled by HFSM
entity HFSM is generic (stack_size : integer : = 15); port ( clk : in std_logic; rst : in std_logic; signal that indicates a possible error : buffer std_logic; X 1_from_datapath : in std_logic; input from datapath outputs_to_datapath : out std_logic_vector(5 downto 1)); outputs to datapath end HFSM; architecture Behavioral of HFSM is -- modules begin type MODULE_TYPE is (m 0, m 2); signal NM: MODULE_TYPE; -- modules end -- FSM module begin type STATE_TYPE is (a 0, a 1, a 2, a 3, a 4); signal NS: STATE_TYPE; -- FSM module end ----------------- for stack begin type stack is array(0 to stack_size) of STATE_TYPE; -- std_logic_vector(3 downto 0); signal FSM_stack : stack; signal stack_counter : integer range 0 to stack_size; signal inc, tmp : std_logic; signal dec : std_logic; ----------------- for stack end
----------------- for stack of modules begin type Mstack is array(0 to stack_size) of MODULE_TYPE; -- std_logic_vector(3 downto 0); signal M_stack : Mstack; ----------------- for stack of modules end signal return_flag : std_logic; begin ----------------- for stack begin process(clk, rst) begin if rst = '1' then stack_counter <= 0; FSM_stack(stack_counter) <= a 0; M_stack(stack_counter) <= m 0; return_flag <= '0'; error <= '0'; elsif rising_edge(clk) then if inc = '1' then if stack_counter = stack_size then error <= '1'; else stack_counter <= stack_counter + 1; FSM_stack(stack_counter+1) <= a 0; M_stack(stack_counter+1) <= NM; end if; elsif dec = '1' then stack_counter <= stack_counter - 1; return_flag <= '1'; else FSM_stack(stack_counter) <= NS; return_flag <= '0'; end if; end process; ----------------- for stack end indicates stack overflow Z 0 Begin a 0 z 2 a 1 End a 2
-- FSM module begin process (FSM_stack, stack_counter, X 1_from_datapath, M_stack) begin case M_stack(stack_counter) is when m 0 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; NS <= a 1; when a 1 => dec <= '0'; NS <= a 2; outputs_to_datapath <= (others => '0'); if return_flag = '0' then inc <= '1'; NM <= m 2; else inc <= '0'; end if; when a 2 => inc <= '0'; NS <= a 2; outputs_to_datapath <= (others => '0'); if stack_counter > 0 then dec <= '1'; else dec <= '0'; end if; Z 0 when others => null; end case; a 0 Begin ---------------------------------------z 2 a 1 End a 2
when m 2 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; if (X 1_from_datapath='1') then NS <= a 1; else NS <= a 4; end if; when a 1 => dec <= '0'; NS <= a 2; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "00011"; NM<=m 2; else inc <= '0'; outputs_to_datapath <= "00000"; end if; when a 2 => outputs_to_datapath <= "00100"; inc <= '0'; dec <= '0'; NS <= a 3; when a 3 => dec <= '0'; NS <= a 4; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "01001"; NM<=m 2; else inc <= '0'; outputs_to_datapath <= "00000"; end if; when a 4 => inc <= '0'; NS <= a 4; if stack_counter > 0 then dec <= '1'; outputs_to_datapath <= "10000"; Z 2 else dec <= '0'; outputs_to_datapath <= "00000"; Begin 0 end if; x 1 1 when others => null; y 1, y 2, z 2 end case; when others => null; y 3 end case; end process; y 1, y 4, z 2 -- FSM module end End, y 5 end Behavioral; a 0 a 1 a 2 a 3 a 4
0 30 1 6 3 18 15 38 ad dr sorted data RAM value 35 5 33 7 37 es s RAM address at the end 14 4 0 14 15 1 8 0 00000 30 3335 37 38 3 0 Result expected for this binary tree 2 address 1 ………. . address 2 "110000001", "01010000111111", "11010101100101", … left node address input data in ROM data right node address HFSM outputs entity Data_LCD is generic ( ROM_address_size : integer : = 4; ROM_words : integer : = 10; ROM_data : integer : = 6; Lstack_size : integer : = 15); port ( HFSM_outputs : in std_logic_vector(5 downto 1); x 1_to_HFSM : out std_logic; clk : in std_logic; rst : in std_logic; error : buffer std_logic ); end Data_LCD;
architecture Behavioral of Data_LCD is type rom_type is array (0 to ROM_words-1) of std_logic_vector (ROM_data+2*ROM_address_size-1 downto 0); constant ROM : rom_type : = ("110000001", "01010000111111", "11010101100101", "01100011110100", "0101011111", "110011111", "11100011110111", "110111111", "0010011111", "100011111"); signal ROM_address : integer; 0 30 ----------------- for local stack begin 2 1 type Lstack_memory is array(0 to Lstack_size) of std_logic_vector(ROM_address_size-1 downto 0); 14 35 signal Lstack : Lstack_memory; 6 3 signal Lstack_counter : integer range 0 to Lstack_size; 18 ----------------- for local stack end ----------------- for output stack begin 4 15 38 7 37 type Ostack_memory is array(0 to ROM_words) of std_logic_vector(ROM_data-1 downto 0); signal Ostack : Ostack_memory; signal Ostack_counter : integer range 0 to ROM_words-1; ----------------- for output stack end 5 33
begin Z 2 process (clk, rst) begin a 0 Begin if rst = '1' then ROM_address <= 0; 0 Lstack_counter <= 0; x 1 1 Ostack_counter <= 0; y 1 , y 2 , z 2 x 1_to_HFSM <= '1'; a 1 error <= '0'; elsif falling_edge(clk) then y 3 a 2 if ROM_address > ROM_words-1 then x 1_to_HFSM <= '0'; else x 1_to_HFSM <= '1'; a 3 y 1 , y 4 , z 2 end if; if Lstack_counter > Lstack_size-1 then error <= '1'; End, y 5 a 4 end if; if HFSM_outputs(1) = '1' then Lstack_counter <= Lstack_counter + 1; Lstack(Lstack_counter) <= conv_std_logic_vector(ROM_address, ROM_address_size); end if; if HFSM_outputs(2) = '1' then ROM_address <= conv_integer(ROM_address)(ROM_address_size-1 downto 0)); end if; if HFSM_outputs(3) = '1' then Ostack_counter <= Ostack_counter + 1; Ostack(Ostack_counter) <= ROM(ROM_address)(ROM_data+2*ROM_address_size-1 downto 2*ROM_address_size); end if; if HFSM_outputs(4) = '1' then ROM_address <= conv_integer(ROM_address)(2*ROM_address_size-1 downto ROM_address_size)); end if; if HFSM_outputs(5) = '1' then Lstack_counter <= Lstack_counter - 1; ROM_address <= conv_integer(Lstack_counter - 1)); end if; end process;
0 30 The result 14 15 1 8 0 00000 30 3335 37 38 3 0 1 2 14 6 3 18 4 15 38 35 5 33 7 37 Clock frequency for this project is set to 25 MHz. The project contains a non linked divider. The divider can be linked in order to provide such (lower) frequency that permits all intermediate steps and relevant changes in the datapath to be seen on the LCD
entity HFSM is generic (stack_size : integer : = 15); port ( clk : in std_logic; rst : in std_logic; error : buffer std_logic; X 1_from_datapath : in std_logic; X 3_from_datapath : in std_logic; X 4_from_datapath : in std_logic; outputs_to_datapath : out std_logic_vector(8 downto 1)); end HFSM; The considered circuit adds a new node to the existing binary tree 7 10 architecture Behavioral of HFSM is -- modules begin type MODULE_TYPE is (m 0, m 1); signal NM: MODULE_TYPE; -- modules end -- FSM module begin type STATE_TYPE is (a 0, a 1, a 2, a 3, a 4, a 5, a 6); signal NS: STATE_TYPE; -- FSM module end 9 20 7 20 The circuit does not check if there is a node in the binary tree with equal value. In other words equal values will be repeated in the binary tree The next example (example 6) eliminates repeating values on the tree
----------------- for stack begin type stack is array(0 to stack_size) of STATE_TYPE; -- std_logic_vector(3 downto 0); signal FSM_stack : stack; signal stack_counter : integer range 0 to stack_size; signal inc, tmp : std_logic; signal dec : std_logic; ----------------- for stack end ----------------- for stack of modules begin type Mstack is array(0 to stack_size) of MODULE_TYPE; -- std_logic_vector(3 downto 0); signal M_stack : Mstack; ----------------- for stack of modules end signal return_flag : std_logic; begin ----------------- for stack begin process(clk, rst) begin if rst = '1' then stack_counter <= 0; FSM_stack(stack_counter) <= a 0; M_stack(stack_counter) <= m 0; return_flag <= '0'; error <= '0'; elsif rising_edge(clk) then if inc = '1' then if stack_counter = stack_size then error <= '1'; else stack_counter <= stack_counter + 1; FSM_stack(stack_counter+1) <= a 0; M_stack(stack_counter+1) <= NM; end if; elsif dec = '1' then stack_counter <= stack_counter - 1; return_flag <= '1'; else FSM_stack(stack_counter) <= NS; return_flag <= '0'; end if; end process; ----------------- for stack end This code has already been considered
This code has already been considered -- FSM module begin process (FSM_stack, stack_counter, X 1_from_datapath, M_stack) begin case M_stack(stack_counter) is when m 0 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; NS <= a 1; when a 1 => dec <= '0'; NS <= a 2; outputs_to_datapath <= (others => '0'); if return_flag = '0' then inc <= '1'; NM <= m 1; else inc <= '0'; end if; when a 2 => inc <= '0'; NS <= a 2; outputs_to_datapath <= (others => '0'); if stack_counter > 0 then dec <= '1'; else dec <= '0'; end if; when others => null; end case; --------------------------------------- Z 0 Begin a 0 zz 12 a 1 End a 2
when m 1 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; if X 3_from_datapath='1' then NS <= a 1; elsif X 4_from_datapath='0' then NS <= a 2; else NS <= a 3; end if; when a 1 => dec <= '0'; inc <= '0'; NS <= a 6; outputs_to_datapath <= "10000000"; when a 2 => dec <= '0'; NS <= a 4; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "00001001"; NM<=m 1; else inc <= '0'; outputs_to_datapath <= (others => '0'); end if; when a 3 => dec <= '0'; NS <= a 5; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "00000011"; NM<=m 1; else inc <= '0'; outputs_to_datapath <= (others => '0'); end if; when a 4 => inc <= '0'; dec <= '0'; NS <= a 6; outputs_to_datapath <= "01000000"; when a 5 => inc <= '0'; dec <= '0'; NS <= a 6; outputs_to_datapath <= "00100000"; when a 6 => inc <= '0'; NS <= a 6; if stack_counter > 0 then dec <= '1'; outputs_to_datapath <= "00010000"; else dec <= '0'; outputs_to_datapath <= (others => '0'); end if; when others => null; end case; 1 X when others => null; 0 a end case; end process; y , y , z -- FSM module end a end Behavioral; Z 1 a 0 0 Begin X 3 1 4 y 8 3 1 2 1 1 4 1 a 2 5 y 6 y 7 a 4 End (y 5) a 7 a 1
entity Data_LCD is generic ( RAM_address_size : integer : = 4; RAM_words : integer : = 10; RAM_data : integer : = 6; Lstack_size : integer : = 15); port ( HFSM_outputs : in std_logic_vector(8 downto 1); x 1_to_HFSM : out std_logic; x 3_to_HFSM : out std_logic; x 4_to_HFSM : out std_logic; clk : in std_logic; clk 48 : in std_logic; rst : in std_logic; error : buffer std_logic ); end Data_LCD; This code has already been considered architecture Behavioral of Data_LCD is type ram_type is array (0 to RAM_words-1) of std_logic_vector (RAM_data+2*RAM_address_size-1 downto 0); type rom_type is array (0 to 10) of std_logic_vector (5 downto 0); constant ROM : rom_type : = ("000111", "001000", "010101", "000110", "001001", "110011", "000000", "000000"); signal ROM_address : integer; signal RAM : ram_type; 7 signal RAM_address : integer; signal RAM_w : integer; This value ----------------- for local stack begin type Lstack_memory is array(0 to Lstack_size) of std_logic_vector(RAM_address_size-1 downto 0); will be added signal Lstack : Lstack_memory; signal Lstack_counter : integer range 0 to Lstack_size; ----------------- for local stack end ----------------- for output stack begin type Ostack_memory is array(0 to RAM_words) of std_logic_vector(RAM_data-1 downto 0); signal Ostack : Ostack_memory; signal Ostack_counter : integer range 0 to RAM_words-1; ----------------- for output stack end
begin process (clk, rst) variable last_address : integer; begin if rst = '1' then RAM_address <= 0; ROM_address <= 0; RAM_w <= 2; RAM(0)(13 downto 8) <= "010000"; RAM(0)(7 downto 0) <= "00010010"; RAM(1)(13 downto 8) <= "100000"; RAM(1)(7 downto 0) <= (others => '1'); 10 9 20 RAM(2)(13 downto 8) <= "001001"; RAM(2)(7 downto 0) <= (others => '1'); Lstack_counter <= 0; Ostack_counter <= 0; Forming logic conditions x 1_to_HFSM <= '1'; x 2 and x 4 error <= '0'; elsif falling_edge(clk) then if RAM_address > RAM_words-1 then x 1_to_HFSM <= '0'; else x 1_to_HFSM <= '1'; end if; if RAM_address = 15 then x 3_to_HFSM <= '1'; else x 3_to_HFSM <= '0'; end if; if ROM(ROM_address) < RAM(RAM_address)(13 downto 8) then x 4_to_HFSM <= '1'; else x 4_to_HFSM <= '0'; end if; if Lstack_counter > Lstack_size-1 then error <= '1'; end if; -----------------------------
if HFSM_outputs(1) = '1' then Lstack_counter <= Lstack_counter + 1; y 3 is not used Lstack(Lstack_counter) <= conv_std_logic_vector(RAM_address, RAM_address_size); for this algorithm end if; but will be used if HFSM_outputs(2) = '1' then in future RAM_address <= conv_integer(RAM_address)(RAM_address_size-1 downto 0)); end if; if HFSM_outputs(3) = '1' then Ostack_counter <= Ostack_counter + 1; Ostack(Ostack_counter) <= RAM(RAM_address) (RAM_data+2*RAM_address_size-1 downto 2*RAM_address_size); end if; if HFSM_outputs(4) = '1' then RAM_address <= conv_integer(RAM_address)(2*RAM_address_size-1 downto RAM_address_size)); end if; if HFSM_outputs(5) = '1' then Lstack_counter <= Lstack_counter - 1; RAM_address <= conv_integer(Lstack_counter - 1)); end if; if HFSM_outputs(6) = '1' then RAM(RAM_address)(RAM_address_size-1 downto 0) <= Lstack(Lstack_counter+1); end if; if HFSM_outputs(7) = '1' then RAM(RAM_address) Z (2*RAM_address_size-1 downto RAM_address_size) <= Lstack(Lstack_counter+1); a Begin end if; if HFSM_outputs(8) = '1' then RAM(RAM_w+1) 0 X (RAM_data+2*RAM_address_size-1 downto 2*RAM_address_size) <= ROM(ROM_address); 1 1 RAM(RAM_w+1)(2*RAM_address_size-1 downto 0) <= (others => '1'); X 0 ROM_address <= ROM_address+1; a a y , y , z RAM_w <= RAM_w+1; a Lstack(Lstack_counter) <= conv_std_logic_vector(RAM_w+1, RAM_address_size); y y a end if; End (y ) a end process; 1 0 3 4 3 1 2 1 8 1 4 1 2 5 6 7 4 5 7 1
Values Left address 0 10 12 2 0 0 00000 ? ? 09? ? 37 00 0 0 2 9 10 Values 1 20 Right address There is no node on the right There is no node on the left address 0 address 1 address 2 10 12 2 0 0 00000 ? ? 09? ? 000 00 00 RAM address y 1…y 8 address 3
The frequency of clocks is low, which permits to see all changes on the HFSM outputs step by step RAM address ? indicates that there is no node after the considered node 0 0 10 2 9 10 2 1 20 10 12 2 0 0 00000 ? ? 09? ? 000 00 00 9 1 20 3 7 There is no node on the right 10 12 2 0 0 00000 ? ? 09? 3 000 07 ? ? address 3 There is the node on the left with the address 3
Local stack stores arguments that are required for an active module (such as z 1 and z 2) at each hierarchical level. In other words the local stack works like a stack for functions (subroutines) in C/C++ languages that keeps arguments of these functions when they are being called
entity HFSM is generic (stack_size : integer : = 15); port ( clk : in std_logic; rst : in std_logic; error : buffer std_logic; X 1_from_datapath : in std_logic; X 2_from_datapath : in std_logic; inputs from X 3_from_datapath : in std_logic; datapath X 4_from_datapath : in std_logic; X 5_from_datapath : in std_logic; outputs_to_datapath : out std_logic_vector(9 downto 1)); end HFSM; outputs to datapath architecture Behavioral of HFSM is -- modules begin type MODULE_TYPE is (m 0, m 1, m 2); signal NM: MODULE_TYPE; -- modules end -- FSM module begin type STATE_TYPE is (a 0, a 1, a 2, a 3, a 4, a 5, a 6, a 7); signal NS: STATE_TYPE; -- FSM module end
----------------- for HFSM stack begin type stack is array(0 to stack_size) of STATE_TYPE; signal FSM_stack : stack; signal stack_counter : integer range 0 to stack_size; signal inc, tmp : std_logic; signal dec : std_logic; ----------------- for HFSM stack end ----------------- for HFSM stack of modules begin type Mstack is array(0 to stack_size) of MODULE_TYPE; signal M_stack : Mstack; ----------------- for HFSM stack of modules end signal return_flag : std_logic; begin ----------------- for HFSM stack begin process(clk, rst) begin if rst = '1' then stack_counter <= 0; FSM_stack(stack_counter) <= a 0; M_stack(stack_counter) <= m 0; return_flag <= '0'; error <= '0'; elsif rising_edge(clk) then if inc = '1' then if stack_counter = stack_size then error <= '1'; else stack_counter <= stack_counter + 1; FSM_stack(stack_counter+1) <= a 0; M_stack(stack_counter+1) <= NM; end if; elsif dec = '1' then stack_counter <= stack_counter - 1; return_flag <= '1'; else FSM_stack(stack_counter) <= NS; return_flag <= '0'; end if; end process; ----------------- for HFSM stack end
-- HFSM module begin process (FSM_stack, stack_counter, X 1_from_datapath, M_stack)begin case M_stack(stack_counter) is when m 0 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; NS <= a 1; when a 1 => dec <= '0'; outputs_to_datapath <= (others => '0'); if X 5_from_datapath='0' then NS <= a 1; else NS <= a 2; end if; if return_flag = '0' then inc <= '1'; NM <= m 1; else inc <= '0'; end if; when a 2 => dec <= '0'; NS <= a 3; outputs_to_datapath <= (others => '0'); if return_flag = '0' then inc <= '1'; NM <= m 2; else inc <= '0'; end if; when a 3 => inc <= '0'; NS <= a 3; outputs_to_datapath <= (others => '0'); if stack_counter > 0 then dec <= '1'; else dec <= '0'; end if; when others => null; end case; ---------------------------------------when m 1 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; if X 3_from_datapath='1' then NS <= a 1; elsif X 2_from_datapath='0' then NS <= a 6; elsif X 4_from_datapath='0' then NS <= a 2; else NS <= a 3; end if; when a 1 => dec <= '0'; inc <= '0'; NS <= a 7; outputs_to_datapath <= "010000000"; when a 2 => dec <= '0'; NS <= a 4; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "000001001"; NM<=m 1; else inc <= '0'; outputs_to_datapath <= (others => '0'); end if; when a 3 => dec <= '0'; NS <= a 5; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "000000011"; NM<=m 1; else inc <= '0'; outputs_to_datapath <= (others => '0'); end if;
when a 4 => inc <= '0'; dec <= '0'; NS <= a 7; outputs_to_datapath <= "001000000"; when a 5 => inc <= '0'; dec <= '0'; NS <= a 7; outputs_to_datapath <= "000100000"; when a 6 => inc <= '0'; dec <= '0'; NS <= a 7; outputs_to_datapath <= "10000"; when a 7 => inc <= '0'; NS <= a 7; if stack_counter > 0 then dec <= '1'; outputs_to_datapath <= "000010000"; else dec <= '0'; outputs_to_datapath <= (others => '0'); end if; when others => null; end case; when m 2 => case FSM_stack(stack_counter) is when a 0 => outputs_to_datapath <= (others => '0'); inc <= '0'; dec <= '0'; if (X 1_from_datapath='1') then NS <= a 1; else NS <= a 4; end if; when a 1 => dec <= '0'; NS <= a 2; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "000000011"; NM<=m 2; else inc <= '0'; outputs_to_datapath <= (others => '0'); end if; when a 2 => outputs_to_datapath <= "000000100"; inc <= '0'; dec <= '0'; NS <= a 3; when a 3 => dec <= '0'; NS <= a 4; if return_flag = '0' then inc <= '1'; outputs_to_datapath <= "000001001"; NM<=m 2; else inc <= '0'; outputs_to_datapath <= (others => '0'); end if; when a 4 => inc <= '0'; NS <= a 4; if stack_counter > 0 then dec <= '1'; outputs_to_datapath <= "000010000"; else dec <= '0'; outputs_to_datapath <= (others => '0'); end if; when others => null; end case; end process; -- HFSM module end Behavioral;
entity Data_LCD is generic ( RAM_address_size : integer : = 4; RAM_words : integer : = 12; ROM_words : integer : = 12; RAM_data : integer : = 6; Lstack_size : integer : = 15); port ( HFSM_outputs : in std_logic_vector(9 downto 1); x 1_to_HFSM : out std_logic; x 2_to_HFSM : out std_logic; outputs to x 3_to_HFSM : out std_logic; HFSM x 4_to_HFSM : out std_logic; x 5_to_HFSM : out std_logic; clk : in std_logic; clk 48 : in std_logic; rst : in std_logic; error : buffer std_logic; 7 end Data_LCD; 2 inputs from HFSM 30 14 37 The modules z 0 9 17 and z 1 will construct this binary tree 13 21 8 architecture Behavioral of Data_LCD is -- begin for ROM that keeps input data and the datapath RAM type ram_type is array (0 to RAM_words-1) of std_logic_vector (RAM_data+2*RAM_address_size-1 downto 0); type rom_type is array (0 to ROM_words-1) of std_logic_vector (5 downto 0); constant ROM : rom_type : = ("110000", "010100", "001001", "000111", "010011", "001001", "110111", "000010", "000111", "001000", "010111", "100001"); -- 30, 14, 9, 7, 13, 9, 37, 2, 7, 8, 17, 21 -- changes in generic -- ROM_words : integer : = 12;
signal ROM_address : integer; signal RAM : ram_type; signal RAM_address : integer; signal RAM_w : integer; signal ROM_w : integer; -- end for ROM that keeps input data and the datapath RAM ----------------- for local stack begin type Lstack_memory is array(0 to Lstack_size) of std_logic_vector(RAM_address_size-1 downto 0); signal Lstack : Lstack_memory; signal Lstack_counter : integer range 0 to Lstack_size; ----------------- for local stack end ----------------- for output stack begin type Ostack_memory is array(0 to RAM_words) of std_logic_vector(RAM_data-1 downto 0); signal Ostack : Ostack_memory; signal Ostack_counter : integer range 0 to RAM_words-1; ----------------- for output stack end begin process (clk, rst) variable last_address : integer; begin if rst = '1' then RAM_address <= 0; ROM_address <= 1; RAM_w <= 0; ROM_w <= ROM_words; RAM(0)(13 downto 8) <= ROM(0); RAM(0)(7 downto 0) <= (others => '1'); LStack(0) <= (others => '0'); Lstack_counter <= 0; Ostack_counter <= 0; x 1_to_HFSM <= '1'; error <= '0'; Initialization
elsif falling_edge(clk) then if RAM_address > RAM_words-1 then x 1_to_HFSM <= '0'; else x 1_to_HFSM <= '1'; end if; if ROM(ROM_address) = RAM(RAM_address) (RAM_data+2*RAM_address_size-1 downto 2*RAM_address_size) then x 2_to_HFSM <= '0'; else x 2_to_HFSM <= '1'; end if; if RAM_address = 15 then x 3_to_HFSM <= '1'; else x 3_to_HFSM <= '0'; end if; if ROM(ROM_address) < RAM(RAM_address) (RAM_data+2*RAM_address_size-1 downto 2*RAM_address_size) then x 4_to_HFSM <= '1'; else x 4_to_HFSM <= '0'; end if; if ROM_address = ROM_w then x 5_to_HFSM <= '1'; else x 5_to_HFSM <= '0'; end if; if Lstack_counter > Lstack_size-1 then error <= '1'; end if; -----------------------------if HFSM_outputs(1) = '1' then Lstack_counter <= Lstack_counter + 1; Lstack(Lstack_counter) <= conv_std_logic_vector(RAM_address, RAM_address_size); end if; if HFSM_outputs(2) = '1' then RAM_address <= conv_integer(RAM_address)(RAM_address_size-1 downto 0)); end if; if HFSM_outputs(3) = '1' then Ostack_counter <= Ostack_counter + 1; Ostack(Ostack_counter) <= RAM(RAM_address) (RAM_data+2*RAM_address_size-1 downto 2*RAM_address_size); end if;
if HFSM_outputs(4) = '1' then RAM_address <= conv_integer(RAM_address) (2*RAM_address_size-1 downto RAM_address_size)); end if; if HFSM_outputs(5) = '1' then if Lstack_counter > 0 then Lstack_counter <= Lstack_counter - 1; RAM_address <= conv_integer(Lstack_counter - 1)); end if; if HFSM_outputs(6) = '1' then RAM(RAM_address) (RAM_address_size-1 downto 0) <= Lstack(Lstack_counter+1); end if; if HFSM_outputs(7) = '1' then RAM(RAM_address) (2*RAM_address_size-1 downto RAM_address_size) <= Lstack(Lstack_counter+1); end if; if HFSM_outputs(8) = '1' then RAM(RAM_w+1) (RAM_data+2*RAM_address_size-1 downto 2*RAM_address_size) <= ROM(ROM_address); RAM(RAM_w+1)(2*RAM_address_size-1 downto 0) <= (others => '1'); ROM_address <= ROM_address+1; RAM_w <= RAM_w+1; Lstack(Lstack_counter) <= conv_std_logic_vector(RAM_w+1, RAM_address_size); end if; if HFSM_outputs(9) = '1' then ROM_address <= ROM_address+1; Lstack(Lstack_counter) <= conv_std_logic_vector(RAM_address, RAM_address_size); end if; end process;
--constant ROM : rom_type : = -("100010", "001000", "111001", -- 22, 8, 39, 6, 39, 3, 6, 8, 18, 21, 0, 28, 1 -"000110", "001001", "000110", -"111001", "000011", "000110", -"001000", "011000", "100001", -- changes in generic -"000000", "101000", "000001"); -- ROM_words : integer : = 15; --constant ROM : rom_type : = -("100010", "001000", "111001", -- 22, 8, 39, 6, 39, 3, 6, 8, 18, 21, 0, 28, 1, 22, 33 -"000110", "001001", "000110", -"111001", "000011", "000110", -"001000", "011000", "100001", -- changes in generic -"000000", "101000", "000001", -- ROM_words : integer : = 18; -"100010", "110011"); These sets of input data make possible to test various examples --constant ROM : rom_type : = -("100010", "000110", "010101", -- 22. 6. 15. 39. 9. 6. 6. 3. 27. 12. 21 -"111001", "000110", -"000110", "000011", "100111", -- changes in generic -"010010", "100001"); -- ROM_words : integer : = 12; --constant ROM : rom_type : = -("100010", "001000", "010101", -- 22, 8, 15, 6, 9, 6, 33, 3, 6, 12, 18, 21 -"000110", "001001", "000110", -"111001", "000011", "000110", -- changes in generic -"010010", "011000", "100001"); -- ROM_words : integer : = 12; --constant ROM : rom_type : = -("100010", "001000", "010101", -- 22, 8, 15, 6, 9, 33, 39, 3, 27, 12, 18, 21 -"000110", "001001", "110011", -"111001", "000011", "100111", -- changes in generic -"010010", "011000", "100001"); -- ROM_words : integer : = 12; --constant ROM : rom_type : = -("010000", "100000", -- 10, 30, 25, 5, 35, 6, 7, 8, , 29, 28, 27 -"100101", "000101", "110101", -"000110", "000111", "001000", -- changes in generic -"101001", "101000", "100111"); -- ROM_words : integer : = 12; The modules z 0, z 1 build 22 this 8 binary tree 6 15 3 9 33 27 39 18 12 21 The module z 2 sorts the numbers and stores in the output stack the following result: 3 6 8 9 12 15 18 21 22 27 33 39
22 33 8 15 6 3 9 27 39 18 12 21 The module z 2 sorts the numbers and stores in the output stack the following result: 3 6 8 9 12 15 18 21 22 27 33 39 This result will be displayed on the LCD as follows: Another example: constant ROM : rom_type : = ("110000", "010100", "001001", "000111", "010011", "001001", "110111", "000010", "000111", "001000", "010111", "100001"); 30 The modules z 0, z 1 build 14 37 this binary 9 17 tree 7 2 13 8 21 03 06 0 8 18 21 2 09 1215 2 27 33 39 -- 30, 14, 9, 7, 13, 9, 37, 2, 7, 8, 17, 21 -- changes in generic -- ROM_words : integer : = 12; The module z 2 sorts the numbers and stores in the output stack the following result: 2 7 8 9 13 14 17 21 30 37 This result will be displayed on the LCD as follows: 02 07 0 8 17 21 3 09 1314 0 37 00 00
x 1, …, x 5 y 1, …, y 9 02 07 0 8 17 21 3 09 1314 0 37 00 00 The code, which contols LCD is inserted to the datapath (the data_lcd block). This code is separated by comments
There are 7 examples available that demonstrate different steps of the tutorial 1. Visual C++ 7. 0 zipped project for C++ program considered in the part 1 2. ISE 5. 2 zipped project for Example 1 – stack memory (see Part 2) 3. ISE 5. 2 zipped project for Example 2 – HFSM stack memory (see Part 2) 4. ISE 5. 2 zipped project for Example 3 – recursive HFSM (see Part 2) 5. ISE 5. 2 zipped project for Example 4 – multi module HFSM (see Part 2) 6. ISE 5. 2 zipped project for Example 5 – constructing a binary tree (see Part 2) 7. ISE 5. 2 zipped project for Example 6 – full example that implements all the circuits and the algorithms considered in the Part 1 (see Part 1 and Part 2) The names of the projects are: C++ 1. HFSM_CPP. zip 2. stack. zip 3. HFSM_stack. zip 4. RHFSM. zip ISE 5. 2 5. MM_HFSM. zip 6. CBT. zip 7. Full_example. zip
- Slides: 87