Output is always zeros (quotient and remainder) in the code shown below. Even if I assign value of b to remainder,it is giving 0. I have checked for many times but I am not able to understand what the issue is. While compiling, it is showing 2 warnings:
- Initial value of "b" depends on value of signal "divisor".
What is the problem?
-- DIVIDER
library ieee;
use ieee.numeric_bit.all;
entity unsigned_divider is
port(
-- the two inputs
dividend: in bit_vector(15 downto 0);
divisor : in bit_vector(15 downto 0);
-- the two outputs
quotient : out bit_vector(15 downto 0);
remainder : out bit_vector(15 downto 0)
);
end entity unsigned_divider;
architecture behave of unsigned_divider is
begin
process
variable a : bit_vector(15 downto 0):=dividend;
variable b : bit_vector(15 downto 0):=divisor;
variable p : bit_vector(15 downto 0):= (others => '0');
variable i : integer:=0;
begin
for i in 0 to 15 loop
p(15 downto 1) := p(14 downto 0);
p(0) := a(15);
a(15 downto 1) := a(14 downto 0);
p := bit_vector(unsigned(p) - unsigned(b));
if(p(15) ='1') then
a(0) :='0';
p := bit_vector(unsigned(p) + unsigned(b));
else
a(0) :='1';
end if;
wait for 1 ns;
end loop;
quotient <= a after 1 ns;
remainder <= p after 1 ns;
end process;
end behave;
You should have explicit assignments to the variables a and b inside the process statement part (as sequential signal assignments). The declarations:
variable a : bit_vector(15 downto 0):=dividend;
variable b : bit_vector(15 downto 0):=divisor;
Should be:
variable a : bit_vector(15 downto 0);
variable b : bit_vector(15 downto 0);
And in the process statement part (following the begin in the process):
a := dividend;
b := divisor;
These overcome the issue natipar mentions, that the values are only assigned to a and b during initialization.
Further should you desire to have a 1 ns delay you should have an explicit wait statement as the last sequential statement of the process statement process statement part:
wait on dividend, divisor;
These make your process statement look something like this (with indentation added):
process
variable a : bit_vector(15 downto 0); -- := dividend;
variable b : bit_vector(15 downto 0); -- := divisor;
variable p : bit_vector(15 downto 0) := (others => '0');
variable i : integer := 0;
begin
a := dividend;
b := divisor;
for i in 0 to 15 loop
p(15 downto 1) := p(14 downto 0);
p(0) := a(15);
a(15 downto 1) := a(14 downto 0);
p := bit_vector(unsigned(p) - unsigned(b));
if p(15) = '1' then
a(0) :='0';
p := bit_vector(unsigned(p) + unsigned(b));
else
a(0) := '1';
end if;
wait for 1 ns;
end loop;
quotient <= a after 1 ns;
remainder <= p after 1 ns;
wait on dividend, divisor;
end process;
(Note the space between the numeric literal and the units, required by IEEE Std 1076-2008, 15.3 Lexical elements, separators and delimiters paragraph 4, the last sentence "At least one separator is required between an identifier or an abstract literal and an adjacent identifier or abstract literal.", despite Modelsim not requiring it).
Writing a simple testbench we find at least one error in your restoring division algorithm:
entity unsigned_divider_tb is
end entity;
architecture foo of unsigned_divider_tb is
signal dividend, divisor: bit_vector (15 downto 0) := (others => '0');
signal quotient, remainder: bit_vector (15 downto 0);
function to_string(inp: bit_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: bit_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(BIT'IMAGE(input_str(i)));
end loop;
return image_str;
end;
begin
DUT:
entity work.unsigned_divider
port map (
dividend,
divisor,
quotient,
remainder
);
MONITOR:
process (quotient, remainder)
begin
report "quotient = " & to_string (quotient) severity NOTE;
report "remainder = " & to_string (remainder) severity NOTE;
end process;
end architecture;
ghdl -a unsigned_divider.vhdl
ghdl -e unsigned_divider_tb
ghdl -r unsigned_divider_tb
unsigned_divider.vhdl:83:9:@0ms:(report note): quotient = 0000000000000000
unsigned_divider.vhdl:84:9:@0ms:(report note): remainder = 0000000000000000
unsigned_divider.vhdl:83:9:@17ns:(report note): quotient = 1111111111111111
unsigned_divider.vhdl:84:9:@17ns:(report note): remainder = 0000000000000000
(And a note on interpretation, the transactions reported at time 0 ms are the default assignments performed as a result of elaboration).
Your algorithm gives a wrong answer for division by 0.
Adding a stimulus process to the testbench:
STIMULUS:
process
begin
wait for 20 ns;
dividend <= x"ffff";
divisor <= x"000f";
end process;
Shows it can get the right answer too:
unsigned_divider.vhdl:83:9:@37ns:(report note): quotient = 0001000100010001
unsigned_divider.vhdl:84:9:@37ns:(report note): remainder = 0000000000000000
And with the testbench and added wait statements and assignments in the stimulus process you can explore further.
I've always been a fan of non-restoring division myself, because the adds or subtracts take a clock in a clocked divider.