2014-10-13 5 views
0

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

То, что я пробовал, состоит в том, чтобы генерировать значения указателя записи в соответствии с параметрами дизайна, например. DATA-IN 32 бит, указатель записи будет увеличивать 4 каждый цикл при записи. Для 64 бит -increment будет на 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 
+0

Перейди через обновленный пост @Morgan – user2624915

+0

'мем [индекс] = дин [(BYTE * (я + 1) -1) -: 8];' – Qiu

+0

Какая разница он будет делать? Не могли бы вы объяснить? @ Qiu – user2624915

ответ

0

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 или обратитесь к ранее задаваемым вопросам: What is `+:` and `-:`? и Indexing vectors and arrays with +:.

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 

 Смежные вопросы

  • Нет связанных вопросов^_^