Verilog asynch mem в Xilinx

Я пытаюсь создать операцию сдвига памяти в verilog, и мне было интересно, как лучше это сделать. Пример кода:

reg [MSB:0] a [0:NO_OF_LOCATIONS];
// after some processing
for(i =0; i <= NO_OF_LOCATIONS; i= i+1)
  a[i] = a[i+1]

Если я использую ROM в Xilinx, он может синхронизировать только записи, и мне нужно сделать все смены за один такт. Если я использую память, как указано выше, я не уверен, что реализация на плате приведет к метастабильности или не будет иметь значения для распространения.

Также, что было бы лучшим способом сделать это вместо цикла for?

1 ответ

Решение

Я предполагаю, что это является частью синхронизированного синхронного блока, то есть что-то вроде следующего (в противном случае это не имело бы особого смысла, и вы написали: "Мне нужно сделать все смены в течение одного тактового цикла", что подразумевает, что это часть синхронный дизайн):

reg [MSB:0] a [0:NO_OF_LOCATIONS];

always @(posedge clk)
  if (...) begin
    for(i =0; i < NO_OF_LOCATIONS; i= i+1)
      a[i] <= a[i+1];
    a[NO_OF_LOCATIONS] <= ...;
  end

// also use a[] somewhere
assign a0 = a[0];

Btw: a[] имеет NO_OF_LOCATIONS+1 места в нем. Я не уверен, предназначено ли это, но я просто оставил это так. Обычно ассортимент a[] будет написано как [0:NO_OF_LOCATIONS-1] за NO_OF_LOCATIONS места памяти.

Обратите внимание, что я изменил назначение = в <=, Когда вы присваиваете что-то в синхронизированном всегда-блоке, и то, что вы назначаете, читается где-то вне этого всегда-блока, тогда вы должны назначить неблокирующее <=), чтобы избежать условий гонки в симуляции, которые могут привести к несоответствиям симуляции-синтеза.

Также обратите внимание, что я учел назначение a[NO_OF_LOCATIONS]так как он получил бы свою ценность от a[NO_OF_LOCATIONS+1], который вне границ и, таким образом, всегда будет неопределенным. Без этого изменения инструмент синтеза будет прав, если предположить, что все элементы a[] постоянны undef и просто заменит все чтения в этом массиве с константой 'bx,

Это прекрасно код. Я не уверен, почему вы подняли метастабильность, но пока ... выражения синхронны с clk в этой схеме нет метастабильности. Но это не совсем модель памяти. Ну, это так, но один с NO_OF_LOCATIONS написать порты и NO_OF_LOCATIONS порты чтения (считая только порты чтения, выведенные этим циклом for). Даже если бы у вас была такая память: было бы очень неэффективно использовать ее таким образом, потому что дорогая вещь о порте памяти - это его способность обращаться к любой ячейке памяти, но все порты в этом примере имеют постоянный адрес памяти (i является постоянным после развертывания цикла for). Таким образом, это огромное количество портов чтения и записи заставит инструмент синтеза реализовать эту память в виде набора отдельных регистров. Однако, если ваша целевая архитектура имеет выделенные ресурсы регистра сдвига (как это делают многие fpgas), то это может быть преобразовано в регистр сдвига.

Для больших значений NO_OF_LOCATIONS Вы можете рассмотреть возможность использования fifo с использованием курсора (ов) в памяти вместо смещения содержимого всей памяти с одного элемента на другой. Это вывело бы только один порт записи и никакой порт чтения из цикла for. Например:

reg [MSB:0] a [0:NO_OF_LOCATIONS];

parameter CURSOR_WIDTH = $clog2(NO_OF_LOCATIONS+1);
reg [CURSOR_WIDTH-1:0] cursor = 0;

always @(posedge clk)
  if (...) begin
    a[cursor] <= ...;
    cursor <= cursor == NO_OF_LOCATIONS ? 0 : cursor+1;
  end

assign a0 = a[cursor];
Другие вопросы по тегам