RPN calculator using VHDL

Thread Starter

Sttorm

Joined May 8, 2017
1
Hello!

I have to project a specialized calculator on a Basys3 board using VHDL. The calculator should be able to group numbers using brackets, perform additions and substractions, AND and OR operations. For example, an expression could be: 4 + 5 AND 6 +(2 AND 7 OR 1) - (4 AND 10)

I decided to code it as a RPN calculator and I used Dijkstra's Shunting-yard algorithm to transform the infix expression into a postfix one. I managed to implement this algorithm, I tested it in the simulator and it transformed the expression correctly. I also tried to synthesize it to the Basys3 board and it worked.

However, the part that should calculate the result doesn't work properly and I can't figure out why. This is the code that I have written:

Code:
calc: process(egal, temp_res) is  
    variable q_front_v: integer := q_front;                                       --inicates the first element from the queue that contains the expression in postfix notation
    variable q_last_v: integer := q_last;                                          --indicates the last element from the queue
    variable top_res_v: integer := top_res;                                     --indicates the top of the result stack  
    variable crt_element: std_logic_vector(17 downto 0) := (others => '0');        --will be the first element from the queue
    variable i: integer;                                                 
   
    variable calculated_v: std_logic := calculated;   
    variable final_result_v: std_logic_vector(17 downto 0) := final_result;
    begin
        if egal = '1' then    --if the whole expression was introduced
           
            if q_front_v < q_last_v then    --if the queue is empty -> we made all the calculations -> we have the final result
                final_result_v := temp_res;
           
            else
                if calculated_v = '1' then    --if we already calculated a partial result -> we add it in the result stack
                    top_res_v := top_res_v - 1;
                    res_stack(top_res_v) <= temp_res;
           
                else --    if we didn't yet calculate any partial result => we will after we exit the process
                    calculated_v := '1';
                   
                end if;
               
                crt_element := queue(q_front_v); --the first element from the queue
                q_front_v := q_front_v - 1;        --dequeue, we eliminate the first element from the queue
                i := 1100;
               
                while (crt_element(17) /= '1') and (i /= 0) loop --while the element we take out of the queue isn't an operator
                    top_res_v := top_res_v - 1;             --we add the element in the result stack => push
                    res_stack(top_res_v) <= crt_element;  --we add the element in the result stack => push
                   
                    crt_element := queue(q_front_v);     --first element from the queue
                    q_front_v := q_front_v - 1;             --dequeue
                   
                    i := i - 1;
                end loop;
               
                -- we exited the while loop => crt_element is an operator => we have to make the calculations
               
                op2 <= res_stack(top_res_v); -- the element from the top of the result stack
                top_res_v := top_res_v + 1;    -- we eliminate the element from the top of the stack => pop
               
                op1 <= res_stack(top_res_v); -- the element from the top of the result stack
                top_res_v := top_res_v + 1;      -- we eliminate the element from the top of the stack => pop
               
                oper_crt <= crt_element(4 downto 0); --the operator that was dequeued last time     
               
                q_front <= q_front_v;
                top_res <= top_res_v;
               
                calculated <= calculated_v;
                final_result <= final_result_v;
               
            end if;
               
        end if;
       
    end process;
   
    ALU_calc: ALU port map(op1(16 downto 0), op2(16 downto 0), oper_crt, temp_res(16 downto 0));
   
    BCD_afis:  BCD_7seg port map(final_result(15 downto 0), clk, clr, a_to_g, an);
    negative <= final_result(16);
op1, op2 and oper_crt don't seem to modify their values in the process (they remain 0 after the process executes once - I don't understand why) and so when the ALU is called, it will do 0+0 and temp_res will remain 0 and the process won't start again (I think that's what's happening).

I tried to synthesize the whole code (the one I posted above + the Shunting-yard algorithm) on the Basys3 board and the synthesis went on forever.

I'm new to VHDL, I'm a student and I have just started learning it and I got stuck at this part in the project. Could you give me some advice on how I could modify the code that I have written so that the RPN calculator would work corectly?

Thanks!
 
Top