4

メモリモジュール(読み取りおよび書き込み信号を備えた単純な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

この最上位モジュールには、メモリに接続する他のモジュールも含まれます。それらをどのように接続するのか、私にはよくわかりません。このようなモジュールが1つあるとします

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

 ....

ここからメモリモジュールにアクセスするにはどうすればよいですか?

4

3 に答える 3

2

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がメモリの読み取りまたは書き込みを行う場合、出力ポートにaddr / dataを配置してメモリモジュールにコマンドを発行し、入力ポートでread_data_from_memory(_valid)がアサートされるのを待ちます。これらの出力と入力は、トップレベルのメモリモジュールに接続されます。

また、ここでバスの競合に対処する必要があります。たとえば、IF_stageの2つのインスタンスが同時に読み取り/書き込みを試みる場合、両方の要求を確認してから、それらを1つずつ転送するための何らかのアービターモジュールが必要になります。時間をメモリに戻し、有効なデータを適切なモジュールに返します。

于 2012-04-11T19:59:55.757 に答える
2

まず、メモリの名前は「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

すべてのクライアントに対してメモリとして動作するメモリ コントローラ/アービタが必要になりますが、実際にはクライアント間の競合を処理します。3 つのクライアントがあり、すべてのクライアントが 3 サイクルに 1 回未満しかメモリにアクセスしないと仮定すると、単純に次のようにすることができます。

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 サイクルに 1 回未満の場合にのみ問題ありません。アクセス レートが変動し、それよりも高い場合は、mem_ctl モジュールに実際のアービターが必要になります。ラウンドロビンアービターでいいと思います。

最後のコメントは、すべてのクライアントの累積アクセス レートが 1 サイクルあたり 1 回よりも大きい場合、ハードウェアで処理することは不可能です。その場合は、別の方法で行う必要があります。

于 2012-04-12T14:15:13.700 に答える
2

あなたのコメントに答えると、メモリを複数回インスタンス化することはありません。階層のあるレベルでメモリの 1 つのインスタンスを作成し、ポート/ワイヤを介してすべてのコンシューマを接続します。したがって、最上位には、メモリにアクセスする 3 つのモジュールと 1 つのメモリ モジュールがあるとします。3 つのアクセサーはそれぞれ単一のインスタンスに接続し、独自のメモリをインスタンス化しません。

それが理にかなっている場合、メモリは他のモジュールの内部ではなく、他のモジュールと並列にする必要があります。

于 2012-04-11T19:36:16.370 に答える