知识点:要实现ROM,首先要声明数据的存储空间,例如:[3:0] rom [7:0];变量名称rom之前的[3:0]表示每个数据具有多少位,指位宽;变量名称rom之后的[7:0]表示需要多少个数据,指深度,注意这里深度为8,应该是使用[7:0],而不是[2:0];
声明存储变量之后,需要对rom进行初始化,写入数据,然后将输入地址作为rom的索引值,将索引值对应的数据输出。
初始化完成之后的rom的形式如下,内部存在地址和数据的对应关系,通过输入相应的地址,可以得到相应的输出数据
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
reg [3:0] rom_data [7:0] ;
assign data = rom_data[addr];
//保持ROM中的数据不变
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
rom_data[0] <= 4'd0;
rom_data[1] <= 4'd2;
rom_data[2] <= 4'd4;
rom_data[3] <= 4'd6;
rom_data[4] <= 4'd8;
rom_data[5] <= 4'd10;
rom_data[6] <= 4'd12;
rom_data[7] <= 4'd14;
end
else begin
rom_data[0] <= 4'd0;
rom_data[1] <= 4'd2;
rom_data[2] <= 4'd4;
rom_data[3] <= 4'd6;
rom_data[4] <= 4'd8;
rom_data[5] <= 4'd10;
rom_data[6] <= 4'd12;
rom_data[7] <= 4'd14;
end
endmodule
对于一个ROM,既要有数据位宽,也要有数据深度,例如
reg [3:0] rom [7:0]
表示,由8个,位宽为4bits的连续地址组成一个名为rom的区域
初始化就简单了,直接时序逻辑对rom的不同地址赋值
由addr提取rom的数据时,应注意使用时序逻辑,因为data随着addr的变化立即发生变化,且是wire型
解法二:
思路:
1,声明ROM存储器,可以理解为一个数组
2,对ROM进行初始化赋值,在initial 块内,因赋值有规律,可以用for循环实现
3,根据传入的地址值,决定从rom中取第几个数
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
reg [3:0] rom_data [7:0] ;
reg [3:0] data_1;
assign data=data_1;
integer i;
always@(*)begin //由于输出要求实时性,所以不能采用时序逻辑,而是组合逻辑
if(!rst_n)begin
data_1 <= 4'b0;
for(i=0;i<8;i=i+1)
begin
rom_data[i] = i << 1; //初始化的位置放置在了复位的阶段
end
end
else begin
case(addr)
8'd0:data_1 <= rom_data[0];
8'd1:data_1 <= rom_data[1];
8'd2:data_1 <= rom_data[2];
8'd3:data_1 <= rom_data[3];
8'd4:data_1 <= rom_data[4];
8'd5:data_1 <= rom_data[5];
8'd6:data_1 <= rom_data[6];
8'd7:data_1 <= rom_data[7];
default: data_1 <= 4'b0;
endcase
end
end
endmodule
解法三:很简单,利用for循环
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
parameter DEPTH = 8;
integer i;
reg [3:0] rom [7:0];
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
for(i=0;i<DEPTH-1;i++)begin
rom[i] <= i*2;
end
end
end
assign data = rom[addr];
endmodule
解法四:注意:条件是上升沿或下降沿或复位低电平有效,没有下降沿代码无法通过
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
reg [3:0] p=0;
always@(posedge clk or negedge clk or negedge rst_n)begin
if(!rst_n)
p<=0;
else begin
p<= addr*2;
end
end
assign data=p;
endmodule