VHDL:为二维数组的特定元素分配新值

VHDL: assign new value to the specific element of 2D Array

我想将平均变量值复制到二维数组的特定位置。对于此代码,它是 array_new_signal11(3,2)

谁能指导我该怎么做?这段代码在模拟时给我错误。

architecture Behavioral of Correction is

type array_new is array (0 to 4, 0 to 4) of integer;
signal array_new_signal: array_new;

begin

array_new_signal11 <=  ((1,2,3,4,5),
                        (4,5,6,7,8),
                        (7,8,9,0,1),
                        (1,3,6,5,9),
                        (2,3,5,4,5)); 

  Process(kelvin)
    variable Sum1: integer:= 0;
    Variable Sum2: integer:= 0;
    Variable Total_Sum: integer:= 0;
    Variable Average: integer:= 0;

    begin

        for Row in 0 to 4 loop
          for Column in 0 to 4 loop 

            if(Row = 1 and Column = 1) then
                for Column in 1 to 3 loop
                    sum1 := array_new_signal11(Row, Column) + Sum1;
                end loop;
            end if;

            if(Row = 2 and Column = 1) then
                for Column in 1 to 3 loop
                    sum2 := array_new_signal11(Row, Column) + Sum2;
                end loop;
            end if;   
         end loop;
        end loop;
      Total_Sum := Sum1 + Sum2;
      Average := Total_Sum / 8;
      **array_new_signal11(3,2) <= Average;**
     end Process;
    end Behavioral;

您正在尝试从两个不同的进程驱动 array_new_signal11 信号。是的,您的第一个并发信号分配:

array_new_signal11 <=  ((1,2,3,4,5),
                        (4,5,6,7,8),
                        (7,8,9,0,1),
                        (1,3,6,5,9),
                        (2,3,5,4,5));

是进程的shorthand。它模拟了一个硬件驱动程序,该驱动程序不断地将这些值强加给您的阵列信号(最后只是一束电线)。

您的第二个进程还尝试将一个值强加给数组的一个单元格(单元格 array_new_signal11(3,2))。在电气工程中,这种情况称为短路:当两个驱动程序不一致时,您会期望什么?这也是你的模拟器拒绝这个的原因:它不知道如何处理这个信号。

解决方案:从一个进程驱动此信号:

process(kelvin)
    ...
