知识点:要实现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