G
Gabriel Schuster
Guest
Hi everybody,
I've got a little problem with the division module (part of a
microcontroller alu) in my current project: I found a nice code sample
in the www implementing a similar module.
Originally ieee.std_logic_arith was used to create it, which I strictly
avoid in my project so I rewrote the divider module using
ieee.numeric_std... but unfortunately it doesn't work so far.
I think there's something wrong in the assignments / conversion between
std_logic_vector and unsigned. I'd appreciate any help, because I'm used
to work with std_logic_arith and I think I'll have more of these
conversion problems in the near future.
How is this conversion done the right way???
Here are the sources of the two divider modules. I also got two
testbenches, which I can add.
Thanks
Gabriel
=====================WORKING=========================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity divider is
generic (DWIDTH : integer := 8);
port (dvdnd_i : in std_logic_vector(DWIDTH-1 downto 0); -- Dividend
dvsor_i : in std_logic_vector(DWIDTH-1 downto 0); -- Divisor
qutnt_o : out std_logic_vector(DWIDTH-1 downto 0); --
Quotient
rmndr_o : out std_logic_vector(DWIDTH-1 downto 0);
ov_o : out std_logic); -- Remainder
end divider;
architecture rtl of divider is
begin -- rtl
ov_o <= '1' when dvsor_i = "00000000" else '0';
-- purpose: Divide dvdnd_i through dvsor_i and deliver the result to
qutnt_o
-- and the remainder to rmndr_o.
-- type : combinational
-- inputs : dvdnd_i, dvsor_i
-- outputs: qutnt_o, rmndr_o
p_divide: process (dvdnd_i, dvsor_i)
variable v_actl_dvdnd : unsigned(DWIDTH-1 downto 0);
variable v_dffrnc : unsigned(DWIDTH-1 downto 0);
variable v_qutnt : unsigned(DWIDTH-1 downto 0);
begin -- process p_divide
v_actl_dvdnd := unsigned(dvdnd_i);
for i in DWIDTH-1 downto 0 loop
-- If the divisor can be subtracted from this part of the
dividend, then
-- the corresponding bit of the quotient has to be 1, otherwise 0.
if conv_std_logic_vector(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH) >=
dvsor_i then
-- Divisor can be subtracted
v_qutnt(i) := '1';
v_dffrnc := conv_unsigned(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH)
- unsigned(dvsor_i);
-- As long as this is not the last step of calculation, shift the
-- intermediate result.
if i /= 0 then
v_actl_dvdnd(DWIDTH-1 downto i) := v_dffrnc(DWIDTH-1-i downto 0);
v_actl_dvdnd(i-1) := dvdnd_i(i-1);
end if;
else
-- Divisor is greater than this part of the dividend.
v_qutnt(i) := '0';
v_dffrnc := conv_unsigned(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH);
end if;
end loop; -- i
rmndr_o <= std_logic_vector(v_dffrnc);
qutnt_o <= std_logic_vector(v_qutnt);
end process p_divide;
end rtl;
=============================NOT WORKING=============================
-- remark:
-- this is the numeric_std version
-- it's possible to simulate the other one with ghdl using --ieee=synopsis
-- but several people suggested to switch to the "real" ieee-stuff
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alu_div is
port (
op1_i : in std_logic_vector(7 downto 0); -- dividend
op2_i : in std_logic_vector(7 downto 0); -- divisor
resa_o : out std_logic_vector(7 downto 0); -- result
resb_o : out std_logic_vector(7 downto 0); -- remainder
ov_o : out std_logic
);
end alu_div;
architecture rtl of alu_div is
begin
ov_o <= '1' when (op2_i="00000000") else '0';
p_divide: process (op1_i,op2_i)
variable v_result : unsigned(7 downto 0);
variable v_remainder : unsigned(7 downto 0);
variable v_tmp : unsigned(7 downto 0);
begin
v_tmp := unsigned(op1_i);
for i in 7 downto 0 loop
if (std_logic_vector(v_tmp(7 downto i)) >= op2_i) then
v_result(i) := '1';
v_remainder := unsigned(v_tmp(7 downto i)) - unsigned(op2_i);
if (i /= 0) then
v_tmp(7 downto i) := v_remainder(7-i downto 0);
v_tmp(i-1) := op1_i(i-1);
end if;
else
v_result(i) := '0';
v_remainder := "00000000";
v_remainder(7-i downto 0) := unsigned(v_tmp(7 downto i));
--v_remainder := to_unsigned(to_integer(v_tmp(7 downto i)),8);
end if;
end loop; -- i
resa_o <= std_logic_vector(v_result);
resb_o <= std_logic_vector(v_remainder);
end process p_divide;
end rtl;
I've got a little problem with the division module (part of a
microcontroller alu) in my current project: I found a nice code sample
in the www implementing a similar module.
Originally ieee.std_logic_arith was used to create it, which I strictly
avoid in my project so I rewrote the divider module using
ieee.numeric_std... but unfortunately it doesn't work so far.
I think there's something wrong in the assignments / conversion between
std_logic_vector and unsigned. I'd appreciate any help, because I'm used
to work with std_logic_arith and I think I'll have more of these
conversion problems in the near future.
How is this conversion done the right way???
Here are the sources of the two divider modules. I also got two
testbenches, which I can add.
Thanks
Gabriel
=====================WORKING=========================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity divider is
generic (DWIDTH : integer := 8);
port (dvdnd_i : in std_logic_vector(DWIDTH-1 downto 0); -- Dividend
dvsor_i : in std_logic_vector(DWIDTH-1 downto 0); -- Divisor
qutnt_o : out std_logic_vector(DWIDTH-1 downto 0); --
Quotient
rmndr_o : out std_logic_vector(DWIDTH-1 downto 0);
ov_o : out std_logic); -- Remainder
end divider;
architecture rtl of divider is
begin -- rtl
ov_o <= '1' when dvsor_i = "00000000" else '0';
-- purpose: Divide dvdnd_i through dvsor_i and deliver the result to
qutnt_o
-- and the remainder to rmndr_o.
-- type : combinational
-- inputs : dvdnd_i, dvsor_i
-- outputs: qutnt_o, rmndr_o
p_divide: process (dvdnd_i, dvsor_i)
variable v_actl_dvdnd : unsigned(DWIDTH-1 downto 0);
variable v_dffrnc : unsigned(DWIDTH-1 downto 0);
variable v_qutnt : unsigned(DWIDTH-1 downto 0);
begin -- process p_divide
v_actl_dvdnd := unsigned(dvdnd_i);
for i in DWIDTH-1 downto 0 loop
-- If the divisor can be subtracted from this part of the
dividend, then
-- the corresponding bit of the quotient has to be 1, otherwise 0.
if conv_std_logic_vector(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH) >=
dvsor_i then
-- Divisor can be subtracted
v_qutnt(i) := '1';
v_dffrnc := conv_unsigned(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH)
- unsigned(dvsor_i);
-- As long as this is not the last step of calculation, shift the
-- intermediate result.
if i /= 0 then
v_actl_dvdnd(DWIDTH-1 downto i) := v_dffrnc(DWIDTH-1-i downto 0);
v_actl_dvdnd(i-1) := dvdnd_i(i-1);
end if;
else
-- Divisor is greater than this part of the dividend.
v_qutnt(i) := '0';
v_dffrnc := conv_unsigned(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH);
end if;
end loop; -- i
rmndr_o <= std_logic_vector(v_dffrnc);
qutnt_o <= std_logic_vector(v_qutnt);
end process p_divide;
end rtl;
=============================NOT WORKING=============================
-- remark:
-- this is the numeric_std version
-- it's possible to simulate the other one with ghdl using --ieee=synopsis
-- but several people suggested to switch to the "real" ieee-stuff
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alu_div is
port (
op1_i : in std_logic_vector(7 downto 0); -- dividend
op2_i : in std_logic_vector(7 downto 0); -- divisor
resa_o : out std_logic_vector(7 downto 0); -- result
resb_o : out std_logic_vector(7 downto 0); -- remainder
ov_o : out std_logic
);
end alu_div;
architecture rtl of alu_div is
begin
ov_o <= '1' when (op2_i="00000000") else '0';
p_divide: process (op1_i,op2_i)
variable v_result : unsigned(7 downto 0);
variable v_remainder : unsigned(7 downto 0);
variable v_tmp : unsigned(7 downto 0);
begin
v_tmp := unsigned(op1_i);
for i in 7 downto 0 loop
if (std_logic_vector(v_tmp(7 downto i)) >= op2_i) then
v_result(i) := '1';
v_remainder := unsigned(v_tmp(7 downto i)) - unsigned(op2_i);
if (i /= 0) then
v_tmp(7 downto i) := v_remainder(7-i downto 0);
v_tmp(i-1) := op1_i(i-1);
end if;
else
v_result(i) := '0';
v_remainder := "00000000";
v_remainder(7-i downto 0) := unsigned(v_tmp(7 downto i));
--v_remainder := to_unsigned(to_integer(v_tmp(7 downto i)),8);
end if;
end loop; -- i
resa_o <= std_logic_vector(v_result);
resb_o <= std_logic_vector(v_remainder);
end process p_divide;
end rtl;