添加无符号信号

时间:2015-03-18 15:56:30

标签: vhdl

我有delcare

SIGNAL sum,sumsq1,sumsq2,res,m: signed(31 downto 0):=(others => '0');

当我在ashycroneous

中执行以下操作时
sum   <= TO_SIGNED(pass(4)*try(4),32);

我得到了正确答案=“111111111 ... 111111111111111100”但是当我这样做时

sum   <= sum + TO_SIGNED(pass(4)*try(4),32);

它给我一个与正确答案无关的数字,即 answer =“111111100 ... 0000011111111100”

我做错了什么?请帮忙

这是完整的代码。我评论了一些部分,因为我试图找到问题,我发现其中一个没有在前面提到的任务中获得正确的值。

LIBRARY IEEE;
library lpm;
use lpm.lpm_components.all;
USE ieee.std_logic_1164.all;

use ieee.numeric_std.all;

ENTITY correlation IS
    PORT (
            CLOCK_50                                        :IN STD_LOGIC;
            SW                                              :IN STD_LOGIC_VECTOR(17 DOWNTO 0);
            LEDG                                            :OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
            LEDR                                            :OUT STD_LOGIC_VECTOR(15 DOWNTO 0));

    function  sqrt  ( d : UNSIGNED ) return UNSIGNED is
        variable a                                      : unsigned(31 downto 0):=d;  --original input.
        variable q                                      : unsigned(15 downto 0):=(others => '0');  --result.
        variable left,right,r                           : unsigned(17 downto 0):=(others => '0');  --input to adder/sub.r-remainder.
        variable i                                      : integer:=0;

    begin
        for i in 0 to 15 loop
            right(0):='1';
            right(1):=r(17);
            right(17 downto 2):=q;
            left(1 downto 0):=a(31 downto 30);
            left(17 downto 2):=r(15 downto 0);
            a(31 downto 2):=a(29 downto 0);  --shifting by 2 bit.
            if ( r(17) = '1') then
                r := left + right;
            else
                r := left - right;
            end if;
            q(15 downto 1) := q(14 downto 0);
            q(0) := not r(17);
        end loop; 
        return q;
    end sqrt;
END correlation;


ARCHITECTURE Behavior OF correlation IS
type data_array is array(1 to 10) of integer;

SIGNAL pass,try  : data_array;
SIGNAL s : unsigned(15 downto 0) :=(others => '0');
SIGNAL sum,sumsq1,sumsq2,res,m: signed(31 downto 0):=(others => '0');
SHARED VARIABLE e: unsigned(31 downto 0):=(others => '0');

