长矢量的加法/减法中未使用的位

时间:2015-12-13 23:09:24

标签: vhdl

我尝试用VHDL编写ALU模块来计算复数。我试图保持一切简单,不要使用任何花哨的算法,如Booth或Vedic进行乘法运算。基本上,我使用简单的“+”,“ - ”,“*”运算符分为“记录”数组:

-- a complex number
    type ComplexNr is record
        Re : signed(3 downto 0);
        Im : signed(3 downto 0);
    end record;

对于加法/减法和乘法的输出结果,我使用相同长度的向量,因此输入向量的双倍大小,即如果Input_1和Input_2是4位,我的结果向量是8位长。现在,如果我进行乘法运算,一切正常,但是当我进行加法/减法时,未使用的位在iSim中显示为“U”。

乘法和加法的代码非常简单:

-- complex multiplication
function c_mult(a, b : ComplexNr) return Complex_res is
    variable RetVal : Complex_res;
begin
    RetVal.Re := a.Re * b.Re - a.Im * b.Im;
    RetVal.Im := a.Re * b.Im + a.Im * b.Re;
    return (RetVal);

end function c_mult;

-- complex addition
function c_add(a, b : ComplexNr) return Complex_res is
    variable RetVal : Complex_res;
begin
    RetVal.Re := a.Re + b.Re;
    RetVal.Im := a.Im + b.Im;
    return (RetVal);

end function c_add;

所以假设我用0010添加0001,我得到“0011UUUU”添加。你通常如何解决这个问题?我是否必须使用0显式初始化未使用的位?

下面是顶部设计,它调用加法/减法和乘法函数。请注意,我将结果向量初始化为零一次。 - 这还不够吗?如果需要,我将提供测试台,但我只分配X和Y值,这就是全部。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

library work;
use work.complex_numbers.all;

entity cmplx_arithm is
    Port(
        -- Inputs:
        CLK       : in  STD_LOGIC;
        X         : in  STD_LOGIC_VECTOR(3 downto 0);   -- real X
        X_i       : in  STD_LOGIC_VECTOR(3 downto 0);   -- imag X
        Y         : in  STD_LOGIC_VECTOR(3 downto 0);   -- real Y
        Y_i       : in  STD_LOGIC_VECTOR(3 downto 0);   -- iamg Y

        -- Outputs:
        mux_res_r : out STD_LOGIC_VECTOR(7 downto 0);   -- mux result
        mux_res_i : out STD_LOGIC_VECTOR(7 downto 0);
        add_res_r : out STD_LOGIC_VECTOR(7 downto 0);   -- add result
        add_res_i : out STD_LOGIC_VECTOR(7 downto 0);
        sub_res_r : out STD_LOGIC_VECTOR(7 downto 0);   -- sub result
        sub_res_i : out STD_LOGIC_VECTOR(7 downto 0)
    );
end cmplx_arithm;

architecture Behavioral of cmplx_arithm is

    -- set the result values to zero
     constant init_to_zero : Complex_res := (
                               Re => (others =>'0'),
                               Im => (others=> '0')
                               );


    signal A : ComplexNr;
    signal B : ComplexNr;

    signal resultMux : Complex_res := init_to_zero;
    signal resultAdd : Complex_res := init_to_zero;
    signal resultSub : Complex_res := init_to_zero;

begin
    A.Re <= signed(X);
    A.Im <= signed(X_i);
    B.Re <= signed(Y);
    B.Im <= signed(Y_i);

    -- multiplication
    process(clk)
    begin
        if (rising_edge(clk)) then
            resultMux <= c_mult(A, B);
        end if;
    end process;

    -- addition
    process(clk)
    begin
        if (rising_edge(clk)) then
            resultAdd <= c_add(A, B);
        end if;
    end process;

    -- subtraction
    process(clk)
    begin
        if (rising_edge(clk)) then
            resultSub <= c_sub(A, B);
        end if;
    end process;

    mux_res_r  <= std_logic_vector(resultMux.Re);
    mux_res_i  <= std_logic_vector(resultMux.Im);
    add_res_r  <= std_logic_vector(resultAdd.Re);
    add_res_i  <= std_logic_vector(resultAdd.Im);
    sub_res_r  <= std_logic_vector(resultSub.Re);
    sub_res_i  <= std_logic_vector(resultSub.Im);

