std_logic_vector VHDL的除数

时间:2017-10-24 11:03:26

标签: vhdl greatest-common-divisor ghdl

我尝试使用语言std_logic_vector实现VHDL的除数。 在我实现它之后,我必须使用GHDL但遇到了这个错误:

vhdl:error: bound check failure at divisor.vhdl

这与此相对应:

else ....
nb_reg <= (2*nb);

我的代码是:

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


entity div is 
    generic 
    (
        DATA_WIDTH : natural := 8;
        ADDR_WIDTH : natural := 3
    );

    port (
        clk     : in std_logic;
        reset   : in std_logic;
        raddr   : in natural range 0 to 2**ADDR_WIDTH - 1;
        waddr   : in natural range 0 to 2**ADDR_WIDTH - 1;
        max     : in std_logic_vector((DATA_WIDTH -1) downto 0);
        data    : in std_logic_vector((DATA_WIDTH -1) downto 0);
        q       : out std_logic_vector((DATA_WIDTH -1) downto 0)

        );

end div;

architecture rtl of div is

    -- Build a 2-D array type for the RAM
    subtype word_t is unsigned((DATA_WIDTH-1) downto 0);
    type memory_t is array(natural range <>) of word_t;

    -- Declare the RAM signal.  
    signal ram, div : memory_t((2**ADDR_WIDTH)-1 downto 0);

    -- Declare the n and max_reg signal.    
    signal n,m : unsigned(((2*DATA_WIDTH)-1) downto 0);
    signal max_reg : unsigned(((2*DATA_WIDTH)-1) downto 0);
    signal nb : unsigned(((2*DATA_WIDTH)-1) downto 0);
    signal nb_reg : unsigned(((4*DATA_WIDTH)-3) downto 0);

    -- Build div_reg, ram_reg
    type memory_reg is array(natural range <>) of unsigned(((2*DATA_WIDTH)-1) downto 0);

    signal ram_reg: memory_reg((2**ADDR_WIDTH)-1 downto 0);

begin
    process(clk,reset)
    begin 
    if (reset = '1') then 
            ram(waddr) <= X"00";
            div(waddr) <= X"00";
            max_reg <= X"0000";
            ram_reg(waddr) <= X"0000";
            n <= X"0000";
            nb <= X"0000";
            --nb_reg(((4*DATA_WIDTH)-3) downto 0) <= "0";
            m <= X"0000";
    elsif(rising_edge(clk)) then 
        ram(waddr) <= unsigned(data);
        max_reg((DATA_WIDTH -1) downto 0) <= unsigned(max);
        ram_reg(waddr)((DATA_WIDTH-1) downto 0) <= ram(waddr)((DATA_WIDTH-1) downto 0);
        nb <= (nb+1);
        if (ram(waddr) = max_reg)then 
            div(waddr) <= div(waddr)+1;
        elsif (ram(waddr) > max_reg)then
            while ((div(waddr)*(ram(waddr)) > max_reg) or (m <(DATA_WIDTH -1))) loop
                div(waddr) <= (div(waddr))+1;
                max_reg <= (max_reg) - (ram_reg(waddr));
                m <= m+1; 
            end loop;
            m <= (m-1);
            while (((div(waddr)*ram_reg(waddr)) < max_reg-1) or (n <(DATA_WIDTH)-(m))) loop
                ram_reg(waddr)(((2*DATA_WIDTH)-1) downto 1) <= ram_reg(waddr)(((2*DATA_WIDTH)-2) downto 0);
                ram_reg(waddr)(0) <= '0';
                n <= n+1; 
                nb_reg <= (nb*2);
                nb(((2*DATA_WIDTH)-1) downto 0) <= nb_reg(((2*DATA_WIDTH)-1) downto 0);
            end loop;
            ram_reg(waddr) <= ram_reg(waddr) - (max_reg);
            div(waddr) <= (div(waddr))+(1/(nb));
        else 
            while (((div(waddr)*ram_reg(waddr)) < max_reg-1) or (n <(DATA_WIDTH)-(m))) loop
                ram_reg(waddr)(((2*DATA_WIDTH)-1) downto 1) <= ram_reg(waddr)(((2*DATA_WIDTH)-2) downto 0);
                ram_reg(waddr)(0) <= '0';
                n <= n+1; 
                nb_reg <= (2*nb);
                nb(((2*DATA_WIDTH)-1) downto 0) <= nb_reg(((2*DATA_WIDTH)-1) downto 0);
            end loop;
            ram_reg(waddr) <= ram_reg(waddr) - (max_reg);
            div(waddr) <= (div(waddr))+(1/(nb));
        end if;
    else null;
    end if;

    end process;

    q <= std_logic_vector(div(waddr));

