convert from verilog to vhdl

M

Mat18111992

Guest
Hello everyone. I had a code for fixed point division by Verilog. I tried to rewrite it with VHDL but not successfull. Can somebody help me? Thanks so much.


module division #(
//Parameterized values
parameter Q = 4, // number of fraction bits
parameter N = 8
)
(
input [N-1:0] i_dividend,
input [N-1:0] i_divisor,
input i_start,
input i_clk,
output [N-1:0] o_quotient_out,
output o_complete,
output o_overflow
);

reg [2*N+Q-3:0] reg_working_quotient;// Our working copy of the quotient
reg [N-1:0] reg_quotient; // Final quotient
reg [N-2+Q:0] reg_working_dividend;// Working copy of the dividend
reg [2*N+Q-3:0] reg_working_divisor; // Working copy of the divisor

reg [$clog2(N-1+Q):0] reg_count;

reg reg_done; // Computation completed flag
reg reg_sign; // The quotient's sign bit
reg reg_overflow; // Overflow flag


initial reg_done = 1'b1;
initial reg_overflow = 1'b0;
initial reg_sign = 1'b0;
initial reg_working_quotient = 0;
initial reg_quotient = 0;
initial reg_working_dividend = 0;
initial reg_working_divisor = 0;
initial reg_count = 0;


assign o_quotient_out[N-2:0] = reg_quotient[N-2:0];//division results
assign o_quotient_out[N-1] = reg_sign; //The sign of the quotient
assign o_complete = reg_done;
assign o_overflow = reg_overflow;

always @( posedge i_clk ) begin
if( reg_done && i_start ) begin //This is our startup condition

reg_done<=1'b0; reg_count<=N+Q-1; reg_working_quotient<=0; reg_working_dividend<=0; reg_working_divisor<=0; reg_overflow <= (i_divisor[N-2:0])?1'b0:1'b1;// check divisor =0 or !=0
reg_working_dividend[N+Q-2:Q] <= i_dividend[N-2:0];
reg_working_divisor[2*N+Q-3:N+Q-1] <= i_divisor[N-2:0];
reg_sign <= i_dividend[N-1] ^ i_divisor[N-1];

end
else if(!reg_done) begin

reg_working_divisor <= reg_working_divisor >> 1;

if(reg_working_dividend >= reg_working_divisor) begin

