My aim is to generate systemverilog module instances based on the content of an array or enum (or something like these) got as a parameter.
In case of array parameter: it can be done if the array is static (i.e. array length is set with constant in declaration), but I would need to provide different length of arrays. If I use dynamic arrays, then I can not refer to the length of the array in a generate block, because length of a dynamic array is not a constant. I can define the length of the static array in a separate parameter, but it would be better to avoide that if possible.
In case of enum: I need to declare 2 enum types to cover the enum values needed in a given test (see t_place) and also the ones which are not needed in the given test (see t_NOT_CHECKED_place), but are referred in a module.
See the code snippets below (array version is remarked in the for loop)
Any hint on a better solution is appreciated.
package sim_checkers_pkg;
typedef enum { GPIF_IN, GPIF_OUT} t_place;
t_place places_to_check_enum;
typedef enum {NUP_DUMMY=places_to_check.num(), CL_SYNCHRONIZER_IN, CL_SYNCHRONIZER_OUT, COLOR_CONV_IN, DATA_STORE_IN} t_NOT_CHECKED_place; // we need to have all the places deined (as enum or constant). The value of these entries must be outside the valid range of t_place entries.
endpackage
import sim_checkers_pkg::*;
module top_checkers();
stream_checker #(
.p_verbose_level (1),
.p_number_of_places_to_check (2),
.places_to_check_arr ({GPIF_IN, GPIF_OUT})
) stream_checker_inst(
.o_check_finished (w_check_finished)
);
endmodule
module stream_checker #(
parameter p_verbose_level=1,
parameter p_number_of_places_to_check=1,
parameter t_place places_to_check_arr[number_of_places_to_check] = {GPIF_OUT}
) (
output int o_check_finished
);
generate
genvar place;
//for (place=0; place < p_number_of_places_to_check; place++) begin : gen_place // $size(places_to_check_arr) could be also used, we can even generate an error if these are not equal.
for (place=0; place < places_to_check_enum.num; place++) begin : gen_place
case (place)
GPIF_IN: begin
assign w_clk [place][stream_addr] = `gpif_path.i_sys_clk;
assign w_rst [place][stream_addr] = !`gpif_path.i_sys_arst_n;
assign w_drop [place][stream_addr] = `gpif_path.i_drop_frame && (1 << stream_addr);
assign w_start_valid [place][stream_addr] = `gpif_path.i_data_store_fifo_tfirst && `gpif_path.i_data_store_fifo_valid && `gpif_path.o_data_store_fifo_ready && (`gpif_path.i_data_store_gpif_addr == stream_addr);
assign w_end_valid [place][stream_addr] = `gpif_path.i_data_store_fifo_tlast && `gpif_path.i_data_store_fifo_valid && `gpif_path.o_data_store_fifo_ready && (`gpif_path.i_data_store_gpif_addr == stream_addr);
assign w_data_valid [place][stream_addr] = !`gpif_path.i_data_store_fifo_tfirst && !`gpif_path.i_data_store_fifo_tlast && `gpif_path.i_data_store_fifo_valid && `gpif_path.o_data_store_fifo_ready && (`gpif_path.i_data_store_gpif_addr == stream_addr);
end
GPIF_OUT: begin
assign w_clk [place][stream_addr] = `gpif_path.i_sys_clk;
assign w_rst [place][stream_addr] = !`gpif_path.i_sys_arst_n;
assign w_drop [place][stream_addr] = `gpif_path.i_drop_frame && (1 << stream_addr);
assign w_start_valid [place][stream_addr] = 1'bX;
assign w_end_valid [place][stream_addr] = !`gpif_path.o_gpif_pktend_n && !`gpif_path.o_gpif_slwr_n && !`gpif_path.o_gpif_slcs_n && `gpif_path.o_gpif_slrd_n && `gpif_path.o_gpif_sloe_n && (`gpif_path.o_gpif_addr == stream_addr);
assign w_data_valid [place][stream_addr] = `gpif_path.o_gpif_pktend_n && !`gpif_path.o_gpif_slwr_n && !`gpif_path.o_gpif_slcs_n && `gpif_path.o_gpif_slrd_n && `gpif_path.o_gpif_sloe_n && (`gpif_path.o_gpif_addr == stream_addr);
end
default: begin
$error("Unhandled place");
end
endcase
stream_frame_checker #(
.p_verbose_level (p_verbose_level),
.p_has_start_flag (c_has_start_flag),
.p_has_end_flag (c_has_end_flag),
.p_supress_first_error_after_reset (c_supress_first_error_after_reset),
.p_stream_len (c_stream_len)
) stream_frame_checker_inst (
.i_clk (w_clk[place][stream_addr]),
.i_rst (w_rst[place][stream_addr]),
.i_drop (w_drop[place][stream_addr]),
.i_start_valid (w_start_valid[place][stream_addr]),
.i_data_valid (w_data_valid[place][stream_addr]),
.i_end_valid (w_end_valid[place][stream_addr]),
.i_stream_addr (G_GPIF_ADDR_BITS'(stream_addr)),
.i_stream_name ({spaces, name}),
.o_transferred_frame_cnt (transferred_frame_cnt[place][stream_addr]),
.o_error_cnt (error_cnt[place][stream_addr])
);
end
endgenerate
endmodule