end rtl;

测试台:

-- descrizione del Test_bench
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity div_tb is
end div_tb;

architecture behaviour of div_tb is

--dichiarazione dei COMPONENT ovvero la Unit Under Test
component div is

    generic 
    (
        DATA_WIDTH : natural := 8;
        ADDR_WIDTH : natural := 3
    );

    port 
    (
        clk     : in std_logic;
        reset   : in std_logic;
        raddr   : in natural range 0 to 2**ADDR_WIDTH - 1;
        waddr   : in natural range 0 to 2**ADDR_WIDTH - 1;
        max     : in std_logic_vector((DATA_WIDTH -1) downto 0);
        data    : in std_logic_vector((DATA_WIDTH -1) downto 0);
        q       : out std_logic_vector((DATA_WIDTH -1) downto 0)
    );
end component;

-- Clock period definitions
constant clk_period : time := 1 us; 

constant DATA_WIDTH : natural := 8;
constant ADDR_WIDTH : natural := 3;
signal CLK_tb: std_logic := '0';
signal RESET_tb: std_logic := '1';
signal raddr_tb, waddr_tb : natural range 0 to 2**ADDR_WIDTH - 1;
signal data_tb, q_tb, max_tb : std_logic_vector((DATA_WIDTH -1) downto 0);

signal I : integer := 0; -- variabile per il conteggio dei clock

begin
        clk_process: process --processo di generazione del CLK
        begin
            CLK_tb <= '0';
            wait for clk_period/2;
            CLK_tb <= '1';
            wait for clk_period/2;
            I<=I+1;

            if I=200 then wait; -- durata della simulazione: 30 colpi di CLK
            else null;
            end if;

        end process;

    -- istanziazione della Unit Under Test
    UUT: div    generic map (ADDR_WIDTH => 3, DATA_WIDTH => 8)
                port map (clk=>clk_tb, reset=>RESET_tb, raddr => raddr_tb, waddr => waddr_tb , data => data_tb, q => q_tb, max => max_tb);  

    stimoli: process
    begin       
        RESET_tb <= '1';
        wait for clk_period*3;
        RESET_tb <= '0';
        wait;       
    end process;


    we: process
    begin       
        max_tb <= "11100110";
        wait;       
    end process;

    Data : process
    begin   
        data_tb <= "00000000"; raddr_tb <= 0; waddr_tb <= 0; wait for clk_period*3;
        data_tb <= "01010110"; raddr_tb <= 1; waddr_tb <= 1; wait for clk_period*8; 
        data_tb <= "01000110"; raddr_tb <= 2; waddr_tb <= 2; wait for clk_period*8; 
        data_tb <= "11001110"; raddr_tb <= 3; waddr_tb <= 3; wait for clk_period*8; 
        data_tb <= "01000111"; raddr_tb <= 4; waddr_tb <= 4; wait for clk_period*8;
        data_tb <= "11100110"; raddr_tb <= 5; waddr_tb <= 5; wait for clk_period*8; 
        data_tb <= "01000110"; raddr_tb <= 6; waddr_tb <= 6; wait for clk_period*8; 
        data_tb <= "01010110"; raddr_tb <= 7; waddr_tb <= 7; wait for clk_period*8; 
        wait;
    end process;

end behaviour;

我使用GHDL的2007版本,我无法更新,我的老师要我使用这个版本。

有人可以帮我这个代码吗?

1 个答案:

答案 0 :(得分:0)

Booking.payment_authorized.or(Booking.payment_captured)包中的乘法运算符定义为numeric_std乘以natural

unsigned

如您所见,输出是 -- Id: A.18 function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0) -- Result: Multiplies an UNSIGNED vector, R, with a nonnegative -- INTEGER, L. L is converted to an UNSIGNED vector of -- SIZE R'LENGTH before multiplication. 参数宽度的两倍减去1.在此行中

unsigned

您要将结果分配回nb <= std_logic_vector(2*unsigned(nb)); 操作数,这显然与自身的宽度不同。

那么,您需要一个正确宽度的中间变量,还是需要左移?