数据存储单元
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>];
几周前我开始使用 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>];