数据存储单元

Data memory unit

几周前我开始使用 Verilog,现在我正在 FPGA 板上实现 MIPS 流水线,我正处于流水线阶段的 MEM 部分。我正在尝试对数据存储单元进行编码(在图片中 -> 数据存储单元)。

我不明白memread的使用。我的理解是如果memwrite为1,就是传递当前地址的内容来读取数据。

到目前为止,这是我的代码:

module data_memory (
input wire [31:0] addr,             // Memory Address
input wire [31:0] write_data,       // Memory Address Contents
input wire memwrite, memread,
output reg [31:0] read_data     // Output of Memory Address Contents
);

reg [31:0] MEMO[0:255];  // 256 words of 32-bit memory

integer i;

initial begin

   read_data <= 0;

   for (i = 0; i < 256; i = i + 1)
     MEMO[i] = i;

   end

always @ (addr) begin

   //**I don't understand the use of memread**//

   if (memwrite == 1'b1)
       MEMO[addr] <= write_data;
   end
end

assign read_data = MEMO[addr];

endmodule 

memread 是否需要另一个 if 语句?任何帮助是极大的赞赏。谢谢

在您上面编码的设计中,您没有使用 memread,而是选择通过模块的最后一行从内存中组合读取。如果没有更多关于图表中的内存应该如何运作的详细信息,就很难说出 memread 的确切用法。典型的存储器只有一个 memwrite 并假设如果提供了一个地址并且 memwrite 被取消断言,则访问是读取。在这种情况下,我只能假设 memread 应该断言从内存中读取。此外,我建议对您的代码进行一些编辑,以使其更好地工作并遵循更好的同步设计风格(这将合并 memread,以便您了解如何使用它):

module data_memory (
input wire [31:0] addr,          // Memory Address
input wire [31:0] write_data,    // Memory Address Contents
input wire memwrite, memread,
input wire clk,                  // All synchronous elements, including memories, should have a clock signal
output reg [31:0] read_data      // Output of Memory Address Contents
);

reg [31:0] MEMO[0:255];  // 256 words of 32-bit memory

integer i;

initial begin
  read_data <= 0;
  for (i = 0; i < 256; i = i + 1) begin
    MEMO[i] = i;
  end
end

// Using @(addr) will lead to unexpected behavior as memories are synchronous elements like registers
always @(posedge clk) begin
  if (memwrite == 1'b1) begin
    MEMO[addr] <= write_data;
  end
  // Use memread to indicate a valid address is on the line and read the memory into a register at that address when memread is asserted
  if (memread == 1'b1) begin
    read_data <= MEMO[addr];
  end
end

endmodule

还需要注意在您的设计中需要一个时钟。该级别的大多数框图将省略假定的时钟,但所有同步元素(存储器和寄存器)将同步到一个公共时钟(或在某些情况下为多个时钟)。

@Unn 给出了很好的答案,而且我只想补充一点,如果你不使用read_enable,那么它可能会不同步数据读取操作,也最好在输出read_data上翻转read_clk

这里和下面的模板供参考。

parameter RAM_WIDTH = <ram_width>;
parameter RAM_ADDR_BITS = <ram_addr_bits>;

(* RAM_STYLE="{AUTO | BLOCK |  BLOCK_POWER1 | BLOCK_POWER2}" *)
reg [RAM_WIDTH-1:0] <ram_name> [(2**RAM_ADDR_BITS)-1:0];
reg [RAM_WIDTH-1:0] <output_dataB>;

<reg_or_wire> [RAM_ADDR_BITS-1:0] <addressA>, <addressB>;
<reg_or_wire> [RAM_WIDTH-1:0] <input_dataA>;

//  The forllowing code is only necessary if you wish to initialize the RAM 
//  contents via an external file (use $readmemb for binary data)
initial
   $readmemh("<data_file_name>", <ram_name>, <begin_address>, <end_address>);

always @(posedge <clockA>)
   if (<enableA>)
      if (<write_enableA>)
         <ram_name>[<addressA>] <= <input_dataA>;

always @(posedge <clockB>)
   if (<enableB>)
      <output_dataB> <= <ram_name>[<addressB>];