Entrada única a la matriz de módulos personalizados en Verilog
Pregunta
Así que tengo una matriz de 4 módulos de RAM en los que quiero poder leer / escribir en función de dos señales de selector diferentes. En este momento estoy instanciando la RAM usando señales intermedias:
genvar i;
generate
for (i = 0; i < regnum; i=i+1) begin: regs
rfram_generic rf (clk,rst,ce_a_int[i],addr_a_int[i],do_a_int[i],
ce_b_int[i],addr_b_int[i],do_b_int[i],
ce_w_int[i],we_w_int[i],addr_w_int[i],
di_w_int[i]);
end
endgenerate
Y quiero seleccionar la RAM para usar usando señales head
o tail
(vectores de 2 bits). ¿Alguna idea de cómo hacer esto?
Solución
Soy nuevo aquí y aún no puedo comentar preguntas, pero en respuesta a Marty: la mayoría de las herramientas de síntesis FPGA traducirán señales internas de múltiples fuentes con valores tristados a una lógica similar a MUX, cuando sea posible. Consulte, por ejemplo: una descripción del antiguo comportamiento de tristate-to-logic que me suena exacto .
Como una recomendación a Adam, probablemente sea mejor hacer esto explícito en su código al realizar el enmascaramiento usted mismo en lugar de usar los tristados. Esto mejorará la portabilidad, le dará resultados más predecibles y servirá como documentación propia si alguien alguna vez tiene que volver a visitar su código.
Sin embargo, haciendo algunas conjeturas basadas en su solución, probablemente tendría sentido simplemente enmascarar la activación del reloj en el puerto de escritura y silenciar la salida del puerto de lectura. Por ejemplo:
reg [WIDTH-1:0] do_a,do_b;
always @(*) do_a = do_a_int[head];
always @(*) do_b = do_b_int[tail];
generate
genvar i;
for (i = 0; i < regnum; i=i+1) begin: regs
rfram_generic rf (clk,rst,
ce_a,addr_a,do_a_int[i],
ce_b,addr_b,do_b_int[i],
ce_w,head==i?we_w:1'b0,addr_w,di_w);
end
endgenerate
Esto probablemente resultará en una lógica menos compleja ( es decir, , mejor área y retraso) que su solución.
Otros consejos
Creo que lo descubrí, tengo que usar una declaración de generación:
genvar i;
generate
for (i = 0; i < regnum; i=i+1) begin: sigassign
//read from the checkpoint in progress
assign ce_a_int[i] = (head == i) ? ce_a : 'bz;
assign addr_a_int[i] = (head == i) ? addr_a : 'bz;
assign do_a = (head == i) ? do_a_int[i] : 'bz;
//write to the checkpoint in progress
assign ce_w_int[i] = (head == i) ? ce_w : 'bz;
assign we_w_int[i] = (head == i) ? we_w : 'bz;
assign addr_w_int[i] = (head == i) ? addr_w : 'bz;
assign di_w_int[i] = (head == i) ? di_w : 'bz;
//read from the last stable checkpoint
assign ce_b_int[i] = (tail == i) ? ce_b : 'bz;
assign addr_b_int[i] = (tail == i) ? addr_b : 'bz;
assign do_b = (tail == i) ? do_b_int[i] : 'bz;
end
endgenerate
me alegra saber que encontró una solución para su problema. Debo admitir que no entendí completamente lo que estabas haciendo, pero un comentario, también puedes usar if
dentro de generar declaraciones y así crear instancias de diferentes módulos o usar diferentes señales dependientes de genvar
, por ejemplo:
generate
genvar i;
for (i = 0; i < regnum; i=i+1) begin: regs
if (i == head) begin
rfram_generic_a rf(...);
end else if (i == tail) begin
rfram_generic_b rf(...);
end else begin
rfram_generic_c rf(...);
end
end
endgenerate