VHDL从RAM中读取并存储在数组延迟中?

时间:2013-12-04 16:15:44

标签: arrays vhdl ram

我目前正在用VHDL进行一个项目,因为我不是专家,所以我遇到了一些问题。

我会尽力澄清一切。所以让我们分成几部分。

我要做的是在两个不同的RAM存储器中写入某些值,然后从它们读取并将不同的值存储到一个阵列中,该阵列将由不同的块用于执行MAC过滤。

这是我正在使用的RAM代码(是Weijun Zhang提供的代码的修改)我不知道是否必须在此处发布链接。如果有人需要它会发布它

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

--------------------------------------------------------------

entity SRAM is

generic(    width:  integer:=32;
            depth:  integer:=1024;
            addr:       integer:=10);

port(   clk:            in std_logic;   
        enable:     in std_logic;
        read_en:        in std_logic;
        write_en:   in std_logic;
        read_addr:  in std_logic_vector(addr-1 downto 0);
        write_addr: in std_logic_vector(addr-1 downto 0); 
        Data_in:    in std_logic_vector(width-1 downto 0);
        Data_out:   out std_logic_vector(width-1 downto 0)
);
end SRAM;

--------------------------------------------------------------

architecture behav of SRAM is

-- use array to define the bunch of internal temporary signals

type ram_type is array (0 to depth-1) of std_logic_vector(width-1 downto 0);
signal tmp_ram: ram_type:= ((others=> (others=>'0')));

