概念
RAM(random access memory)即随机存储内存,这种存储器在断电时将丢失其存储内容,故主要用于存储短时间使用的程序。
ROM 指的是“只读存储器”,即Read-Only Memory。只读存储器(Read-Only Memory,ROM)以非破坏性读出方式工作,只能读出无法写入信息。信息一旦写入后就固定下来,即使切断电源,信息也不会丢失,所以又称为固定存储器。ROM所存数据通常是装入整机前写入的,整机工作过程中只能读出,不像随机存储器能快速方便地改写存储内容。ROM所存数据稳定 ,断电后所存数据也不会改变,并且结构较简单,使用方便,因而常用于存储各种固定程序和数据。
PROM 指的是“可编程只读存储器”既Programmable Red-Only Memory。这样的产品只允许写入一次,所以也被称为“一次可编程只读存储器”(One Time Progarmming ROM,OTP-ROM)。最初从工厂中制作完成的PROM内部并没有资料,用户可以用专用的编程器将自己的资料写入,但是这种机会只有一次,一旦写入后也无法修改。
EPROM 指的是“可擦写可编程只读存储器”,即Erasable Programmable Read-Only Memory。它的特点是具有可擦除功能,擦除后即可进行再编程,但是缺点是擦除需要使用紫外线照射一定的时间。
EEPROM 指的是“电可擦除可编程只读存储器”,即Electrically Erasable Programmable Read-Only Memory。它的最大优点是可直接用电信号擦除,也可用电信号写入。EEPROM不能取代RAM的原因是其工艺复杂, 耗费的门电路过多,且重编程时间比较长,同时其有效重编程次数也比较低。
Flash memory 指的是“闪存”,所谓“闪存”,它也是一种非易失性的内存,属于EEPROM的改进产品。它的最大特点是必须按块(Block)擦除(每个区块的大小不定,不同厂家的产品有不同的规格), 而EEPROM则可以一次只擦除一个字节(Byte)。目前“闪存”被广泛用在PC机的主板上,用来保存BIOS程序,便于进行程序的升级。其另外一大应用领域是用来作为硬盘的替代品,具有抗震、速度快、无噪声、耗电低的优点,但是将其用来取代RAM就显得不合适,因为RAM需要能够按字节改写,而Flash ROM做不到。
二、编程
1.要求:
编程实现512x8的ROM和RAM。
ROM、RAM至少应该包含的端口包括地址线、数据线、片选线、读写使能端,复位端和时钟端(其中部分信号线只适用于RAM)。
ROM、RAM和总测试模块分别包含在不同的.v文件中。
端口意义:
2.设计思路:
512x8的ROM和RAM,至少需要9位地址线和8位数据位。
3.RAM实现代码
//模块声明,指定模块名和端口引脚
module RAM (Data,Addr,CS,RWEnable,Reset,Clk);
//参数定义,指定数据总线和地址总线的宽度,以及内存单元的数量
parameter width=8,msize=512;
//端口引脚的方向和位宽定义
input CS,RWEnable,Reset,Clk; //输入信号,分别为芯片选择、读写使能、复位和时钟
input[width:0] Addr; //输入地址总线,宽度由width参数决定
inout[width-1:0] Data; //双向数据总线,宽度由width参数决定
//内部信号和寄存器的定义
reg [width-1:0] Data_temp; //用于暂存读出的数据的寄存器,宽度与Data总线相同
reg [width-1:0] Mem [msize-1:0]; //用于存储所有数据的内存数组,大小与内存单元数量相同
integer i; //用于遍历内存单元的整数变量
//always块,指定模块中所有操作的逻辑
always @(posedge Clk or posedge Reset)
begin
//复位条件,当Reset为1时,所有内存单元都被置为0
if(Reset)
begin
for(i=0;i<msize;i=i+1) //用一个for循环遍历所有内存单元
Mem[i] <= 0; //将每个内存单元赋值为0
end
//写操作条件,当RWEnable为1且CS为1时,将Data总线上的数据写入到Addr指定的内存单元中
else if((RWEnable==1'b1)&&(CS==1'b1))
begin
Mem[Addr] <= Data; //将Data总线上的数据赋值给Mem[Addr]
end
//读操作条件,当RWEnable为0且CS为1时,将Addr指定的内存单元中的数据读出并暂存在Data_temp中
else if((RWEnable==1'b0)&&(CS==1'b1))
begin
Data_temp<=Mem[Addr]; //将Mem[Addr]中的数据赋值给Data_temp
end
//其他条件,当CS为0或RWEnable为不确定值时,将Data_temp置为高阻抗状态
else
begin
Data_temp <= 8'bz; //将Data_temp赋值为高阻抗状态
end
end
//assign语句,指定Data总线与Data_temp之间的连接关系
assign Data=RWEnable?8'bz:Data_temp; //当RWEnable为1时,Data总线处于高阻抗状态;当RWEnable为0时,Data总线接收Data_temp中的数据
endmodule //模块结束
测试代码如下:
//模块声明,指定模块名为RAM_TS
module RAM_TS;
//信号和寄存器的定义,指定与RAM模块相连的端口引脚和内部变量
reg CS_t,RWEnable_t,Reset_t,Clk_t; //芯片选择、读写使能、复位和时钟信号,都是1位的寄存器
wire [7:0] Data_t; //数据总线,是8位的线网
reg [8:0] Addr_t; //地址总线,是9位的寄存器
reg [7:0] Data_temp_t; //用于暂存写入数据的寄存器,也是8位的
//initial块,指定测试RAM模块的过程,只会在仿真开始时执行一次
initial
begin
RWEnable_t = 1;//w //初始化读写使能信号为1,表示写模式
Reset_t = 1; //初始化复位信号为1,表示复位模式
Clk_t = 0; //初始化时钟信号为0
Addr_t = 0; //初始化地址总线为0
Data_temp_t = 0; //初始化暂存数据为0
CS_t=1; //初始化芯片选择信号为1,表示使能模式
#5 Reset_t=0; //延迟5个时间单位后,将复位信号置为0,表示正常工作模式
repeat(10) //重复10次以下操作
begin
#5 //延迟5个时间单位后
Addr_t=Addr_t+10; //将地址总线加10,表示访问下一个内存单元
Data_temp_t=Addr_t; //将地址总线上的值赋给暂存数据,表示要写入的数据与地址相同
end
#70 //延迟70个时间单位后
RWEnable_t = 0;//r //将读写使能信号置为0,表示读模式
Addr_t=0; //将地址总线置为0,表示从第一个内存单元开始读取数据
repeat(10) //重复10次以下操作
begin
#5 //延迟5个时间单位后
Addr_t=Addr_t+10; //将地址总线加10,表示访问下一个内存单元
end
end
//assign语句,指定数据总线与暂存数据之间的连接关系
assign Data_t=RWEnable_t?Data_temp_t:8'bz;
always #5 Clk_t=~Clk_t;
//实例化一个RAM模块,并且用定义好的信号和寄存器与之相连
RAM myRAM(
.Data(Data_t), //将数据总线与RAM模块的Data端口相连
.Addr(Addr_t), //将地址总线与RAM模块的Addr端口相连
.CS(CS_t), //将芯片选择信号与RAM模块的CS端口相连
.RWEnable(RWEnable_t), //将读写使能信号与RAM模块的RWEnable端口相连
.Reset(Reset_t), //将复位信号与RAM模块的Reset端口相连
.Clk(Clk_t) //将时钟信号与RAM模块的Clk端口相连
);
endmodule //模块结束
4.RAM仿真测试:
① 数据写入操作
② 数据读取操作
5.ROM实现代码:
ROM代码如下:
//模块声明,指定模块名和端口引脚
module ROM(Data,Addr,CS,RDEnable,Reset,Clk);
//参数定义,指定数据总线和地址总线的宽度,以及内存单元的数量
parameter width=8,msize=512;
//端口引脚的方向和位宽定义
input CS,RDEnable,Reset,Clk; //输入信号,分别为芯片选择、读使能、复位和时钟
input[width:0] Addr; //输入地址总线,宽度由width参数决定
output [width-1:0] Data; //输出数据总线,宽度由width参数决定
//内部信号和寄存器的定义
reg [width-1:0] Data_read; //用于暂存读出的数据的寄存器,宽度与Data总线相同
reg [width-1:0] Mem [msize-1:0]; //用于存储所有数据的内存数组,大小与内存单元数量相同
integer i; //用于遍历内存单元的整数变量
//always块,指定模块中所有操作的逻辑
always @(posedge Clk or posedge Reset)
begin
//复位条件,当Reset为1时,所有内存单元都被置为其地址值
if(Reset)
begin
for(i=0;i<msize;i=i+1) //用一个for循环遍历所有内存单元
Mem[i] <= i; //将每个内存单元赋值为其地址值
end
//读操作条件,当RDEnable为1且CS为1时,将Addr指定的内存单元中的数据读出并暂存在Data_read中
else if((RDEnable==1'b1)&&(CS==1'b1))
begin
Data_read<=Mem[Addr]; //将Mem[Addr]中的数据赋值给Data_read
end
//其他条件,当CS为0或RDEnable为不确定值时,将Data_read置为高阻抗状态
else
Data_read <= 8'bz; //将Data_read赋值为高阻抗状态
end
//assign语句,指定Data总线与Data_read之间的连接关系
assign Data=Data_read; //当RDEnable为1时,Data总线输出Data_read中的数据;当RDEnable为0时,Data总线处于高阻抗状态
endmodule //模块结束
测试代码如下:
//模块声明,指定模块名为R0M98_TS
module R0M_TS;
//信号和寄存器的定义,指定与ROM98模块相连的端口引脚和内部变量
reg CS_t,RDEnable_t,Reset_t,Clk_t; //芯片选择、读使能、复位和时钟信号,都是1位的寄存器
wire [7:0] Data_t; //数据总线,是8位的线网
reg [8:0] Addr_t; //地址总线,是9位的寄存器
//initial块,指定测试ROM98模块的过程,只会在仿真开始时执行一次
initial
begin
RDEnable_t = 1;//r //初始化读使能信号为1,表示读模式
Reset_t = 1; //初始化复位信号为1,表示复位模式
Clk_t = 0; //初始化时钟信号为0
Addr_t = 0; //初始化地址总线为0
// Data_read_ts = 0; //初始化暂存数据为0
CS_t=1; //初始化芯片选择信号为1,表示使能模式
#5 Reset_t=0; //延迟5个时间单位后,将复位信号置为0,表示正常工作模式
repeat(10) //重复10次以下操作
begin
#10 //延迟10个时间单位后
Addr_t=Addr_t+10; //将地址总线加10,表示访问下一个内存单元
end
end
//always块,指定时钟信号的变化规律,每隔5个时间单位翻转一次
always #5 Clk_t=~Clk_t;
//实例化一个ROM98模块,并且用定义好的信号和寄存器与之相连
ROM myROM(
.Data(Data_t), //将数据总线与ROM98模块的Data端口相连
.Addr(Addr_t), //将地址总线与ROM98模块的Addr端口相连
.CS(CS_t), //将芯片选择信号与ROM98模块的CS端口相连
.RDEnable(RDEnable_t), //将读使能信号与ROM98模块的RDEnable端口相连
.Reset(Reset_t), //将复位信号与ROM98模块的Reset端口相连
.Clk(Clk_t) //将时钟信号与ROM98模块的Clk端口相连
);
endmodule //模块结束
6.ROM仿真测试:
评论 (0)