end Behavioral;

1 个答案:

答案 0 :(得分:1)

您的c_add和(可能)c_sub未正确写入

function c_add(a, b : ComplexNr) return Complex_res is
    variable RetVal : Complex_res;
begin
    RetVal.Re := a.Re + b.Re;
    RetVal.Im := a.Im + b.Im;
    return (RetVal);

end function c_add;

您所关联的Complex_res的记录元素的长度是两倍长,但加法(和减法)的长度与任一操作数的最长长度相匹配(包numeric_std,signed&#34; +&#34; )。

您可以调整总和(和差异,显示c_add):

    resize(RetVal.Re := a.Re + b.Re,8);
    resize(RetVal.Im := a.Im + b.Im,8);

请注意,如果iSIM完全符合VHDL标准,您将获得运行时边界检查错误(除非禁用

ISim User Guide(UG660,v14.3)第3章编译和仿真,表3-7:fuse,vhpcomp和vlogcomp命令选项--rangecheck选项的条目告诉我们&#34; ISim总是将索引检查到数组中是否在允许的范围内。&#34;没有提到我可以发现有一个元素在表达式中为目标中的每个元素。

参见IEEE Std 106-2008,10.6.2简单变量赋值,10.6.2.1概述,第5段:

  

为了执行目标是变量名的变量赋值,首先计算变量名和表达式。然后检查表达式的值是否属于变量的子类型,除非是具有复合类型的变量(在这种情况下,赋值涉及子类型转换)。 ...

和10.6.2.2复合变量赋值:

  

如果赋值语句的目标是表示复合变量(包括切片)的名称,则分配给目标的值将隐式转换为复合变量的子类型;此子类型转换的结果将成为复合变量的新值。

     

这意味着复合变量的每个元素的新值由匹配元素(见9.2.3)在通过表达式求值获得的相应复合值中指定。子类型转换检查复合变量的每个元素在复合值中是否存在匹配元素,反之亦然。如果此检查失败,则会发生错误。

填写空白以创建Minimal, Complete, and Verifiable example

library ieee;
use ieee.numeric_std.all;

package complex_numbers is
    type ComplexNr is record
        Re: signed (3 downto 0);
        Im: signed (3 downto 0);
    end record;

    type Complex_res is record
        Re: signed (7 downto 0);
        Im: signed (7 downto 0);
    end record;

    function c_mult(a, b:  ComplexNr) return Complex_res;
    function c_add(a, b:  ComplexNr) return Complex_res;
    function c_sub(a, b:  ComplexNr) return Complex_res;
end package;

package body complex_numbers is
    -- complex multiplication
    function c_mult(a, b:  ComplexNr) return Complex_res is
        variable RetVal:  Complex_res;
    begin
        RetVal.Re := a.Re * b.Re - a.Im * b.Im;
        RetVal.Im := a.Re * b.Im + a.Im * b.Re;
        return (RetVal);
    end function c_mult;

    -- complex addition
    function c_add(a, b:  ComplexNr) return Complex_res is
        variable RetVal:  Complex_res;
    begin
        RetVal.Re := resize(a.Re + b.Re,8);
        RetVal.Im := resize(a.Im + b.Im,8);
        return (RetVal);
    end function c_add;

    -- complex subtraction
    function c_sub(a, b:  ComplexNr) return Complex_res is
        variable RetVal:  Complex_res;
    begin
        RetVal.Re := resize(a.Re - b.Re,8);
        RetVal.Im := resize(a.Im - b.Im,8);
        return (RetVal);
    end function c_sub;   
end package body;

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

library work;
use work.complex_numbers.all;

entity cmplx_arithm is
    port (
        -- Inputs:
        CLK:        in  std_logic;
        X:          in  std_logic_vector(3 downto 0);   -- real X
        X_i:        in  std_logic_vector(3 downto 0);   -- imag X
        Y:          in  std_logic_vector(3 downto 0);   -- real Y
        Y_i:        in  std_logic_vector(3 downto 0);   -- iamg Y

        -- Outputs:
        mult_res_r:  out std_logic_vector(7 downto 0);   -- mult result
        mult_res_i:  out std_logic_vector(7 downto 0);
        add_res_r:   out std_logic_vector(7 downto 0);   -- add result
        add_res_i:   out std_logic_vector(7 downto 0);
        sub_res_r:   out std_logic_vector(7 downto 0);   -- sub result
        sub_res_i:   out std_logic_vector(7 downto 0)
    );
end entity cmplx_arithm;

architecture Behavioral of cmplx_arithm is

    -- set the result values to zero
     constant init_to_zero:  Complex_res := (
                               Re => (others =>'0'),
                               Im => (others=> '0')
                               );

    signal A:  ComplexNr;
    signal B:  ComplexNr;

    signal resultmult:  Complex_res := init_to_zero;
    signal resultAdd:  Complex_res := init_to_zero;
    signal resultSub:  Complex_res := init_to_zero;

begin
    A.Re <= signed(X);
    A.Im <= signed(X_i);
    B.Re <= signed(Y);
    B.Im <= signed(Y_i);

    -- multiplication
    process(clk)
    begin
        if rising_edge(clk) then
            resultmult <= c_mult(A, B);
        end if;
    end process;

    -- addition
    process(clk)
    begin
        if rising_edge(clk) then
            resultAdd <= c_add(A, B);
        end if;
    end process;

    -- subtraction
    process(clk)
    begin
        if rising_edge(clk) then
            resultSub <= c_sub(A, B);
        end if;
    end process;

    mult_res_r  <= std_logic_vector(resultmult.Re);
    mult_res_i  <= std_logic_vector(resultmult.Im);
    add_res_r   <= std_logic_vector(resultAdd.Re);
    add_res_i   <= std_logic_vector(resultAdd.Im);
    sub_res_r   <= std_logic_vector(resultSub.Re);
    sub_res_i   <= std_logic_vector(resultSub.Im);

end architecture Behavioral;

library ieee;
use ieee.std_logic_1164.all;

entity cmplx_arithm_tb is
end entity;

architecture foo of cmplx_arithm_tb is
    signal clk:        std_logic := '0';
    signal x:          std_logic_vector(3 downto 0);
    signal x_i:        std_logic_vector(3 downto 0);
    signal y:          std_logic_vector(3 downto 0);
    signal y_i:        std_logic_vector(3 downto 0);

    signal mult_res_r:  std_logic_vector(7 downto 0);
    signal mult_res_i:  std_logic_vector(7 downto 0);
    signal add_res_r:   std_logic_vector(7 downto 0);
    signal add_res_i:   std_logic_vector(7 downto 0);
    signal sub_res_r:   std_logic_vector(7 downto 0);
    signal sub_res_i:   std_logic_vector(7 downto 0);
begin
DUT:
    entity work.cmplx_arithm
        port map (
            CLK => clk,
            X => x,
            X_i => x_i,
            Y => y,
            Y_i => y_i,
            mult_res_r => mult_res_r,
            mult_res_i => mult_res_i,
            add_res_r => add_res_r,
            add_res_i => add_res_i,
            sub_res_r => sub_res_r,
            sub_res_i => sub_res_i
        );

CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if now > 40 ns then
            wait;
        end if;
    end process;
STIMULUS:
    process
    begin
        wait for 10 ns;
        x <= "0100";
        x_i <= "0010";
        y <= "0010";
        y_i <= "0001";
        wait;
    end process;
end architecture;

给出:

cmplx_arithm_tb.png

(这是通过在带有GTKWave的Mac上的OS X上托管的ghdl-0.33完成的)