begin   

    -- read_en Functional Section
    process(clk, read_en)

     begin
            if (clk'event and clk='1') then
                if enable='1' then
                    if read_en='1' then
                    -- buildin function conv_integer change the type
                    -- from std_logic_vector to integer
                    Data_out <= tmp_ram(conv_integer(read_addr)); 
                    else
                    Data_out <= (Data_out'range => 'Z');
                    end if;
                end if;
            end if;
    end process;

    -- write_en Functional Section
    process(clk, write_en)

     begin
            if (clk'event and clk='1') then
                if enable='1' then
                    if write_en='1' then
                    tmp_ram(conv_integer(write_addr)) <= Data_in;
                    end if;
                end if;
            end if;
    end process;

end behav;

这个RAM代码工作正常,我无法附加图像,因为我没有足够的声誉(这对我来说听起来很熟悉......) 我想用图像解释的是,在设置地址的同时,输出值是该地址中包含的值。

现在让我们转到实际问题:

我要做的是创建一个包含两个这些RAM内存的块。其中一个RAM用于存储要过滤的输入值,另一个用于存储滤波器系数的值。所以执行将是这样的:

  1. 仅将输入系数写入其专用存储器(地址从1到1024)
  2. 将所有新系数写入其内存(同样地址为1到1024)
  3. 从两个记忆中读取一个系数和一个输入值(从地址1开始)并将它们存储在两个数组中(在这种情况下是4个向量的数组)
  4. 填充阵列(步骤3中多3个循环)
  5. 阵列完成后,使用4个输入值和4个系数(仍未实现)执行过滤
  6. 再次启动第3点
  7. 我将尝试保存所有可以删除多行的空间(初始化和端口声明)

    library IEEE;               -- declare the library
    use IEEE.std_logic_1164.all;
    use IEEE.std_logic_arith.all;
    library work;
    use work.mypackage.all; -- use of mypackage to use arrays as inputs
    entity MAC_1024 is
    
        port( clk:                  in  std_logic;
                enable:             in  std_logic;
                enable_MAC:         in  std_logic;
                rst:                    in  std_logic;
                read_input_en:  in  std_logic; 
                write_input_en: in  std_logic;
                read_coeff_en:  in  std_logic;
                write_coeff_en: in  std_logic;
                X:                      in std_logic_vector(31 downto 0);
                W:                      in std_logic_vector(31 downto 0);
                Yt:                 out std_logic_vector(31 downto 0);
                Yn:                 out std_logic_vector(31 downto 0)
                );
    
        end MAC_1024;
    

    现在声明两个RAM

            input_RAM: SRAM generic map (width=> t_width, depth=> t_depth, addr=> t_addr) 
                                 port map (clk, enable, read_input_en, write_input_en,read_input_addr, write_input_addr, X, saved_input);
    
            coeff_RAM: SRAM generic map (width=> t_width, depth=> t_depth, addr=> t_addr) 
                                 port map (clk, enable, read_coeff_en, write_coeff_en,read_coeff_addr, write_coeff_addr, W, saved_coeff);
    

    此过程(常量值为“0000000001”)

    process (clk, write_input_en, write_coeff_en)
    
                begin
    
                if (clk'event and clk='1') then
    
                    if (write_coeff_en='1') then
                        write_coeff_addr <= cont2;
                        cont2 <= unsigned(cont2) + unsigned(one);
    
                    end if;
                    if (write_input_en='1') then
                        i:=0;
                        write_input_addr <= cont1;
                        cont1 <= unsigned(cont1) + unsigned(one);
    
                    end if;
    
    
    
                    if (read_input_en='1' and read_coeff_en='1') then
    
                        read_input_addr <= cont3;
                        read_coeff_addr <= cont4;
                        X_in(i) <= saved_input;
                        W_in(i) <= saved_coeff;
                        cont3 <= unsigned(cont3) + unsigned(one);
                        cont4 <= unsigned(cont4) + unsigned(one);
                        X_in(i) <= saved_input;
                        W_in(i) <= saved_coeff;
                        i:=i+1;
                        if(i=4) then 
                            i:=0;
                        end if;
                    end if;
    
                end if; 
    end process;
    
    
    
    Yn <= X_in(0);
    Yt <= saved_input;
    

    正如您所看到的,我使用变量i从0开始并填充数组X_in和W_in。当值为4时,放置在该数组中的位置将返回0.

    输出Y_n和Y_t用于测试功能。 Y_n输出存储在X_in [0]中的值,Y_t输出系数RAM的输出值

    所以,让我们说保持简单,我有一系列输入值(X),即1,2,3,4 .... 1024,这些值中的每一个都存储在地址1,2,3中, 4 .... 1024

    我希望在下一个序列之后将值放在数组中:
    X_in [Z Z Z 1]
    X_in [Z Z 2 1]
    X_in [Z 3 2 1]
    X_in [4 3 2 1]
    X_in [4 3 2 5]
    X_in [4 3 6 5]
    ...
    (当读启用激活时) 输出Y_n(读取X_in [0])将为1 1 1 1 5 5 5 5 9 9 9 9 ...
    输出Y_t(读取RAM输出)将为1 2 3 4 5 6 7 8 9 ...

    但我获得的是

    Y_n Z Z Z Z 4 4 4 4 8 8 8 8 ....
    Y_t 1 2 3 4 5 6 7 8 9 ...(预期)

    它看起来像索引i的问题(如果读取输出值X_in [1]我获得了与我预期的X_in [0]相对应的值),但是如果它是在我获得的同一时刻在Y_t值4我应该在Y_n中获得值4但是我仍然得到之前的Z.(粗体)

    阵列W_in ...

    也是如此

    坦率地说,我有点迷茫,我不知道我是否有问题,有延迟或有什么问题。

    我试图明确但我能理解这是一个解释相当复杂的问题

    非常感谢你的帮助

    更新1: 我不想重置地址计数器,因为我想写入1到1024的顺序地址。由于地址深度为1024是10位,我将地址加到常数,这是一个10位常数(“ 0000000001" )。一旦到达“1111111111”,下一个地址将是“0000000000”。现在的代码是为1024 FIR滤波器准备的,稍后我会尝试做更灵活的。另外我只想在存储器中添加一个输入值值,但每个滤波器周期增加1024个新系数,因此系统的计数器可以在写入操作后复位,但我不重置输入值的计数器,因为我需要知道我在哪里将存储此值。

    更新2:我一直在读到,在将地址设置为在RAM中读取(通常为一个周期)后,数据输出会出现一些周期。这可能是我的问题的原因,但那为什么我的RAM代码没有任何延迟工作???

1 个答案:

答案 0 :(得分:0)

你不应该在另外两个if语句中驱动i。尝试更改为if...elseif。也许这不是你的错误的原因,但它是一个基本规则。