什么是 RAM(随机存取存储器)?
RAM(随机存取存储器)是用于系统读/写和存储数据的存储设备。RAM 存在范围从嵌入式系统、智能手机等小型系统到台式机、笔记本电脑等大型系统。系统中使用的 RAM 对系统性能有重大影响。它负责执行多项任务并存储数据。RAM的版本越高,它的性能就越高。
现在我们对 RAM 是什么有了清晰的认识,让我们看看如何在 VHDL 中实现 RAM。尽管业界使用了更高版本的 RAM。在本教程中,我们将实现一个简单的 32X8 RAM。它是存储设备的小规模版本。
内存规格
通常,内存用 M x N 表示,其中 M 是位置数,N 是数据线。所以这里 32 x 8,“32”代表 32 个位置,或者一个有 32 个位置的数组,“8”代表 8 条数据线。简单来说,一个 32 x 8 RAM 有 32 个位置,每 32 个位置可以存储 8 位数据。因此,32 x 8 RAM 可以存储的总位数为 256 位。现在,您可以想象用于笔记本电脑/台式机的 8GB、16GB RAM 的存储容量。
下面给出了一个示意图,指示了 RAM 中的端口/线路。
RAM 具有数据线、地址线、写入信号、时钟信号和用于从 RAM 读取内容的数据输出端口。地址线大小/位因 M x N 规格而异。让我们了解如何计算地址线位 (A) 的大小。
地址线位数/大小 (A):2 A =M。因此,在我们的例子中,它是 2 A =32 (M=32),其中 A=5。
An → 地址线
M → 位置数
N → 数据线
W → 写信号
由于 RAM 是时序电路,因此它具有时钟信号。所有时序电路都有时钟信号。此外,写入信号负责将数据刻录到 RAM 中。只有当时钟和写信号都为“1”时,数据才会存储在 RAM 中。
下面给出了与写入和时钟信号有关的事件。
RAM 的 VHDL 代码:
图书馆 IEEE; 使用 IEEE.STD_LOGIC_1164.ALL; 使用 ieee.numeric_std.ALL; 实体 RAM_32X8 是 端口( 地址:in std_logic_vector(4 downto 0); data_in:in std_logic_vector(7 downto 0); write_in:in std_logic; 时钟:in std_logic; data_out:out std_logic_vector(7 downto 0) ); 结束 RAM_32X8; 架构 RAM_32X8 的行为是 类型 ram_array 是 std_logic_vector 的数组(0 到 31 )(7 到 0); 信号 ram_data: ram_array :=( b"10000000",b"01001101",x"77",x"67", x"99",x"25",x"00",x"1A", x"00 ",x"00",x"00",x"00", x" x"00",x"00",b"00111100",x"00", x"00",x"00",x"00",x"00", x"00",x"00", x"00",x"1F" ); 开始 进程(时钟) 开始 如果(上升沿(时钟))然后 如果(写入='1')然后 ram_data(to_integer(无符号(地址)))<=数据输入; 万一; 万一; 结束进程; data_out <= ram_data(to_integer(unsigned(address))); 结束行为;
让我们先一步一步来,以便我们可以跟踪事情。首先,让我们逐段编写代码,然后合并。
第一步是导入库和实体声明。就像“使用IEEE.std_logic_1164.all ”、“使用IEEE.numeric_std.ALL ”一样,导入了我们将使用的数字库。这个库的使用将在下面的代码中解释。
该实体使用标签“ RAM_32X8 ”声明。接下来,声明了所有输入和输出端口。位大小为五 (5) 的地址线 (A)、数据线 (即 N = 8)、写入信号 (W)、时钟信号和数据输出是对应的输入和输出端口,如前所述。
图书馆 IEEE; 使用 IEEE.STD_LOGIC_1164.ALL; 使用 ieee.numeric_std.ALL; 实体 RAM_32X8 是 港口( 地址:在 std_logic_vector(4 downto 0) 中; data_in: 在 std_logic_vector(7 downto 0); write_in:在std_logic中; 时钟:在 std_logic 中; data_out: 输出 std_logic_vector(7 downto 0) ); 结束 RAM_32X8;
一旦实体被声明,我们就可以从架构定义开始。该架构被标记为“RAM_32x8”。
RAM_32X8 的架构行为是
ram_array 类型是 std_logic_vector(7 到 0)的数组(0 到 31): 现在,我们必须创建一个大小为 32 的数组。因此,我们将变量“ ram_array ”声明为“类型 ram_array”,它是一个枚举类型。枚举类型什么都不是,只是列出变量的所有可能值。“is array (0 to 31)”表示“type ram_array”将是一个大小为(M)为32的数组,从0开始到31结束。这32个位置应该能够存储一个8位向量为N= 8. 因此,我们将其声明为“ std_logic_vector (7 down to 0) ”。所以通常 ram_arary 是一个有 32 个位置的数组,每个位置可以存储 8 位。
类型 ram_array 是 std_logic_vector 的数组(0 到 31)(从 7 到 0);
现在,我们必须将其存储为信号。因此,我们将“ram_data”声明为信号并将其映射到数组“ram_array”。现在“ram_array”的内容将被映射到信号“ram_data”。所以,我们必须初始化数组的内容。所以,我已经初始化了一些值。
注意:我们可以用二进制或十六进制表示/初始化。“b”代表二进制,“x”代表十六进制。然而,ModelSim 在模拟时默认将表示转换为二进制。
信号 ram_data: ram_array :=( b"10000000",b"01001101",x"77",x"67", x"99",x"25",x"00",x"1A", x"00 ",x"00",x"00",x"00", x"00",x"00",x"00",x"00", x"00",x"0F",x"00 ",x"00", x"00",x"00",b"00111100",x"00", x"00",x"00",x"00",x"00", x"00 ",x"00",x"00",x"1F"
由于整个if条件过程都依赖于时钟,我们通过“process(clock)”声明
开始 进程(时钟) 开始
if (rising_edge(clock)) then: ModelSim 有一个预定义的函数“rising_edge()”。“rising_edge”表示信号从低到高的转换点。因此,只有在发生从低到高的转换时,它才会传递到下一条语句。
如果(上升沿(时钟))那么
if (write_in='1') then:这是一个简单的 if 条件,只有当信号“write_in”为 1 时,它才会传递到下一个。
if(write_in='1') 那么
ram_data v(to_integer(unsigned(address))) <= data_in: “ram_data”信号本身是一个数组,因此我们必须设置必须存储数据的数组的索引。该索引将只接受一个正整数。“to_integer()”将转换为整数值。“无符号”用于将二进制数转换为无符号二进制数。“IEEE.NUMERIC_STD all”包负责整数转换。
注意:默认情况下,Modelsim 会将给定的输入作为二进制。
如果您的地址是“11111”,ModelSim 有时会将“11111”解释为负数,因为 MSB(最高有效位)为“1”。因此,始终建议使用unsigned()。最后,当 ModelSim 处理这条语句时,它会是ram_data(index)。 只是我们已经将给定的地址转换为适当的索引格式。现在,“data_in”信号中的数据将被存储到适当的“ram_data”索引中。
由于我们使用了 2 个 if,我们必须通过两个“end if”来终止 if
万一; 万一; 结束进程;
由于必须通过给定地址从 RAM 中读取数据,因此声明了“data_out”信号以从特定索引读取内容。
data_out <= ram_data(to_integer(unsigned(address)));
只需复制粘贴上面的代码,编译和模拟代码。仿真过程请参考“ModelSim中使用VHDL实现基本逻辑门”
沿波形移动光标以读取信号的内容。这就是用 VHDL 编写 RAM 的方式。
图书馆 IEEE;
使用 IEEE.STD_LOGIC_1164.ALL;
使用 ieee.numeric_std.ALL;
实体 RAM_32X8 是
端口(
地址:in std_logic_vector(4 downto 0);
data_in:in std_logic_vector(7 downto 0);
write_in:in std_logic;
时钟:in std_logic;
data_out:out std_logic_vector(7 downto 0)
);
结束 RAM_32X8;
架构 RAM_32X8 的行为是
类型 ram_array 是 std_logic_vector 的数组(0 到 31 )(7 到 0);
信号 ram_data: ram_array :=(
b“10000000”,b“01001101”,x“77”,x“67”,
x“99”,x“25”,x“00”,x“1A”,
x“00 ”,x“00”,x“00”,x“00”,
x“00”,x“00”,b“00111100”,x“00”,
x“00”,x“00”,x“00”,x“00”,
x“00”,x“00”, x“00”,x“1F”
);
开始
进程(时钟)
开始
如果(上升沿(时钟))然后
如果(写入=‘1’)然后
ram_data(to_integer(无符号(地址)))《=数据输入;
万一;
万一;
结束进程;
data_out 《= ram_data(to_integer(unsigned(address)));
结束行为;
评论
查看更多