自定义类型的数组聚合?

时间:2018-01-01 10:32:52

标签: vhdl hdl vivado

我尝试使用RAM行为实现FSM。在描述此FSM时,应该初始化此ram的多个地址。所以,我使用数组聚合技术来初始化 ram_block 的前20个地址。但是,我在每行发生聚合时出现错误的语法错误,或者ram_block(i)的部分部分已初始化。任何帮助将不胜感激。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity RegisterController is
    port(
        r1_p: inout std_logic_vector(31 downto 0);
        r2_p: inout std_logic_vector(31 downto 0);
        write_p: in std_logic;
        enable_p: in std_logic;
        clk_p: in std_logic;
        ram_rw: in std_logic;                       -- 0 => Read from ram | 1 => Write to the ram
        reset_p: in std_logic
    );
end RegisterController;

architecture RTL of RegisterController is
    -- Create the ram word
    subtype ram_word is std_logic_vector(66 downto 0);

    -- Create the ram block of 32 ram_words
    type ram_block is array (31 downto 0) of ram_word;

    -- Address to read from the ram
    signal R_ADDR_S: std_logic_vector(4 downto 0) := "00000";

begin
    RAM_LOAD: process(clk)
    begin 
        -- We're gonna load the 32 words of this ram with clock first
        -- Outputs are being updated in the runtime :D
        if(rising_edge(clk)) then
            if(ram_rw = '1') then
                -- STATE 0 DESCRIPTION
                ram_block(0) <= ("000", std_logic_vector(to_unsigned(0, 32)), std_logic_vector(to_unsgined(0, 32)));
                ram_block(1) <= ("000", std_logic_vector(to_unsigned(0, 32)), std_logic_vector(to_unsigned(0, 32)));
                ram_block(2) <= ("001", std_logic_vector(to_unsigned(0, 32)), std_logic_vector(to_unsigned(0, 32)));
                ram_block(3) <= ("001", std_logic_vector(to_unsigned(0, 32)), std_logic_vector(to_unsigned(0, 32)));

                -- STATE 1 DESCRIPTION
                ram_block(4) <= (66 downto 64) => "001";
                ram_block(5) <= (66 downto 64) => "001";
                ram_block(6) <= ("001", r2_p, r1_p);
                ram_block(7) <= (66 downto 64) => "010";

                -- STATE 2 DESCRIPTION
                ram_block(8) <= (66 downto 64) => "010";
                ram_block(9) <= (66 downto 64) => "010";
                ram_block(10) <= (66 downto 64) => "011";
                ram_block(11) <= (66 downto 64) => "011";

                -- STATE 3 DESCRIPTION
                ram_block(12) <= (66 downto 64) => "011";
                ram_block(13) <= (66 downto 64) => "011";
                ram_block(14) <= (66 downto 64) => "100";
                ram_block(15) <= (66 downto 64) => "100";

                -- STATE 4 DESCRIPTION
                ram_block(16) <= (66 downto 64) => "100";
                ram_block(17) <= (66 downto 64) => "100";
                ram_block(18) <= (66 downto 64) => "001";
                ram_block(19) <= (66 downto 64) => "001";
                ram_block(31 downto 20) <= std_logic_vector(to_unsigned(0, 67));
            end if;
        end if;
    end process;

    START_FSM: process(clk)
        -- TEMPORARY VARIABLE TO STORE THE READ VALUE FROM THE RAM BLOCK
        variable temp_read_ram: std_logic_vector(66 downto 0);
        variable temp_read_ram2: std_logic_vector(66 downto 0);
        -- R3 Declaration as a variable 
        variable R3_V: std_logic_vector(31 downto 0);
    begin 
        if(rising_edge(clk)) then
            if(ram_rw = '0') then
                -- START READING THE RAM FROM ADDRESS 0
                temp_read_ram := ram_block(to_integer(unsigned(R_ADDR_S)));
                R_ADDR_S(4 downto 2) <= temp_read_ram(66 downto 64);
                R_ADDR_S(1 downto 0) <= (enable_p, write_p);

                -- UPDATE THE OUTPUTS
                if(R_ADDR_S = "00110") then
                    -- READ THE PREVIOUS VALUE IN THAT ADDRESS
                    temp_read_ram2 <= ram_block(R_ADDR_S);
                    -- UPDATE THE OUTPUT VALUES INSIDE RAM
                    ram_block(R_ADDR_S) <= (temp_read_ram2(66 downto 64), r2_p, r1_p);
                    -- NO NEED TO UPDATE r2_p and r1_p
                elsif(R_ADDR_S = "00111") then
                    -- PUT THE CURRENT VALUE OF R1 TO THE R3
                    temp_read_ram2 <= ram_block(R_ADDR_S);
                    -- SAVE R1 TO THE R3_V
                    R3_V := temp_read_ram2(31 downto 0);

                elsif(R_ADDR_S = "01110" or R_ADDR_S = "01111") then
                    -- READ THE PREVIOUS VALIE IN THOSE ADDRESSES
                    temp_read_ram2 <= ram_block(R_ADDR_S);
                    -- UPDATE THE OUTPUT VALUE OF R2 INSIDE RAM
                    ram_block(R_ADDR_S) <= (temp_read_ram2(66 downto 64), R3_V, temp_read_ram2(31 downto 0)); 
                    -- UPDATE THE OUTPUT VALUE OF r2_p
                    r2_p <= R3_V;
               else
               else
                    -- NO CHANGE
                    ram_block(R_ADDR_S) <= ram_block(R_ADDR_S);
               end if;
           end if;
       end if;
   end process;       
