для цикла является вашим другом, но только тогда, когда он используется в генерации, а не в последовательном коде (always
/initial
/function
/task
). Последовательные циклы могут привести к запутанному оборудованию, если вы не будете осторожны.
Вы можете в принципе закодировать это так же, как на любом другом языке, с (основной) проблемой, с которой вы не можете передавать массивы через порты модулей. Ниже приведен пример работы. Это было бы намного проще и яснее в VHDL (и, вероятно, SV, которого я не использую). Если вы собираетесь делать много такого, и вы только начинаете, вы должны сменить язык.
Аппаратное обеспечение квадратной матрицы 3x3, умноженное ниже, выполняется быстро, за счет большого количества аппаратного обеспечения. Он генерирует 9 единиц MAC, каждый из которых требует трех умножителей и двух сумматоров. вам нужно подумать о ширине бит; код в его нынешнем виде присваивает результат MAC 18-битовому значению, которое не будет работать вообще (код имитирует правильно, потому что значения в A
и B
являются небольшими).
Вам нужно подумать о ресурсах и сроках. Если у вас нет 27 множителей и 18 сумматоров, но вам не нужен ответ в спешке, а затем делитесь ими.В пределе вы можете построить очень компактное серийное оборудование за счет множества циклов и сложного управления.
module top;
wire[17:0]A[1:3][1:3]; // the matrices
wire[17:0]B[1:3][1:3];
wire[17:0]C[1:3][1:3];
wire[(9*18)-1:0] Abits; // bit-decomposed versions of the above
wire[(9*18)-1:0] Bbits;
wire[(9*18)-1:0] Cbits;
genvar i,j;
// set A and B with initial values
generate
for(i=0; i<3; i=i+1)
for(j=0; j<3; j=j+1) begin
assign A[i+1][j+1] = i*3 + j;
assign B[i+1][j+1] = i*3 + j + 1;
end
endgenerate
// decompose A and B, set C
generate
for(i=1; i<=3; i=i+1)
for(j=1; j<=3; j=j+1) begin
assign Abits[(((i-1)*3 + (j-1)) * 18)+17 -:18] = A[i][j];
assign Bbits[(((i-1)*3 + (j-1)) * 18)+17 -:18] = B[i][j];
assign C[i][j] = Cbits[(((i-1)*3 + (j-1)) * 18)+17 -:18];
end
endgenerate
initial
#1 $display("%4d %4d %4d\n%4d %4d %4d\n%4d %4d %4d\n",
C[1][1], C[1][2],C[1][3],
C[2][1], C[2][2],C[2][3],
C[3][1], C[3][2],C[3][3]);
mmult3x3 U1(Abits, Bbits, Cbits);
endmodule
module mmult3x3
(input wire[(9*18)-1:0] AI,
input wire[(9*18)-1:0] BI,
output wire[(9*18)-1:0] CO);
wire[17:0]A[1:3][1:3];
wire[17:0]B[1:3][1:3];
wire[17:0]C[1:3][1:3];
genvar i,j;
generate
for(i=1; i<=3; i=i+1)
for(j=1; j<=3; j=j+1) begin
assign A[i][j] = AI[(((i-1)*3 + (j-1)) * 18)+17 -:18];
assign B[i][j] = BI[(((i-1)*3 + (j-1)) * 18)+17 -:18];
assign CO[(((i-1)*3 + (j-1)) * 18)+17 -:18] = C[i][j];
end
endgenerate
// this is the bit that matters - everything else just works around shortcomings
// in the language:
generate
for(i=1; i<=3; i=i+1)
for(j=1; j<=3; j=j+1)
assign C[i][j] = A[i][1]*B[1][j] + A[i][2]*B[2][j] + A[i][3]*B[3][j];
endgenerate
endmodule
Да, я знаю об ограничениях HDL. Infact, я только что внедрил пользовательскую реализацию AES на доске, поэтому я знаю, как много мучительно нужно планировать и сопоставлять каждую единицу. Однако, поскольку этот код относительно прост, я думал, что это будет меньше головной боли. Можете ли вы указать мне какой-то ссылочный код для больших множителей? – Sam29
У меня есть пара потенциальных хитов путем поиска * opensores matrix multipication *, возможно, захочет проверить их. @ Sam29 – Tim
спасибо за помощь. Прямо сейчас, так как я просто хочу «преобразовать» код в Verilog, эффективность для меня не слишком важна (на данный момент, конечно же, вся картинная вещь будет рассмотрена позже). Тем не менее, я просто хотел знать и избегать неправильных методов кодирования в Verilog для таких операций. – Sam29