从其他几个模块内访问一个模块的实例? (Verilog的)(Accessing instance

2019-09-16 11:41发布

我写一个简单的系统,其中有一个内存模块(简单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

 ....

我怎么会在这里访问存储器模块?

Answer 1:

您需要修改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的两个实例尝试在同一时间读/写,你需要某种形式的仲裁器模块的承认两项请求,再往前逐一时间的记忆,和有效的数据返回到正确的模块。



Answer 2:

回答您的意见,你不实例存储不止一次。 您在层次结构的某种程度的创建存储的一个实例,然后通过端口/线所有的消费者连接到它。 因此,在顶层,你可能有一个要访问的内存3个模块和1个存储模块。 每三个访问器连接到单个实例,他们并不如自己的记忆。

该存储器应当平行于其他模块,而不是在其内部的,如果是有道理的。



Answer 3:

首先,你的记忆的名称是“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)
标签: verilog