I would like to report a bug in Icarus Verilog version 0.9.7 (v0_9_7).
The code is rejected at the compilation.
This is the code of a generic multiplexer for N inputs, 1 output.
The code compile perfectly with quartus and with Xilinx also.
You can see below my shell output :
iverilog -Wall ro_puf_mux_n_to_1.v -o tb_mux_n_to_1.v
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[1].genblk6.INTERMEDIARY_STAGE[0]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[1].genblk6.INTERMEDIARY_STAGE[1]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[1].genblk6.INTERMEDIARY_STAGE[2]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[1].genblk6.INTERMEDIARY_STAGE[3]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[2].genblk6.INTERMEDIARY_STAGE[0]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[2].genblk6.INTERMEDIARY_STAGE[1]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
ro_puf_mux_n_to_1.v:80: error: Index of inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)] needs to be constant in this context.
ro_puf_mux_n_to_1.v:80: : Index expression is: (((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)
ro_puf_mux_n_to_1.v:80: : Context scope is: ro_puf_mux_n_to_1.genblk2.SELECT_STAGE[3].genblk6.INTERMEDIARY_STAGE[0]
ro_puf_mux_n_to_1.v:80: error: Output port expression must support continuous assignment.
ro_puf_mux_n_to_1.v:80: : Port dat_o of ro_puf_mux_2_to_1 is connected to inter_w[(((n_inputs)/(('sd2)(i)))*((('sd2)(i))-('sd1)))+(j)]
14 error(s) during elaboration.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
//`define ALTERA
module ro_puf_mux_2_to_1
(
input sel_i,
input [1:0] dat_i,
output dat_o
);
assign dat_o = sel_i && dat_i[1] || sel_i && dat_i[0];
endmodule
module ro_puf_mux_n_to_1
#(
parameter sel_w = 4,
parameter n_inputs = 2**sel_w
)
(
input [n_inputs-1:0] inputs_i,
input [sel_w-1:0] sel_i,
output output_o
);
`ifdef ALTERA
lpm_mux
#(
.lpm_size(n_inputs),
.lpm_type("LPM_MUX"),
.lpm_width(1),
.lpm_widths(sel_w)
)
LPM_MUX_component
(
.data(inputs_i),
.sel(sel_i),
.result(output_o)
);
`else // Generic
genvar i,j;
generate
if(sel_w == 1) begin
ro_puf_mux_2_to_1 mux_simple
(
.sel_i(sel_i),
.dat_i(inputs_i),
.dat_o(output_o)
);
end else begin
wire [n_inputs-2:0] inter_w; for(i=0; i<sel_w; i=i+1) begin : SELECT_STAGE if(i==0) begin for(j=0; j<n_inputs/2; j=j+1) begin : FIRST_STAGE ro_puf_mux_2_to_1 mux_first_stage ( .sel_i(sel_i[i]), .dat_i(inputs_i[2*j+1:2*j]), .dat_o(inter_w[j]) ); end end else begin for(j=0; j<(n_inputs/(2**(i+1))); j=j+1) begin : INTERMEDIARY_STAGE ro_puf_mux_2_to_1 mux_intermediary_stages ( .sel_i(sel_i[i]), .dat_i(inter_w[ (n_inputs/(2**(i-1)))*((2**(i-1))-1) + 2*j + 1 : (n_inputs/(2**(i-1)))*((2**(i-1))-1) + 2*j ]), .dat_o(inter_w[ (n_inputs/(2**i))*((2**i)-1) + j ]) ); end end end assign output_o = inter_w[ (n_inputs/(2**(sel_w-1)))*((2**(sel_w-1))-1) ]; end
endgenerate
`endif
endmodule
I can confirm that this is still failing with the latest V0.9 from git. It does compile correctly using the latest development from git.
Just as a note, there is an error in the code for the 2 to 1 mux module. The term that selects the zero input should be ~sel not sel. With this change the V0.9 branch is still broken, but the development branch generates a mux that functions correctly.
The issue here is that V0.9 uses eval_const() when calculating the constant for a net bit select and eval_const() does not have code to support the power operator. This causes the compiler to mistakenly think the expression is not constant when it really is. One of the enhancements in development is that it uses the eval_tree() infrastructure to calculate the constant. You can work around this problem by replacing 2**i in the .dat_o assignment with 1<<i which switches to the supported shift operator. I will discuss this issue with Steve and get his opinion regarding the best way to fix this issue.
I have pushed a fix for this to git and it will be available in V0.9.8 whenever it is released.
I use now the master branch version. Thank you for your help.
On 07/08/2014 03:26 AM, Cary R. wrote:
Related
Bugs:
#955