我有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;
答案 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
。
这表明乘法(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,了解模拟周期中发生的情况。
如果我们模拟它,我们会得到预期的结果:
sum
和sum2
增加,好像它们不在循环中一样。 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提供正确的答案 显然,循环确实给加法器和乘法器提供了运行时间。用计数器替换它,该组件的操作将在不同的时钟周期内为阵列的每个值执行