VHDL循环-仅完成最后一个增量

VHDL循环-仅完成最后一个增量,vhdl,Vhdl,我对下面代码中的for循环有一个问题-在模拟中,它显示循环的最后一个增量已经完成,例如: 对于我给出的输入(显然是w0、w1、w2的8位符号): 在输出端,我接收的是u=31,而不是u=94。 因此,方程式似乎是: u = (x2 * w2) - w0 而不是: u = (x1 * w1) + (x2 * w2) - w0 我知道VHDL中的循环与C中的循环工作方式不同,但变量的使用应该可以做到这一点。不幸的是,我遗漏了一些东西。可能是什么 LIBRARY IEEE; USE I

我对下面代码中的for循环有一个问题-在模拟中,它显示循环的最后一个增量已经完成,例如:

对于我给出的输入(显然是w0、w1、w2的8位符号):

在输出端,我接收的是
u=31
,而不是
u=94。
因此,方程式似乎是:

u = (x2 * w2) - w0
而不是:

u = (x1 * w1) + (x2 * w2) - w0
我知道VHDL中的循环与C中的循环工作方式不同,但变量的使用应该可以做到这一点。不幸的是,我遗漏了一些东西。可能是什么

  LIBRARY IEEE;
    USE IEEE.STD_LOGIC_1164.ALL;
    USE IEEE.NUMERIC_STD.ALL;

    ENTITY NeuronBehavioral IS
         GENERIC ( n: INTEGER := 1;
                      m: INTEGER := 2;
                      b: INTEGER := 8);
        PORT ( x1  : in   STD_LOGIC;
               x2  : in   STD_LOGIC;
               w0  : in   SIGNED (b-1 downto 0); --11100000 (-32)
               w1  : in   SIGNED (b-1 downto 0); --00111111  (63)
               w2  : in   SIGNED (b-1 downto 0); --00111111  (63)
               u   : out  STD_LOGIC_VECTOR (b-1 downto 0));
    END NeuronBehavioral;

    ARCHITECTURE Behavioral OF NeuronBehavioral IS
        TYPE weights IS ARRAY (1 TO n*m) OF SIGNED(b-1 DOWNTO 0);
        TYPE inputs IS ARRAY (1 TO m) OF SIGNED(b-1 DOWNTO 0);
        TYPE outputs IS ARRAY (1 TO n) OF SIGNED(b-1 DOWNTO 0);
    BEGIN
        PROCESS (w0, w1, w2, x1, x2)
            VARIABLE weight: weights;
            VARIABLE input: inputs;
            VARIABLE output: outputs;
            VARIABLE prod, acc: SIGNED(b-1 DOWNTO 0);
        BEGIN
            input(1)  := "0000000" & x1;
            input(2)  := "0000000" & x2;
            weight(1) := w1;
            weight(2) := w2;
            L1: FOR i IN 1 TO n LOOP
                acc := (OTHERS => '0');
                L2: FOR j IN 1 TO m LOOP
                    prod := input(j)*weight(m*(i-1)+j);
                    acc := acc + prod;
                END LOOP L2;
                output(i) := acc + w0;
            END LOOP L1;
            u <= STD_LOGIC_VECTOR(output(1));
        END PROCESS;
    END Behavioral;