reg_working_quotient[reg_count<=1'b1; reg_working_dividend <= reg_working_dividend - reg_working_divisor;

end


if(!(reg_count | 0)) begin //count = 0

reg_done<=1'b1;
reg_quotient <= reg_working_quotient;
reg_overflow <= (reg_working_quotient[2*N+Q-3:N]) ? 1'b1 : 1'b0;

end
else

reg_count <= reg_count - 1;

end
end
endmodule
 
Am Dienstag, 21. Juli 2015 10:32:22 UTC+2 schrieb Mat18111992:
> Hello everyone. I had a code for fixed point division by Verilog. I tried to rewrite it with VHDL but not successfull. Can somebody help me? Thanks so much.

Are you looking for someone to write the same code in VHDL? Than it helps to write something about the amount of money you like to spend.

If you like to have free help, you might get more information when asking specific questions. Maybe add your VHDL code as well and present the points where you had trouble. Or start with concrete points you need help with.

Quick and dirty: Open Synthesis tool, read verilog, perform synthesis and write out vhdl.

regards,

Thomas
 
Thanks Thomas.
Here are VHDL code and testbench of mine. When I run simulation, I get an error :"Fatal: (vsim-3420) Array lengths do not match. Left is 11 (10 downto 0). Right is 18 (17 downto 0)." Can you give me some indication?
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use ieee.math_real.all;

entity division_m is
generic(
INPUT_WIDTH : integer :=8;
FRAC : integer :=4);
port (
clk : in std_logic;
reset : in std_logic;
dividend : in signed(INPUT_WIDTH-1 downto 0);
divisor : in signed(INPUT_WIDTH-1 downto 0);
quotient : out signed(INPUT_WIDTH-1 downto 0)
--overflow : out std_logic
) ;
end entity ; -- division_m

architecture behavior of division_m is

begin
divider : process( clk, reset )
variable dividend_reg : signed(INPUT_WIDTH+FRAC-2 downto 0);
variable divisor_reg : signed(2*INPUT_WIDTH+FRAC-3 downto 0);
variable quotient_reg : signed(2*INPUT_WIDTH+FRAC-3 downto 0);

begin
if rising_edge(clk) then
if reset = '1' then
quotient <= (others => '0');
else
dividend_reg := dividend(INPUT_WIDTH-2 downto 0)&(FRAC-1 downto 0 =>'0');
divisor_reg := divisor(INPUT_WIDTH-2 downto 0)&(INPUT_WIDTH+FRAC-2 downto 0 => '0');
for i in INPUT_WIDTH+FRAC-1 downto 0 loop
divisor_reg := divisor_reg sll 1;
if (dividend_reg >= divisor_reg) then
quotient_reg(i) := '1';
dividend_reg := dividend_reg - divisor_reg;
else
quotient_reg(i) := '0';
end if ;
end loop ;
quotient(INPUT_WIDTH-1) <= dividend(INPUT_WIDTH-1) xor divisor(INPUT_WIDTH-1);
quotient(INPUT_WIDTH-2 downto 0) <= quotient_reg(INPUT_WIDTH-2 downto 0);
end if ;
end if ;
end process ; -- divider
end architecture ; -- behavior

Testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity division_m_tb is
end division_m_tb;

architecture behavioral of division_m_tb is

component division_m
generic (
INPUT_WIDTH : integer;
FRAC : integer);
port (
clk : in std_logic;
reset : in std_logic;
dividend : in signed(INPUT_WIDTH-1 downto 0);
divisor : in signed(INPUT_WIDTH-1 downto 0);
quotient : out signed(INPUT_WIDTH-1 downto 0));
end component;

-- component generics
constant INPUT_WIDTH : integer := 8;
constant FRAC : integer := 4;

-- component ports
signal reset : std_logic;
signal dividend : signed(INPUT_WIDTH-1 downto 0);
signal divisor : signed(INPUT_WIDTH-1 downto 0);
signal quotient : signed(INPUT_WIDTH-1 downto 0);
-- clock
signal clk : std_logic := '1';

begin -- behavioral

-- component instantiation
DUT : division_m
generic map (
INPUT_WIDTH => INPUT_WIDTH,
FRAC => FRAC)
port map (
clk => clk,
reset => reset,
dividend => dividend,
divisor => divisor,
quotient => quotient);

-- clock generation
clk <= not clk after 10 ns;

-- waveform generation
WaveGen_Proc : process
begin
--signal assignments
reset <= '1';
--data_in <= (others => '0');
wait for 20 ns;
wait until rising_edge(clk);
reset <= '0';
dividend <= "01110000"; --7
divisor <= "00100000"; --2
wait until rising_edge(clk);
dividend <= "01001000"; --4,5
divisor <= "00100000"; --2
wait until rising_edge(clk);
dividend <= "01011000"; --5,5
divisor <= "00101100"; --2,75
wait until rising_edge(clk);
dividend <= "01101110"; --6,875
divisor <= "00110000"; --3
--wait until rising_edge(clk);
--data_in <= (others => '0');
wait;
end process WaveGen_Proc;

end behavioral;
 
Am Dienstag, 21. Juli 2015 13:53:56 UTC+2 schrieb Mat18111992:
Thanks Thomas.
Here are VHDL code and testbench of mine. When I run simulation, I get an error :"Fatal: (vsim-3420) Array lengths do not match. Left is 11 (10 downto 0). Right is 18 (17 downto 0)." Can you give me some indication?

You missed to post the line number for that error. Open editor go to that line number. You will see there something like
Left <= Right ( might be ":=" for variables insterad of "<=")
with Left beeing vector of 11 bit and right of 18 bit width. This is impossible in VHDL (and common mistake). In your code Divisor and Quotient are good candidates for 18 bit width.

regards Thomas
 
Thomas.
Below is the code I have rewritten to implement pipelined module fixed-point division. Signal quotient_reg was calculated correctly but when I use the assignment sentence :
" quotient(INPUT_WIDTH-2 downto 0) <= std_logic_vector(quotient_reg(INPUT_WIDTH-2 downto 0));"

The output signal (quotient) is not correct, it get unknown value.
How I fix this error?
Thanks again!!

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity division is
generic(
INPUT_WIDTH : integer :=8;
FRAC : integer :=4);
port (
clk : in std_logic;
reset : in std_logic;
dividend : in std_logic_vector(INPUT_WIDTH-1 downto 0);
divisor : in std_logic_vector(INPUT_WIDTH-1 downto 0);
quotient : out std_logic_vector(INPUT_WIDTH-1 downto 0)
) ;
end entity ; -- division

architecture behavior of division is
constant N : integer := INPUT_WIDTH+FRAC-1;
constant K : integer := 2*INPUT_WIDTH+FRAC-3;
type dividend_array is array (0 to N) of unsigned(K downto 0);
type divisor_array is array (0 to N) of unsigned(K downto 0);
signal dividend_reg : dividend_array;
signal divisor_reg : divisor_array;
signal quotient_reg : std_logic_vector(N-1 downto 0);
begin
divider : process( clk, reset )

variable tmp : unsigned(K downto 0);

begin
if rising_edge(clk) then
if reset = '1' then
quotient <= (others => '0');
quotient_reg <= (others => '0');
dividend_reg <= (others =>(others => '0'));
divisor_reg <= (others =>(others => '0'));
else
dividend_reg(N) <= (K downto N => '0') & unsigned(dividend(INPUT_WIDTH-2 downto 0)) & (FRAC-1 downto 0 =>'0');
divisor_reg(N) <= unsigned(divisor(INPUT_WIDTH-2 downto 0)) & (N-1 downto 0 => '0');
quotient_reg <= (others => '0');

for i in N-1 downto 0 loop
tmp := '0'&divisor_reg(i+1)(K downto 1);
if (std_logic_vector(dividend_reg(i+1)) >= std_logic_vector(tmp)) then
quotient_reg(i) <= '1';
dividend_reg(i) <= dividend_reg(i+1) - tmp;
divisor_reg(i) <= '0'&divisor_reg(i+1)(K downto 1);
else
quotient_reg(i) <= '0';
dividend_reg(i) <= dividend_reg(i+1);
divisor_reg(i) <= '0'&divisor_reg(i+1)(K downto 1);
end if ;
end loop;
end if ;
end if ;
end process ; -- divider
quotient(INPUT_WIDTH-1) <= dividend(INPUT_WIDTH-1) xor divisor(INPUT_WIDTH-1);
quotient(INPUT_WIDTH-2 downto 0) <= std_logic_vector(quotient_reg(INPUT_WIDTH-2 downto 0));
end architecture ; -- behavior

Testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity division_tb is
end division_tb;

architecture behavioral of division_tb is

component division
generic (
INPUT_WIDTH : integer;
FRAC : integer);
port (
clk : in std_logic;
reset : in std_logic;
dividend : in std_logic_vector(INPUT_WIDTH-1 downto 0);
divisor : in std_logic_vector(INPUT_WIDTH-1 downto 0);
quotient : out std_logic_vector(INPUT_WIDTH-1 downto 0));
end component;

-- component generics
constant INPUT_WIDTH : integer := 8;
constant FRAC : integer := 4;

-- component ports
signal reset : std_logic;
signal dividend : std_logic_vector(INPUT_WIDTH-1 downto 0);
signal divisor : std_logic_vector(INPUT_WIDTH-1 downto 0);
signal quotient : std_logic_vector(INPUT_WIDTH-1 downto 0);
-- clock
signal clk : std_logic := '1';

begin -- behavioral

-- component instantiation
DUT : division
generic map (
INPUT_WIDTH => INPUT_WIDTH,
FRAC => FRAC)
port map (
clk => clk,
reset => reset,
dividend => dividend,
divisor => divisor,
quotient => quotient);

-- clock generation
clk <= not clk after 10 ns;

-- waveform generation: execute 7/2=3.5
WaveGen_Proc : process
begin
--signal assignments
reset <= '1';
--data_in <= (others => '0');
wait for 20 ns;
wait until rising_edge(clk);
reset <= '0';
dividend <= "01110000"; --7
divisor <= "00100000"; --2
wait;
end process WaveGen_Proc;

end behavioral;
 

Welcome to EDABoard.com

Sponsor

Back
Top