我写一个简单的系统,其中有一个内存模块(简单REG与读写信号)。 现在,这个存储器已被其它几个模块(非同时)进行访问。 所以我创建这个存储的实例和饲料数据到它。 但我无法弄清楚如何将我的其他模块访问存储器模块的同一个实例。 任何帮助吗?
编辑
让我通过一些代码澄清一下。 这是我的内存模块,简单的信号。
module rom(
input [15:0] addr,
input [15:0] data_in,
input rd,
input wr,
input cs,
output reg [15:0] data_out
);
reg [15:0] mem[255:0];
integer k;
initial begin
for(k = 0;k<256;k=k+2)
mem[k] = 16'h0011;
for(k = 1;k<256;k=k+2)
mem[k] = 16'h0101;
end
always @(cs)begin
if(wr)
mem[addr] <= data_in;
if(rd)
data_out <= mem[addr];
end
endmodule
这将在我的顶层模块实例化,这样的事情
module Top;
// Inputs
reg [15:0] addr;
reg [15:0] data_in;
reg rd;
reg wr;
reg cs;
// Outputs
wire [15:0] data_out;
// Instantiate the Unit Under Test (UUT)
rom uut (
.addr(addr),
.data_in(data_in),
.rd(rd),
.wr(wr),
.cs(cs),
.data_out(data_out)
);
....
....
....
endmodule
现在,这个顶层模块也将包含将要连接到存储一些其他模块。 我真的不明白我怎么会连接它们。 假设有一个模块,这样的
module IF_stage(
input clk,
input rst,
output reg [15:0] pc,
output [15:0] instruction
);
//pc control
always@(posedge clk or posedge rst)
begin
if(rst)
pc <= 16'hFFFF;
else
pc <= pc+1;
end
....
我怎么会在这里访问存储器模块?
您需要修改IF_stage添加可与记忆,像这样的东西通信的接口:
module IF_stage(
input clk,
input rst,
input [15:0] read_data_from_memory, //new
input read_data_from_memory_valid, //new
output reg [15:0] pc,
output [15:0] instruction
output do_memory_write //new
output do_memory_read //new
output [15:0] memory_write_data //new
output [15:0] addr //new
);
然后,当IF_stage要读取或写入内存,它把地址/数据上它的输出端口发出命令到内存模块,然后等待read_data_from_memory(_valid)被确立在它的输入端口。 这些输出和输入可以连接到在顶层内存模块。
您还可以在这里处理总线争用,例如,如果IF_stage的两个实例尝试在同一时间读/写,你需要某种形式的仲裁器模块的承认两项请求,再往前逐一时间的记忆,和有效的数据返回到正确的模块。
回答您的意见,你不实例存储不止一次。 您在层次结构的某种程度的创建存储的一个实例,然后通过端口/线所有的消费者连接到它。 因此,在顶层,你可能有一个要访问的内存3个模块和1个存储模块。 每三个访问器连接到单个实例,他们并不如自己的记忆。
该存储器应当平行于其他模块,而不是在其内部的,如果是有道理的。
首先,你的记忆的名称是“ROM”,这是只读的。 我想这是一个错字,否则就没有必要有WR端口,你可以简单地实现独立的ROM放在客户,让合成器进行优化设计。
对于你的问题,基本上你需要一个仲裁者来处理多个客户端之间的争夺。 所有客户端都可以假设它们占用专用内存,但内存是由所有客户端共享,并不能同时访问。
Tim是正确的关于IF_stage。 每个客户端必须有一个独立的存储器接口
output [15:0] addr;
output [15:0] data_out;
input [15:0] data_in;
output wr, rd, cs;
input rdy; // only when rdy == 1, the memory operation is finished
您将需要一个内存控制器/仲裁者,其表现为内存的所有客户端,但实际处理客户之间的争用。 假设有三个客户和所有客户端访问的内存比每三个周期最少一次,你可以简单地有东西如下:
module mem_ctl(
addr_c1, dw_c1, dr_c1, wr_c1, rd_c1, cs_c1,
addr_c2, dw_c2, dr_c2, wr_c2, rd_c2, cs_c2,
addr_c3, dw_c3, dr_c3, wr_c3, rd_c3, cs_c3,
addr_m, dw_m, dr_m, wr_m, rd_m, cs_m,
rdy_c1, rdy_c2, rdy_c3,
rst_n, clk
);
input clk, rst_n;
input [15:0] addr_c1, addr_c2, addr_c3, dw_c1, dw_c2, dw_c3; // addr and data_write from clients
output [15:0] dr_c1, dr_c2, dr_c3; // data read from clients
input wr_c1, wr_c2, wr_c3, rd_c1, rd_c2, rd_c3, cs_c1, cs_c2, cs_c3; // control from clients
output [15:0] addr_m, dw_m; // addr and data write to memory
input [15:0] dr_m;
output wr_m, rd_m, cs_m; // control the memory
output rdy_c1, rdy_c2, rdy_c3;
reg [15:0] dr_c1, dr_c2, dr_c3, dw_m, addr_m;
reg wr_m, rd_m, cs_m;
reg [1:0] cnt;
always @(posedge clk or negedge rst_n)
if (~rst_n)
cnt <= 0;
else if(cnt == 2'd2)
cnt <= 0;
else
cnt <= cnt + 1;
always @(*) // Verilog 2001, if not recognizable, fill in yourself
begin
case(cnt)
0: begin
dw_m = dw_c1;
wr_m = wr_c1;
cs_m = cs_c1;
rd_m = rd_c1;
dr_c1 = dr_m;
end
1: begin
dw_m = dw_c2;
wr_m = wr_c2;
cs_m = cs_c2;
rd_m = rd_c2;
dr_c2 = dr_m;
end
default: begin
dw_m = dw_c3;
wr_m = wr_c3;
cs_m = cs_c3;
rd_m = rd_c3;
dr_c3 = dr_m;
end
endcase
end
assign rdy_c1 = (cnt == 0) & cs_c1;
assign rdy_c2 = (cnt == 1) & cs_c2;
assign rdy_c3 = (cnt == 2) & cs_c3;
endmodule
然而,当所有客户端的接入速率比每3个周期,一旦下,这是唯一的确定。 如果访问率是变种和较高的比,你将需要mem_ctl模块在一个真正的仲裁者。 我认为,一个循环仲裁器将被罚款。
最后评论,如果所有客户端的累计接入速率低于每循环一次较大的,这是不可能的硬件来处理。 在这种情况下,你将需要做的是在其他方面。
文章来源: Accessing instance of one module from inside of several other modules? (verilog)