Input singolo per array di moduli personalizzati in Verilog
Domanda
Quindi ho un array di 4 moduli RAM che voglio poter leggere / scrivere sulla base di due diversi segnali di selezione. In questo momento sto istanziando la RAM usando segnali intermedi:
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
E voglio selezionare la RAM da usare usando i segnali head
o tail
(vettori a 2 bit). Qualche idea su come farlo?
Soluzione
Sono nuovo qui e non posso ancora commentare le domande, ma in risposta a Marty: la maggior parte degli strumenti di sintesi FPGA tradurrà segnali multisource interni con valori tristati in logica simile a MUX, ove possibile. Vedi, ad esempio: una descrizione del vecchio comportamento da tristato a logica che mi sembra accurato .
Come consiglio ad Adam, probabilmente stai meglio facendo questo esplicito nel tuo codice eseguendo il mascheramento da te piuttosto che usare i tristati. Ciò migliorerà la portabilità, ti darà risultati più prevedibili e fungerà da autocompensazione se qualcuno dovesse mai rivedere il tuo codice.
Tuttavia, facendo alcune ipotesi basate sulla tua soluzione, probabilmente avrebbe senso mascherare semplicemente l'abilitazione dell'orologio sulla porta di scrittura e combinare l'output della porta di lettura. Ad esempio:
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
Ciò comporterà probabilmente una logica meno complessa ( cioè , area e ritardo migliori) rispetto alla tua soluzione.
Altri suggerimenti
Penso di averlo capito, devo usare un'istruzione generate:
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
felice di sapere che hai trovato una soluzione al tuo problema. Devo ammettere che non ho capito appieno cosa stavi facendo, ma un commento, puoi anche usare if
all'interno di generare istruzioni e quindi creare un'istanza di moduli diversi o usare segnali diversi dipendenti dal genvar , ad esempio:
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