Реконфигурируемый экземпляр памяти в verilog с DATA-IN и DATA-OUT передается как параметр

Как я могу сделать модуль памяти, в котором ширина шины DATA передается в качестве параметра для каждого экземпляра, и мой дизайн перенастраивается в соответствии с параметром? Например, предположим, что у меня есть память с байтовой адресацией, а ширина шины DATA-IN составляет 32 бита (4 байта записываются в каждом цикле), а DATA-OUT составляет 16 бит (2 байта считываются в каждом цикле). Для другого экземпляра DATA-IN — 64 бита, а DATA-OUT — 16 бит. Для всех таких случаев мой дизайн должен работать.

Я пробовал генерировать значения указателя записи в соответствии с параметрами проекта, например. DATA-IN 32 бита, указатель записи будет увеличиваться на 4 каждый цикл во время записи. Для 64-битных - приращение будет на 8 и так далее.

Проблема: как сделать так, чтобы 4 или 8 или 16 байт записывались за один цикл в соответствии с параметрами, переданными экземпляру?

//Something as following I want to implement. This memory instance can be considered as internal memory of FIFO having different datawidth for reading and writing in case you think of an application of such memory

module mem#(parameter DIN=16, parameter DOUT=8, parameter ADDR=4,parameter BYTE=8)
(
  input  [DIN-1:0]  din,
  output [DOUT-1:0] dout,
  input             wen,ren,clk
);

localparam DEPTH = (1<<ADDR);
reg [BYTE-1:0] mem [0:DEPTH-1];
reg wpointer=5'b00000;
reg rpointer=5'b00000;
reg [BYTE-1:0] tmp [0:DIN/BYTE-1];

function [ADDR:0] ptr;
input [4:0] index;
integer i;
  begin
    for(i=0;i<DIN/BYTE;i=i+1)  begin 
      mem[index] = din[(BYTE*(i+1)-1):BYTE*(i)]; // something like this I want to implement, I know this line is not allowed in verilog, but is there any alternative to this?
      index=index+1;
    end
    ptr=index;
  end
endfunction

always @(posedge clk) begin 
  if(wen==1)
    wpointer <= wptr(wpointer);
end

always @(posedge clk) begin
  if(ren==1)
    rpointer <= ptr(rpointer);
end

endmodule

person user2624915    schedule 13.10.2014    source источник
comment
Пожалуйста, просмотрите обновленный пост @Morgan   -  person user2624915    schedule 13.10.2014
comment
Какая разница будет? Не могли бы вы объяснить? @Qiu   -  person user2624915    schedule 13.10.2014


Ответы (1)


din[(BYTE*(i+1)-1):BYTE*(i)] не будет компилироваться в Verilog, потому что биты выбора MSB и LSB являются переменными. Verilog требует известного диапазона. +: предназначен для выбора части (также известного как срез), позволяет использовать переменный индекс выбора и постоянное значение диапазона. Он был введен в IEEE Std 1364-2001 4.2.1. Вы также можете узнать больше об этом в IEEE Std 1800-2012 11.5. .1 или обратитесь к ранее заданным вопросам: Что такое `+:` и `-:`? и индексирование векторов и массивов с помощью +:.

din[BYTE*i +: BYTE] должен работать на вас, в качестве альтернативы вы можете использовать din[BYTE*(i+1)-1 -: BYTE].

Кроме того, вы должны использовать неблокирующие назначения (<=) для mem. В вашем коде чтение и запись могут происходить одновременно. При блокировке возникает состояние гонки между доступом к одному и тому же байту. Он может синтезировать, но ваша симуляция RTL и гейта может давать разные результаты. Я также настоятельно рекомендую агенту использовать функции для распределения памяти. Функции в синтезируемом коде без неприятных сюрпризов должны быть автономными без ссылок на что-либо вне функции, и любые внутренние переменные всегда сбрасываются до статической константы в начале функции.

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

...
localparam DEPTH = (1<<ADDR);
reg [BYTE-1:0] mem [0:DEPTH-1];
reg [ADDR-1:0] wpointer, rpointer;
integer i;
initial begin // init values for pointers (FPGA, not ASIC)
  wpointer = {ADDR{1'b0}};
  rpointer = {ADDR{1'b0}};
end
always @(posedge clk) begin
  if (ren==1) begin
    for(i=0; i < DOUT/BYTE; i=i+1) begin
        dout[BYTE*i +: BYTE] <= mem[rpointer+i];
    end
    rpointer <= rpointer + (DOUT/BYTE);
  end
  if (wen==1) begin
    for(i=0; i < DIN/BYTE; i=i+1) begin
        mem[wpointer+i] <= din[BYTE*i +: BYTE];
    end
    wpointer <= wpointer + (DIN/BYTE);
  end
end
person Greg    schedule 13.10.2014