begin
    array_new_signal11 <= (
        (1,2,3,4,5),
        (4,5,6,7,8),
        ...
    for Row in 0 to 4 loop
        ...
end process;

备注:

  1. Average 是一个变量你应该有另一个错误:

    Average <= Total_Sum / 8;
    

    应该是:

    Average := Total_Sum / 8;
    
  2. 您在两个嵌套循环中使用了相同的循环索引 (Column)。不确定您要做什么,但这不是很安全。

  3. 即使按照我的建议来修复你的错误,你也会遇到另一个问题:array_new_signal11 既是过程的输入(你读取它)又是输出(你分配它) .因此,它也应该列在敏感列表中。在电气工程中,这被称为组合回路,通常是非常不受欢迎的,除非你想创建一个振荡器或一种随机发生器。

  4. 您的进程对信号 Kelvin 敏感但不使用它。奇怪的情况。您是否清楚要建模的硬件是什么?

  5. 您可能认为每次进程恢复时(即每次 Kelvin 更改),您的进程变量都会重新初始化为 0。事实并非如此:它们保留最后分配给它们的值。可能不是你想要的。您应该在流程主体的开头初始化它们。

根据问题构造一个最小的、完整的和可验证的例子:

entity correction is 
end correction;

architecture behavioral of correction is
    type array_new is array (0 to 4, 0 to 4) of integer;
    signal array_new_signal11: array_new := ((1,2,3,4,5),
                                             (4,5,6,7,8),
                                             (7,8,9,0,1),
                                             (1,3,6,5,9),
                                             (2,3,5,4,5));
    signal kelvin: boolean;
begin

    -- array_new_signal11 <=  ((1,2,3,4,5),
    --                         (4,5,6,7,8),
    --                         (7,8,9,0,1),
    --                         (1,3,6,5,9),
    --                         (2,3,5,4,5));

    process (kelvin)
        variable sum1: integer:= 0;
        variable sum2: integer:= 0;
        variable total_sum: integer:= 0;
        variable average: integer:= 0;
    begin
        for row in 0 to 4 loop
            for column in 0 to 4 loop 
                if row = 1 and column = 1 then
                    for column in 1 to 3 loop
                        sum1 := array_new_signal11(row, column) + sum1;
                    end loop;
                end if;
                if row = 2 and column = 1 then
                    for column in 1 to 3 loop
                        sum2 := array_new_signal11(row, column) + sum2;
                    end loop;
                end if;   
            end loop;
        end loop;
      total_sum := sum1 + sum2;
      average := total_sum / 8;
      report "sum1 = " & integer'image(sum1) & ", " &
             "sum2 = " & integer'image(sum2) & ", " &
             "average = " & integer'image(average);
      array_new_signal11(3,2) <= average;
    end process;
MONITOR_PROCESS:
    process
    begin
        wait on array_new_signal11;
        for row in 0 to 4 loop
            report "row" & integer'image(row) & " = " &
                    integer'image(array_new_signal11(row,0)) & ", " &
                    integer'image(array_new_signal11(row,1)) & ", " &
                    integer'image(array_new_signal11(row,2)) & ", " &
                    integer'image(array_new_signal11(row,3)) & ", " &
                    integer'image(array_new_signal11(row,4));
        end loop;
    end process;
end behavioral;

我们看到报告语句告诉我们平均值并报告新的数组值。

我们看到第 3 行第 2 列被初始化为 6,现在是 4:

ghdl -a correction.vhdl
ghdl -e correction
ghdl -r correction
correction.vhdl:42:7:@0ms:(report note): sum1 = 18, sum2 = 17, average = 4
correction.vhdl:52:13:@0ms:(report note): row0 = 1, 2, 3, 4, 5
correction.vhdl:52:13:@0ms:(report note): row1 = 4, 5, 6, 7, 8
correction.vhdl:52:13:@0ms:(report note): row2 = 7, 8, 9, 0, 1
correction.vhdl:52:13:@0ms:(report note): row3 = 1, 3, 4, 5, 9
correction.vhdl:52:13:@0ms:(report note): row4 = 2, 3, 5, 4, 5

由平均值指定。

正如 Renaud Pacalet 指出的那样,您有两个不同的进程驱动 array_new_signal11,这在 VHDL 中是不合法的,因为它的元素类型整数不是已解析的数据类型。

解决方案是在声明数组的地方初始化数组。

否则每次对数组信号元素的赋值都必须在同一个进程中。您拥有的并发信号分配将被详细说明为等效的过程语句,并在按最初显示的详细说明时生成错误:

ghdl -r correction
for signal: .correction(behavioral).array_new_signal11(3,2)
./correction:error: several sources for unresolved signal
./correction:error: error during elaboration

(对于 ghdl 模拟器的详细说明部分(包括链接和加载)在调用模拟时完成(-r 命令,加载部分,创建设计网络的地方))。

Renaud Pacalet 建议在进程内分配数组值,但如果没有干预等待语句,这些值将无法在同一模拟周期中进行后续使用。新信号值在分配给它们的同一仿真周期中不可用。

每个信号分配都会安排一次波形更新,并且只有一个特定模拟时间的条目可用。在这种情况下,它会保证 array(3, 2) 将是 integer'left 的八个值的平均值(这是不正确的,您应该会在未标记的第三个循环语句第一个循环中的 sum1 累加期间出现导致模拟结束的错误迭代)。

这告诉我们您需要在读取之前初始化数组。

上述示例成功的唯一原因是没有数组元素加在一起时不会超出您指定值的整数类型的取值范围。

您可以通过使用整数的二进制数组等价物并注意所需的准确性来解决这类问题。

这个故事有几个寓意。首先,VHDL 不是一种编程语言,其次它是强类型的,第三个信号分配值在它们创建的仿真周期中永远不可见。

请注意,已将开尔文添加为布尔信号以触发进程执行一次而不更改它。