Блок памяти данных

Я запустил Verilog несколько недель назад, и теперь я реализую конвейерную обработку MIPS на плате FPGA, и я нахожусь на этапе конвейерной обработки 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 

Нужен ли мне еще один оператор if для memread? Любая помощь приветствуется. Спасибо


person El Dj    schedule 27.04.2016    source источник


Ответы (2)


В дизайне, который вы закодировали выше, вы не используете 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

Важно отметить также необходимость часов в вашем дизайне. Большинство блок-схем на этом уровне будут опускать часы, как предполагается, но все синхронные элементы (память и регистры) будут синхронизированы с общими часами (или несколькими часами в некоторых случаях).

person Unn    schedule 27.04.2016

@Unn дает отличный ответ, более того, я просто хочу добавить, что если вы не используете read_enable, это может привести к несинхронизированной операции чтения данных. Также предпочтительно перебрасывать вывод read_data на read_clk.

Здесь с см. ниже Templent для справки.

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>];
person Prakash Darji    schedule 27.04.2016