2012-04-11 109 views
4

我正在寫一個簡單的系統,其中有一個內存模塊(帶有讀寫信號的簡單寄存器)。現在這個內存必須被其他幾個模塊訪問(不是同時)。所以我創建了這個內存的一個實例並向它提供數據。但我不知道我的其他模塊將如何訪問內存模塊的相同實例。任何幫助?從其他幾個模塊內部訪問一個模塊的實例? (verilog)

編輯

讓我通過一些代碼澄清一下。這是我的記憶模塊,簡單的信號。

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 
    [email protected](posedge clk or posedge rst) 
    begin 
     if(rst) 
      pc <= 16'hFFFF; 
     else 
      pc <= pc+1; 
    end 

.... 

如何從這裏訪問內存模塊?

+2

「訪問模塊」是什麼意思?你只需要像其他任何東西一樣連接電線。你能否再描述一下層次結構,並解釋爲什麼你不能通過端口/電線連接模塊? – Tim 2012-04-11 19:14:41

+0

@Tim我無法通過電線連接它們(據我所知)。內存模塊是一個,所有其他模塊都希望從中訪問數據。所以如果我在任何其他模塊中創建一個實例,它將是一個不同的實例。你如何建議我通過電線連接它們? – 2012-04-11 19:24:41

回答

1

回答您的評論,你不會多次實例化內存。您在層次結構的某個級別創建一個內存實例,然後通過端口/線路將所有使用者連接到它。所以在頂層你可能有3個模塊需要訪問內存,1個內存模塊。三個訪問器分別連接到單個實例,但它們沒有實例化自己的內存。

如果有意義的話,內存應該與其他模塊並行,而不是內部。

+0

查看新代碼添加到問題中,也許這會澄清我的問題 – 2012-04-11 19:51:14

2

您需要修改IF_stage增加一個接口,可以與內存溝通,是這樣的:當一個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 

); 

然後,它把地址/數據上它的輸出端口向內存模塊發出命令,然後等待在其輸入端口上聲明read_data_from_memory(_valid)。這些輸出和輸入連接到頂層的內存模塊。

您還需要在這裏處理總線爭用,例如,如果IF_stage的兩個實例試圖同時讀/寫,則需要某種仲裁器模塊來確認這兩個請求,然後轉發它們一次一個地存儲到內存中,並將有效數據返回到適當的模塊。

1

首先,你的記憶名稱是「rom」,它是隻讀的。我認爲這是一個錯字,否則就沒有必要使用wr port,你可以簡單地在客戶端實現單獨的ROM,並讓合成器優化設計。

對於你的問題,基本上你需要一個仲裁器來處理多個客戶端之間的爭用。所有客戶端都可以假設他們獨佔內存,但內存被所有客戶端共享,並且不能同時訪問。

蒂姆是正確的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個週期,一旦少,你可以簡單地有東西如下:

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 

然而,這僅僅是確定,當所有客戶端的接入速率比一次低每三個週期。如果訪問速率是變化的並且高於這個速度,那麼您將需要mem_ctl模塊中的一個真正的仲裁器。我認爲一個循環仲裁者會沒事的。

最後的評論,如果所有客戶端的累計訪問速率大於每個週期一次,則不可能在硬件上處理。在這種情況下,您需要以其他方式來完成。

相關問題