如何填写和显示矩阵? [VHDL]

时间:2016-12-22 17:46:21

标签: vhdl xilinx

我有一个数据作为std_logic_vector,我想填充一个带有datain位的矩阵,然后显示它。

我如何填写并显示矩阵?

这是我的代码:

    signal datain : std_logic_vector(39 downto 0) := "1111011101100110011001010110011001100110";

     for i1 in 1 to 5 loop 
     for j1 in 1 to 8 loop
     for j2 in datain'range loop
     mat1(i1,j1)<=datain(j2);
      end loop;
      end loop; 
      end loop;

      ------- display the matrix

        for i2 in 1 to 5 loop 
         for i3 in 1 to 8 loop  
          for i4 in dataout'range loop       
           dataout(i4) <= mat1(i2,i3);
          end loop;
        end loop;
       end loop;    

谢谢,

1 个答案:

答案 0 :(得分:2)

首先,我们从您的代码段构建Minimal, Complete and Verifiable example

library ieee;
use ieee.std_logic_1164.all;

entity abir is
end entity;

architecture foo of abir is

    type mat_type is array (1 to 5, 1 to 8) of std_logic;
    signal mat1: mat_type;
    signal datain : std_logic_vector(39 downto 0) := 
                "1111011101100110011001010110011001100110";
    signal dataout: std_logic_vector (39 downto 0);  -- MISSING

    -- this function is predefined in VHDL -2008:
    function to_string (inp: std_logic_vector) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  std_logic_vector (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

INITIALIZE_MATRIX:
    process  -- (datain)
    begin
        for i1 in 1 to 5 loop 
            for j1 in 1 to 8 loop
                for j2 in datain'range loop
                    mat1(i1,j1)<=datain(j2);
                end loop;
            end loop; 
        end loop;
        wait;   -- Do only once, depends on the initial value of datain
    end process; -- the wait statement can be removed if you add sensitivity

   ------- display the matrix
MATRIX_T0_DATAOUT:
    process (mat1)
    begin
        for i2 in 1 to 5 loop
            for i3 in 1 to 8 loop
                for i4 in dataout'range loop
                    dataout(i4) <= mat1(i2,i3);
                end loop;
            end loop;
        end loop;
    end process;

DISPLAY_DATAOUT:
    process -- (dataout)
    begin               -- wait statements so only disply valid datout
        wait for 0 ns;  -- first delta cycle all 'U's (dataout uninitialized)
        wait for 0 ns;  -- second delta cycle all 'U's (mat1 uninitialized)
        report LF &
               HT & "datain  = " & to_string(datain) & LF & 
               HT & "dataout = " & to_string(dataout);
        wait on dataout;
    end process;
end architecture;

函数to_string是在VHDL -2008中预定义的,此MCVE应该与符合VHDL标准早期版本的工具一起使用。

它专门用于演示您的代码。它给出了:

ghdl -a abir.vhdl
ghdl -e abir
ghdl -r abir
abir.vhdl:58:9:@0ms:(report note):
    datain  = 1111011101100110011001010110011001100110
    dataout = 0000000000000000000000000000000000000000

所以你的嵌套循环出了问题(你也可以用波形查看器验证这一点,以确定mat1确实是全部&#39; 0)。

所以原因就是内部循环。使用datain,您可以为矩阵mat1(i,j)的每个元素分配N次,其中N是datain的长度(j2的范围)。使用dataout,您可以为mat(i2,i3)的每个矩阵元素分配dataout(i4)的每个索引元素。

那么有三个循环可以执行这些分配吗?

嗯,不。

在INITIALIZE_MATRIX过程中,mat1的每个(i,j)位置都被datain的所有索引值覆盖。只有最后一个生效了。这填补了所有&#39;

的矩阵。

在MATRIX_TO_DATAOUT过程中,所有数据输出索引都被安排在&#39;获得每个i3循环迭代的最后一个mat1(i2,i3)值,确定i2和i3的最后一个循环迭代值,a&#39; 0&#39;。

我们可以修改两组循环,直接将j2或i4递减为变量(datain和dataout的范围按降序排列):

INITIALIZE_MATRIX:
    process  -- (datain)
        variable j2: natural range datain'range;
    begin
        j2 := datain'LEFT;  -- so the process can execute again.
        for i1 in 1 to 5 loop 
            for j1 in 1 to 8 loop
                -- for j2 in datain'range loop
                    mat1(i1,j1) <= datain(j2);
                    if j2 /= datain'RIGHT then
                        j2 := j2 - 1;  -- datain has descending range
                    end if;
                -- end loop;
            end loop; 
        end loop;
        wait;   -- Do only once, depends on the initial value of datain
    end process; -- the wait statement can be removed if you add sensitivity

   ------- display the matrix
MATRIX_T0_DATAOUT:
    process (mat1)
        variable i4: natural range dataout'range;
    begin
        i4 := dataout'LEFT;  -- so the process can execute again
        for i2 in 1 to 5 loop
            for i3 in 1 to 8 loop
                -- for i4 in dataout'range loop
                    dataout(i4) <= mat1(i2,i3);
                    if i4 /= dataout'RIGHT then
                        i4 := i4 - 1;  -- dataout has descending range
                    end if;
                -- end loop;
            end loop;
        end loop;
    end process;

这给了我们:

abir.vhdl:68:9:@0ms:(report note):
    datain  = 1111011101100110011001010110011001100110
    dataout = 1111011101100110011001010110011001100110

我们发现dataout匹配datain。 (好事。)

所以问题是每个进程中的三个嵌套循环都是错误的。我们想分别管理指向输入和输出数组的指针。

我们还管理变量j2或i4的赋值,以防止使用if语句违反边界,以防止在变量赋值超出变量值范围时减少j2或i4。分配时的边界检查失败将中止模拟。

请注意,信号分配会导致将值写入投影输出波形(队列)。在任何待处理的进程运行和暂停之前,不会发生信号更新。投影输出波形中的任何时间只有一个值。 (包括当前的模拟时间)。

这两个修改过程可以用作转换函数的基础:

architecture fum of abir is

    type mat_type is array (1 to 5, 1 to 8) of std_logic;
    signal mat1: mat_type;
    signal datain : std_logic_vector(39 downto 0) := 
                "1111011101100110011001010110011001100110";
    signal dataout: std_logic_vector (39 downto 0);  -- MISSING

    -- this function is predefined in VHDL -2008:
    function to_string (inp: std_logic_vector) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  std_logic_vector (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;

    function to_matrix (inp: std_logic_vector) return  mat_type is
        alias input: std_logic_vector(0 to inp'length - 1) is inp; -- ascending
        variable mat: mat_type;
        variable inptr: natural range 0 to inp'length;
    begin
        assert input'length = mat'length(1) * mat'length(2)
        report LF & 
            "to_matrix call, input length (" &
            integer'image(inp'length) & ") " &
            "/= " & integer'image( mat'length(1) * mat'length(2))
        severity FAILURE;
        for i in mat'range(1) loop      -- first dimension
            for j in mat'range(2) loop  -- second dimension
                mat(i,j) := input(inptr);
                inptr := inptr + 1;  -- inptr range allows last increment
            end loop;
        end loop;
        return mat;
    end function;

    function to_std_logic_vector (mat: mat_type) return std_logic_vector is
        variable retval: 
            std_logic_vector(0 to mat'length(1) * mat'length(2) - 1);
        variable outptr: natural range 0 to retval'length;
    begin
        for i in mat'range(1) loop      -- first dimension
            for j in mat'range(2) loop  -- second dimension
                retval(outptr) := mat(i,j);
                outptr := outptr + 1; -- outptr range allows last increment
            end loop;
        end loop;
        return retval;
    end function;
begin

INITIALIZE_MATRIX:
    mat1 <= to_matrix(datain);

MATRIX_T0_DATAOUT:
    dataout <= to_std_logic_vector(mat1);

DISPLAY_DATAOUT:
    process -- (dataout)
    begin               -- wait statements so only disply valid datout
        wait for 0 ns;  -- first delta cycle all 'U's (dataout uninitialized)
        wait for 0 ns;  -- second delta cycle all 'U's (mat1 uninitialized)
        report LF &
               HT & "datain  = " & to_string(datain) & LF & 
               HT & "dataout = " & to_string(dataout);
        wait for 1 ns;
        wait on dataout;
    end process;
end architecture;

这两个函数仅依赖于矩阵类型声明。您可以更改mat_type声明,而无需修改声明或函数中的任何语句序列。

to_matrix[std_logic_vector return mat_type]to_std_logic_vector[mat_type return std_logic_vector]函数调用的新架构提供与MCVE相同的答案以及更正的流程语句。