Single Input to Array of Custom Modules in Verilog
So I have an array of 4 RAM modules that I want to be able to read/write to based on two different selector signals. Right now I'm instantiating the RAM using intermediary signals:
genvar i;
generate
for (i = 0; i < regnum; i=i+1) begin:开发者_如何学Go 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
And I want to select the RAM to use using either head
or tail
signals (2-bit vectors). Any ideas how to do this?
I'm new here and can't comment on questions yet, but in response to Marty: most FPGA synthesis tools will translate internal multisource signals with tristate values into MUX-like logic, where possible. See, for instance: a description of old tristate-to-logic behaviour that sounds accurate to me.
As a recommendation to Adam, you're probably better off making this explicit in your code by performing the masking yourself rather than using the tristates. This will improve portability, give you more predictable results, and serve as self-documentation if anybody ever has to revisit your code.
However, making some guesses based on your solution, it would probably make sense to simply mask off the clock enable on the write port and mux the output of the read port. For instance:
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
This will probably result in less complex logic (i.e., better area and delay) than your solution.
I think I figured it out, gotta use a generate statement:
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
glad to hear you found a solution for your problem. I must admit I didn't fully understand what you were up to, but one comment, you can also use if
inside generate statements and thus instantiate different modules or use different signals dependent on the genvar
, e.g.:
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
精彩评论