BEGIN
    pass<=(0,0, 1, 2, 4, 7, 4, 5, 3,0);
    try <=(0,0,-1,-2,-4,-7,-4,-5,-3,0); 

    PROCESS (try)
    VARIABLE t,r: INTEGER:=0;
    BEGIN
     IF (CLOCK_50'EVENT AND CLOCK_50 = '1') THEN
--      FOR i in 1 to 10 LOOP
--          sum   := TO_SIGNED(TO_INTEGER(pass(i))*TO_INTEGER( try(i)),32);
            sum   <= sum + TO_SIGNED(pass(4)*try(4),32);
--          sumsq1:=sumsq1+TO_SIGNED(TO_INTEGER(pass(i))*TO_INTEGER(pass(i)),32);
--          sumsq2:=sumsq2+TO_SIGNED(TO_INTEGER( try(i))*TO_INTEGER( try(i)),32);
--      END LOOP;
----        t:=TO_INTEGER(sumsq1);
----        r:=TO_INTEGER(sumsq2);
--      e:=TO_UNSIGNED((TO_INTEGER(sumsq1)*TO_INTEGER(sumsq2)),32);
--      
--      s <=sqrt(e);
--
--      res:=TO_SIGNED(TO_INTEGER(sum)/TO_INTEGER(s),32);
--      r:=TO_INTEGER(res);
----     END IF;
----     IF (res>3) THEN LEDG<="11110000"; END IF;
----     IF (res<=3) THEN LEDG<="00001111"; END IF;
     LEDG<=(others => '0');
--   CASE SW(7 downto 0) IS
--     When "00000001" => LEDR<=STD_LOGIC_VECTOR(sum(15 DOWNTO 0)); 
--     When "00000010" => LEDR<=STD_LOGIC_VECTOR(sumsq1(15 DOWNTO 0)); 
--     When "00000100" => LEDR<=STD_LOGIC_VECTOR(sumsq2(15 DOWNTO 0)); 
--     When "00001000" => LEDR<=STD_LOGIC_VECTOR(e(15 DOWNTO 0));
----       When "00010000" => LEDR<=STD_LOGIC_VECTOR(t(15 downto 0)); 
--     When "00010000" => LEDR<=STD_LOGIC_VECTOR(s(15 downto 0)); 
----       When "01000000" => LEDR<=r(15 DOWNTO 0); 
--     When "01000000" => LEDR<=STD_LOGIC_VECTOR(res(15 DOWNTO 0)); 
--      when others => LEDR <=(others => '0');
--    END CASE;
     CASE SW(7 downto 0) IS
        When "00000001" => LEDR<=STD_LOGIC_VECTOR(sum(15 downto 0)); 
        When "00000010" => LEDR<=STD_LOGIC_VECTOR(TO_signed(try(2),16)); 
        When "00000100" => LEDR<=STD_LOGIC_VECTOR(TO_signed(try(3)*pass(3),16)); 
        When "00001000" => LEDR<=STD_LOGIC_VECTOR(TO_signed(try(4),16));
        When "00010000" => LEDR<=STD_LOGIC_VECTOR(TO_signed(try(5),16)); 
        When "00100000" => LEDR<=STD_LOGIC_VECTOR(TO_signed(try(6),16)); 
        When "01000000" => LEDR<=STD_LOGIC_VECTOR(TO_signed(try(7),16)); 
        when others => LEDR <=(others => '0');
     END CASE;
--   IF (r>-1/4 AND r<0)    THEN LEDG<="00010000"; END IF;
--   IF (r>-1/2 AND r<-1/4) THEN LEDG<="00110000"; END IF;
--   IF (r>-3/4 AND r<-1/2) THEN LEDG<="01110000"; END IF;
--   IF (r<-3/4)            THEN LEDG<="11110000"; END IF;
--   IF (r>0    AND r<1/4)  THEN LEDG<="00000001"; END IF;
--   IF (r>1/4  AND r<1/2)  THEN LEDG<="00000011"; END IF;
--   IF (r>1/2  AND r<3/4)  THEN LEDG<="00000111"; END IF;
--   IF (r>3/4)             THEN LEDG<="00001111"; END IF;

    END PROCESS;
END Behavior;

2 个答案:

答案 0 :(得分:2)

我将你的例子提炼为MVCe,并添加sum1以显示乘法本身:

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

entity correlation is
end correlation;

architecture behavior of correlation is
    type data_array is array(1 to 10) of integer;

    signal pass,try  : data_array;
    signal sum: signed(31 downto 0) := (others => '0');
    signal sum1: signed(31 downto 0) := (others => '0');
    signal clock_50:  std_logic := '0';

begin

clock:
    process
    begin
        wait for 10 ns;
        clock_50 <= not clock_50;
        if now > 60 ns then
            wait;
        end if;
    end process;

    pass<=(0,0, 1, 2, 4, 7, 4, 5, 3,0);
    try <=(0,0,-1,-2,-4,-7,-4,-5,-3,0); 

    process (clock_50)
    begin
        if (clock_50'event and clock_50 = '1') then
            sum   <= sum + to_signed(pass(4)*try(4),32);
            sum1  <= to_signed(pass(4)*try(4),32);
        end if;
    end process;
end behavior;

注意我还将进程敏感性列表更改为对CLOCK_50敏感,并为CLOCK_50添加了时钟进程和声明,以使代码成为独立的测试平台。您的示例也缺少end if

这给出了: correlation.png (点击)

这表明乘法(sum1)有效。它还指出sum是一个累加器,其中乘法的结果被加到每个时钟的总和上。

您的疯狂号码很可能是在某个任意点从您的模型中获取sum的快照。

您可以在第一个时钟上看到sum也有正确答案。

强烈建议使用Minimal, Complete, and Verifiable example的原因之一是,创建一个人的行为有时可能指向问题。

在评论中添加了问题

您的其他问题可能已附加到您当前的问题中,或作为单独的问题提出,而不是作为评论提出。

  

感谢我在Modelsim中模拟的回复提供的MCV示例,它没有遇到任何问题。我做了一些更改来扫描数组:if(clock_50&#39; event和clock_50 =&#39; 1&#39;)然后FOR i在1到10 LOOP sum&lt; = sum + TO_SIGNED(pass(4)*尝试(4),32); sum2&lt; = sum2 + TO_SIGNED(pass(4)* pass(4),32); sum3&lt; = sum3 + TO_SIGNED(try(i)* try(i),32);结束循环;万一;这样做我得到0作为答案。我错过了什么?

我创建了第二个架构来清楚地说明:

architecture different of correlation is
    type data_array is array(1 to 10) of integer;

    signal pass,try  : data_array;
    signal sum, sum2, sum3: signed(31 downto 0) := (others => '0');
    signal clock_50:  std_logic := '0';

begin

clock:
    process
    begin
        wait for 10 ns;
        clock_50 <= not clock_50;
        if now > 60 ns then
            wait;
        end if;
    end process;

    pass<=(0,0, 1, 2, 4, 7, 4, 5, 3,0);
    try <=(0,0,-1,-2,-4,-7,-4,-5,-3,0); 

    process (clock_50)
    begin
     if clock_50'event and clock_50 = '1' then 
         for i in 1 to 10 loop 
             sum  <= sum  + to_signed(pass(4)*try(4),  32);
             sum2 <= sum2 + to_signed(pass(4)*pass(4), 32); 
             sum3 <= sum3 + to_signed(try(i) *try(i),  32); 
         end loop; 
     end if;
    end process;
end architecture;

首先要注意的是,您正在对同一信号执行连续的顺序信号分配,并且分配位于同一过程中。每个进程只有一组驱动程序,并且在相同的模拟循环中暂停执行进程。由隐含的等待语句作为等待敏感性列表的最后一个语句暂停。

这些分配作为循环的连续迭代发生,并且因为对于任何特定模拟时间的任何驱动器,只有一个投影波形,实际上只会发生最后一次信号分配。基本上,您为每个信号分配安排信号更新,并且它们的预测值被下一个覆盖,直到只剩下最后一个信号分配。

当前模拟周期中任何进程仍在执行或挂起时,没有信号分配更新值。

具有无延迟元素的波形的信号分配将导致增量循环,并且在当前模拟循环完成之后且增量模拟循环执行开始之前,下一个排队模拟时间的所有待定信号分配将更新。另请参阅此答案 - The VHDL Simulation Cycle,了解模拟周期中发生的情况。

如果我们模拟它,我们会得到预期的结果:

correlation_loop (点击)

sumsum2增加,好像它们不在循环中一样。 sum3使用恰好为0的最后try值。

因为你有一个时钟,你期望这三组十次乘法并在一个时钟周期内增加。这不实用,或者您可以简单地切换到在循环语句中使用变量作为赋值目标。

变量赋值立即生效它是永恒的,而信号分配是在当前时间(无后等)或某个未来时间(例如10ns之后)的未来事件的时间表。

您可以使用i作为计数器而不是循环,使用最后一个值生成指定10个时钟的信号。您仍然使用i作为try索引。假设CLOCK_50是FPGA的50 MHz时钟,我们的想法是你不能在一个时钟内执行10次乘法和累加运算。

答案 1 :(得分:0)

最终代码如下

LIBRARY IEEE;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;


ENTITY correlation IS
    PORT (
            CLOCK_50                                        :IN STD_LOGIC);
end correlation;

architecture behavior of correlation is
     type data_array is array(1 to 10) of integer;

     signal pass,try : data_array;
     signal sum      : signed(31 downto 0) := (others => '0');
     signal sum2     : unsigned(31 downto 0) := (others => '0');
     signal sum3     : unsigned(31 downto 0) := (others => '0');

begin

     pass<=(0,0, 1, 2, 4, 7, 4, 5, 3,0);
     try <=(0,0,-1,-2,4,-7,-4,-5,-3,0); 

     PROCESS (clock_50)
         variable i  :integer:=0;
     BEGIN
        if (clock_50'event and clock_50 = '1') then
            IF i<10 THEN
                i:=i+1;      
                sum  <= sum + TO_SIGNED(pass(i)*try(i),32);
                sum2 <= sum2+ TO_UNSIGNED(pass(i)*pass(i),32);
                sum3 <= sum3+ TO_UNSIGNED(try(i) *try(i),32);
             END IF;
         END IF;
     END PROCESS;
END Behavior;

这会扫描数组并为SUM,SUM1和SUM2提供正确的答案 显然,循环确实给加法器和乘法器提供了运行时间。用计数器替换它,该组件的操作将在不同的时钟周期内为阵列的每个值执行