0

This is a simulation of a long division binary divider. The program performs as expected except it will not subtract the divisor from the 5 MSBs of the register no matter how I code it.

Following is the code:

            library ieee;
            use ieee.std_logic_1164.all;
            use ieee.std_logic_unsigned.all;
            use ieee.std_logic_arith.all;

            ENTITY divider IS

                PORT(
                            Clock               :IN STD_LOGIC;
                            Dividend            :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
                            Divisor         :IN STD_LOGIC_VECTOR(4 DOWNTO 0);
                            Reset               :IN STD_LOGIC;
                            St                  :IN STD_LOGIC;

                            outDRegister            :OUT STD_LOGIC_VECTOR(8 DOWNTO 0):="000000000";
                            outCurrentState         :OUT STD_LOGIC_VECTOR(2 DOWNTO 0):="000";
                            Quotient            :OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
                            Remainder       :OUT STD_LOGIC_VECTOR(4 DOWNTO 0));
            END divider;

            ARCHITECTURE Behavior of divider IS

            SIGNAL DRegister                        :STD_LOGIC_VECTOR(8 DOWNTO 0);
            SIGNAL SubOut                           :STD_LOGIC_VECTOR(4 DOWNTO 0);
            Signal C,ShiftIn, ShiftRes          :STD_LOGIC;
            Signal ShiftEnable                  :STD_LOGIC;
            Signal tempSt                           :STD_LOGIC:='1';
            TYPE    State_type IS (S0, S1, S2, S3, S4, S5);
            SIGNAL y:State_type:=S0;

            BEGIN
            PROCESS(Dividend,Divisor,y, st, reset, clock) IS
            BEGIN
            If (Reset='0') THEN
            Y<=S0;
            ELSIF (Clock'EVENT and CLOCK = '1') THEN

                CASE y IS
                    WHEN S0=>
                        IF(st='0' AND tempSt='1' AND reset = '1') THEN
                            DRegister <= '0'&Dividend;
                            y<=S1;
                        ELSIF(st='1' AND reset = '1') THEN
                            Quotient    <= DRegister(3 DOWNTO 0);
                            Remainder   <= DRegister(8 DOWNTO 4);
                            y<=S0;
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="000";
                        tempSt<=st; 

                    WHEN S1=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            y<=S0;
                        ELSE
                            DRegister <= (DRegister(7 DOWNTO 0) & '0');
                            y<=S2;
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="001";
                    WHEN S2=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                            DRegister <= DRegister(7 DOWNTO 0) & '1';
                        ELSE
                            DRegister <= DRegister(7 DOWNTO 0) & '0';
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="010";     
                        y<=S3;

                    WHEN S3=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                            DRegister <= DRegister(7 DOWNTO 0) & '1';
                        ELSE
                            DRegister <= DRegister(7 DOWNTO 0) & '0';

                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="011";
                        y<=S4;

                    WHEN S4=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                            DRegister <= DRegister(7 DOWNTO 0) & '1';
                        ELSE
                            DRegister <= DRegister(7 DOWNTO 0) & '0';
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="100";
                        y<=S5;

                    WHEN S5=>   
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="101";

                        y<=S0;

                END CASE;

            END IF;




            END PROCESS;


            END Behavior;

2 Answers2

0

First step is to read up on the difference between variable and signal assignment in VHDL. Your problem lies there. One solution involves an intermediate variable for the problem states; another involves rewriting a signal assignment.

My usual explanation is here, there's a link at the bottom of the page to "VHDL's Crown Jewel" which is also very well worth reading.

Also note:

  • There are better libraries for arithmetic : ieee.numeric_std rather than std_logic_unsigned or std_logic_arith or (worst of all) mixing the two.
  • There are better data type for arithmetic than std_logic_vector : ieee.numeric_std.unsigned (or signed), or even subtypes of integer or natural;
  • As you are writing a nice clean single-process state machine, its sensitivity list ONLY needs clock, reset
  • You can lose the parentheses around conditional expressions, If Reset='0' Then is fine (this is not your father's C compiler)
  • rising_edge(Clock) is preferred to Clock'EVENT and CLOCK = '1'
    but these are all peripheral to the main issue.
Community
  • 1
  • 1
0

The problematic code part, as you also marked, is:

...
DRegister(8 downto 4) <= (DRegister(8 downto 4) - Divisor);  --Does not work!! Does nothing.
DRegister             <= DRegister(7 downto 0) & '1';
...

In VHDL, the value of a signal is not updated until the end of the current simulation cycle, so the value of DRegister used in the second assign to DRegister above is not altered by the first assign to DRegister.

So, the effect of the first assign to DRegister(8 downto 4) is overridden by the second assign to all bits in DRegister, whereby the subtraction of the Divisor does not have any effect.

One way to correct the code, so to make only a single assign to all DRegister bits.

You may want to take a look at David Koontz answer at https://stackoverflow.com/a/20104800/2352082 since this covers a similar issue.

Community
  • 1
  • 1
Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49