Лучший способ кодирования оперативной памяти в Verilog - PullRequest
17 голосов
/ 03 октября 2011

Какой код лучше писать в ОЗУ?

  1. назначение data_out внутри always блока:

    module memory(
        output reg [7:0] data_out,
        input [7:0] address,
        input [7:0] data_in, 
        input write_enable,
        input clk
    );
        reg [7:0] memory [0:255];
    
        always @(posedge clk) begin
            if (write_enable) begin
                memory[address] <= data_in;
            end
            data_out <= memory[address];
        end
    
    endmodule
    
  2. назначение data_out с использованием оператора assign:

    module memory(
        output [7:0] data_out,
        input [7:0] address,
        input [7:0] data_in, 
        input write_enable,
        input clk
    );
        reg [7:0] memory [0:255];
    
        always @(posedge clk) begin
            if (write_enable) begin
                memory[address] <= data_in;
            end
        end
    
        assign data_out = memory[address];
    
    endmodule
    

Есть рекомендации?

Ответы [ 5 ]

9 голосов
/ 03 октября 2011

Это зависит от ваших требований.

  1. Регистрирует вывод вашей памяти.Если вы синтезируете это для ворот, у вас будет на 16 шлепанцев больше, чем в случае 2. Это означает, что вы используете немного больше площади.Это также означает, что ваш выход будет иметь меньшую задержку распространения относительно часов, чем в случае 2. Кроме того, выходные данные не будут доступны до следующего тактового цикла.

  2. Ваши выходные данные будутдоступны в том же тактовом цикле, в котором они были записаны, хотя и с более длительной задержкой распространения относительно часов.

Вам необходимо решить, какой из них использовать, исходя из ваших требований.

Третий вариант - использовать сгенерированную оперативную память, которая является жестким макросом.Это должно иметь преимущества по площади, мощности и, возможно, времени по сравнению с вариантами 1 и 2.

7 голосов
/ 05 октября 2011

, чтобы добавить к ответу инструмента - если вы используете метод асинхронного чтения (случай 2), он не будет сопоставлен с блоком ОЗУ в ПЛИС, поскольку блоки ОЗУ во всех основных архитектурах, о которых я знаю, имеют синхронное чтение.

1 голос
/ 22 декабря 2016

Обе формы действительны, в зависимости от желаемого типа конвейерной обработки.Я всегда рекомендую следовать рекомендациям по кодированию Xilinx RAM - это хороший способ убедиться, что код синтезируется в правильные конструкции FGPA.

Например, ваш пример 1 будет синтезироваться в BRAM Xilinx (т. Е. Выделенный блок Ram), так как это синхронное чтение, а ваш пример 2 будет синтезироваться в распределенный Ram Xilinx (поскольку это асинхронное чтение).

См. Рекомендации по кодированию в документе Xilinx UG901 (Руководство пользователя Vivado Design Suite), в разделе RAM HDL Coding Techniques.В нем также есть хорошее описание разницы между синхронным чтением и асинхронным чтением для ОЗУ.

0 голосов
/ 26 сентября 2018

module mem_try (clk, // управляющий сигнал для создания оперативной памяти addr, // адрес, из которого необходимо извлечь данные data_in, // входные данные rd, wr, // запись управляющего сигнала на высоком уровне, чтение на низком уровне;// rst, // вводим управляющий сигнал // rd_count, // wr_count, data_out // считывание данных);

  parameter addr_length=32,data_width=32,ram_depth= 1 << addr_length;
  input [data_width-1:0]data_in;
  input clk,rd,wr;
  input [addr_length-1:0]addr;
  output reg [data_width-1:0]data_out;
  reg[data_width-1:0]ram[ram_depth-1:0];//ram variable decalaration 
  assign write_only =wr&~rd ;
  assign read_only =~wr&rd ;

  always@(posedge clk) begin

  if(write_only) begin
     ram[addr]<=data_in;
  end


  if(read_only) begin    
    data_out<=ram[addr];
  end

  end         

endmodule

я написал этот код для 32x32 оперативной памяти и былнадеясь, что в конструкции будет выведен блок памяти, однако вивадо рассматривает его как распределенную память

0 голосов
/ 30 сентября 2014

Во второй программе будет ошибка компиляции, так как мы не можем «Назначить» значение для «Reg». Будет выдано сообщение об ошибке: ' Регистр недопустим в левой части непрерывного присваивания '

...