end RTL;

1 个答案:

答案 0 :(得分:-1)

代码中没有一个,但语法错误很多。

首先,ram_block类型,而不是信号。那么你为什么要给它赋值?你需要先声明一个信号。即。

-- Create the ram block of 32 ram_words
type ram_block_type is array (31 downto 0) of ram_word;
signal ram_block : ram_block_type := (others => (others => '0'));

^我在这里也包括,是信号的初始化。同样可以做到:

signal R_ADDR_S: std_logic_vector(4 downto 0) := (others => '0');

在此过程中,您将同时为RAM中的许多位置分配值!那不像RAM那样。随机存取存储器通常只有1或2个端口,访问1个resp。一次2个元素。您正在设计通用分布式内存,因此imho不应将其称为RAM。

分配给数组的一部分有一个特定的语法。您可以一次性分配整个矩阵(顺便说一下,这是VHDL-2008):

ram_block <= (4 => (66 downto 64 => "001", others => '0'), others => '0');

注意:您需要在此处分配所有值,因此需要others语句。 第二个选项,分配一个子数组

ram_block(4) <= (66 downto 64 => "001", others => '0');

最后,也许你想要的,分配一个子数组的特定子集:

ram_block(4)(66 downto 64) <= "001";

但是在这种情况下,你想要初始化数组,因为未分配的std_logic将具有默认值'U'。

然后:

ram_block(31 downto 20) <= std_logic_vector(to_unsigned(0, 67));

这不起作用。您将数组结构分配给数组数组。

变量R3_V在一种情况下分配,但不直接使用:它使用不同的时钟周期。在这种情况下,不要使用变量:这是错误的编码风格。它应该是一个信号。

并且您必须记住,在时钟进程中分配的信号在下一个增量周期之前无法访问其新值。因此,对于以下if语句,信号R_ADDR_S(4 downto 2) <= temp_read_ram(66 downto 64);的分配将不可用!

其他事项:

  • clk应该是clk_p
  • to_unsgined - &gt; to_unsigned
  • 第79行
  • 使用正确的ram_block(to_integer(unsigned(R_ADDR_S))),但稍后(第86行)你做错了ram_block(R_ADDR_S)
  • 在第79行
  • 中,您还使用:=正确分配变量,但稍后(第86行)又使用了不正确的<=
  • 代码末尾有一个双else