IEEE库;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.NUMERIC_STD.ALL;
实体神经元是行为的
泛型(n:整数:=1;
m:整数:=2;
b:整数:=8);
端口(x1:STD_逻辑中;
x2:标准逻辑中;
w0:in签名(b-1降到0);--11100000(-32)
w1:in签名(b-1降到0);--00111111(63)
w2:in签名(b-1降到0);--00111111(63)
u:输出标准逻辑向量(b-1下降到0);
末端神经元行为;
神经元行为系统的结构
类型权重是有符号(b-1到0)的数组(1到n*m);
类型输入是有符号(b-1到0)的数组(1到m);
类型输出是有符号(b-1到0)的数组(1到n);
开始
过程(w0、w1、w2、x1、x2)
可变重量:重量;
变量输入:输入;
可变输出:输出;
可变产品,acc:有符号(b-1下降到0);
开始
输入(1):=“0000000”&x1;
输入(2):=“0000000”&x2;
重量(1):=w1;
重量(2):=w2;
L1:对于1到n循环中的i
acc:=(其他=>'0');
L2:对于1到m环路中的j
产品:=输入(j)*重量(m*(i-1)+j);
acc:=acc+prod;
端环L2;
输出(i):=acc+w0;
端环L1;
u‘0’;
信号w1:有符号(从7到0):=(其他=>'0');
信号w2:有符号(从7到0):=(其他=>0');
--输出
信号u:标准逻辑向量(7到0);
开始
--实例化被测单元(UUT)
uut:行为端口映射(
x1=>x1,
x2=>x2,
w0=>w0,
w1=>w1,
w2=>w2,
u=>u
);
--刺激过程
刺激程序:过程
开始
--保持复位状态100纳秒。
等待100纳秒;

x1问题最初没有提供答案,缺乏复制错误的方法,更不用说预期结果了。这并不是解决实际问题的全部障碍


有一个越界错误

prod := input(j) * weight( m * (i - 1) + j);
带符号类型的右侧表达式的长度为被乘数(
input(j)
)和乘数(
weight(m*(i-1)+j)
)长度之和

本标准要求检测通过评估赋值语句中右手表达式的投影输出波形产生的最终有效值,目标的每个元素都有一个匹配元素(见IEEE Std 1076-2008 14.7.3.4信号更新,-1993至-2002 12.6.2信号值的传播)

(当工具允许通过命令行标志或配置暂停执行此检查时,人们期望它在某个时候已经完成,并且消除它会提高性能。)

关于不需要MCVe,一些模拟器允许运行带有顶级端口的模型。可以通过为所有输入提供默认值来识别此问题。根据VHDL版本,带有to_字符串(输出(1)的报告语句可以显示原始引用答案

port ( 
    x1:   in   std_logic := '1'; -- default added
    x2:   in   std_logic := '1'; -- default added
    w0:   in   signed (b-1 downto 0) := to_signed(-32,b); --11100000 (-32) -- default added
    w1:   in   signed (b-1 downto 0) := to_signed(63, b); --00111111  (63)
    w2:   in   signed (b-1 downto 0) := to_signed(63, b); --00111111  (63)
    u:    out  std_logic_vector (b-1 downto 0)
);
当使用ghdl运行时,设计规范在循环L2中产生边界故障

在更改产品声明的未标记流程中:

    variable prod: signed(b * 2 - 1 downto 0);
以及分配给acc的任务:

                acc := acc + prod (b - 1 downto 0);
允许计算完成,生成

neuronbehavious.vhdl:58:9:@0ms:(报告注释):u=01011110

在流程中添加了最后一条语句:

        report "u = " & to_string (output(1));
对于不符合VHDL-2008的模拟器,可以将to_字符串函数添加到流程语句的声明区域:

        function to_string (inp: signed) return string is
            variable image_str: string (1 to inp'length);
            alias input_str:  signed (1 to inp'length) is inp;
        begin
            for i in input_str'range loop
                image_str(i) := character'value(std_ulogic'image(input_str(i)));
            end loop;
            return image_str;
        end function;
注:报告值是94的8位有符号值

此外,还应检查prod、acc和u的声明,以确保设计能够在w0、w1和w2的输入值范围内产生结果

VHDL不仅是强类型的,而且在数学意义上也很特殊。如果结果不正确,则是错误的,“*”运算符的乘积长度足以生成有效的数学结果。这可以在numeric_std包体中看到

根据上述设计规范,测试台可生产:

由于基于输入
x1
x2
)的
input(j)
只能是“00000000”或“00000000 1”),因此有一种替代上述更改的方法:

    prod :=  resize(input(j) * weight( m * (i - 1) + j), b);
可以调整乘法器结果的大小(采用最低有效b长度位)。最左边的乘法为0或1

由于
输入(j)
的值为零或一(作为8位有符号值),因此可以消除第一次乘法:

architecture foo of neuronbehavioral is
    type weights is array (1 to n*m) of signed(b-1 downto 0);
    -- type inputs is array (1 to m) of signed(b-1 downto 0); -- CHANGED
    type inputs is array (1 to m) of std_logic;
    type outputs is array (1 to n) of signed(b-1 downto 0);
begin
    process (w0, w1, w2, x1, x2)
        variable weight: weights;
        variable input: inputs;
        variable output: outputs;
        -- variable prod: signed(b * 2 - 1 downto 0);  -- RESTORED:
        variable prod: signed(b - 1 downto 0);
        variable acc: signed(b - 1 downto 0);

        function to_string (inp: signed) return string is
            variable image_str: string (1 to inp'length);
            alias input_str:  signed (1 to inp'length) is inp;
        begin
            for i in input_str'range loop
                image_str(i) := character'value(std_ulogic'image(input_str(i)));
            end loop;
            return image_str;
        end function;

    begin
        -- input(1)  := "0000000" & x1;  -- CHANGED
        -- input(2)  := "0000000" & x2;  -- CHANGED
        input := x1 & x2;    -- ADDED
        weight(1) := w1;
        weight(2) := w2;
l1: 
        for i in 1 to n loop
            acc := (others => '0');
l2: 
            for j in 1 to m loop
                if input(j) = '1' then   -- ADDED
                -- prod := input(j) * weight( m * (i - 1) + j); -- CHANGED
                    prod :=  weight(m * (i - 1) + j);  -- ADDED
                else                                   -- ADDED
                    prod := (others => '0');           -- ADDED
                end if;                                -- ADDED
                -- acc := acc + prod (b - 1 downto 0); -- RESTORED:
                acc := acc + prod;
            end loop l2;
            output(i) := acc + w0;
        end loop l1;
        u <= std_logic_vector(output(1));
        report "u = " & to_string (output(1));
    end process;

end architecture foo;
其中不使用乘法,所有静态索引元素在两个位置累积。
等待0 ns语句用于通过连续信号克服0延迟分配中的增量延迟。(某个地方有一些东西在做离散事件,例如
x1
x2
,如果没有其他目的的话。)

这给出了与上述相同的答案:


表示相同的硬件。

您能提供测试台吗?这段代码是用于合成的吗?这样做将非常消耗资源。你的要求是什么
ghdl -r neurontb
neuronbehavioral.vhdl:58:9:@0ms:(report note): u = 00000000
neuronbehavioral.vhdl:58:9:@100ns:(report note): u = 01011110
neuronbehavioral.vhdl:58:9:@200ns:(report note): u = 00011111
neuronbehavioral.vhdl:58:9:@300ns:(report note): u = 00011111
neuronbehavioral.vhdl:58:9:@400ns:(report note): u = 11100000
    prod :=  resize(input(j) * weight( m * (i - 1) + j), b);
architecture foo of neuronbehavioral is
    type weights is array (1 to n*m) of signed(b-1 downto 0);
    -- type inputs is array (1 to m) of signed(b-1 downto 0); -- CHANGED
    type inputs is array (1 to m) of std_logic;
    type outputs is array (1 to n) of signed(b-1 downto 0);
begin
    process (w0, w1, w2, x1, x2)
        variable weight: weights;
        variable input: inputs;
        variable output: outputs;
        -- variable prod: signed(b * 2 - 1 downto 0);  -- RESTORED:
        variable prod: signed(b - 1 downto 0);
        variable acc: signed(b - 1 downto 0);

        function to_string (inp: signed) return string is
            variable image_str: string (1 to inp'length);
            alias input_str:  signed (1 to inp'length) is inp;
        begin
            for i in input_str'range loop
                image_str(i) := character'value(std_ulogic'image(input_str(i)));
            end loop;
            return image_str;
        end function;

    begin
        -- input(1)  := "0000000" & x1;  -- CHANGED
        -- input(2)  := "0000000" & x2;  -- CHANGED
        input := x1 & x2;    -- ADDED
        weight(1) := w1;
        weight(2) := w2;
l1: 
        for i in 1 to n loop
            acc := (others => '0');
l2: 
            for j in 1 to m loop
                if input(j) = '1' then   -- ADDED
                -- prod := input(j) * weight( m * (i - 1) + j); -- CHANGED
                    prod :=  weight(m * (i - 1) + j);  -- ADDED
                else                                   -- ADDED
                    prod := (others => '0');           -- ADDED
                end if;                                -- ADDED
                -- acc := acc + prod (b - 1 downto 0); -- RESTORED:
                acc := acc + prod;
            end loop l2;
            output(i) := acc + w0;
        end loop l1;
        u <= std_logic_vector(output(1));
        report "u = " & to_string (output(1));
    end process;

end architecture foo;
architecture foo of neuronbehavioral is
    type weights is array (1 to n*m) of signed(b - 1 downto 0);
    type inputs is array (1 to m) of std_logic;
    type outputs is array (1 to n) of signed(b - 1 downto 0);
    signal weight: weights;
    signal input: inputs;
    signal output: outputs;

    function to_string (inp: signed) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  signed (1 to inp'length) is inp;
    begin
        for i in input_str'range loop
            image_str(i) := character'value(std_ulogic'image(input_str(i)));
        end loop;
        return image_str;
    end function;
begin
    weight <= w1 & w2;
    input  <= x1 & x2;

l1: 
    for i in 1 to n generate
        type accums is array (1 to m) of signed (b - 1 downto 0);
        signal accum: accums;

        function acc (inp: accums) return signed is
            variable retval: signed (b - 1 downto 0) := (others => '0');
        begin
            for i in accums'range loop
                retval := retval + inp(i);
            end loop;
            return retval;
        end function;
    begin
l2: 
        for j in 1 to m generate
            accum(j) <= weight(m * (i - 1) + j) when input(j) = '1' else
                        (others => '0');
        end generate;
        output(i) <= acc(accum) + w0;
    end generate;

    u <= std_logic_vector(output(1));

MONITOR:
    process
    begin
        wait on x1, x2, w0, w1, w2;
        wait for 0 ns;
        wait for 0 ns;
        wait for 0 ns;
        wait for 0 ns;
        report "u = " & to_string (output(1));
    end process;

end architecture foo;
ghdl -r neurontb
neuronbehavioral.vhdl:169:9:@100ns:(report note): u = 01011110
neuronbehavioral.vhdl:169:9:@200ns:(report note): u = 00011111
neuronbehavioral.vhdl:169:9:@300ns:(report note): u = 00011111
neuronbehavioral.vhdl:169:9:@400ns:(report note): u = 11100000