Electronics > FPGA
How do I initiate multiple instances of 1 module in verilog?
(1/1)
BrianHG:
I have a module called MAGGIE. It is fed by are receives bus controls. I want to initiate 15 of them without copying and pasting 15 of the same modules. I would like to do something along the lines of a 'for' loop, however, for loops are not outside the 'always' portion of you verilog code.
Example of what I would like to do:
--- Code: ---for (i=1 ; i<NUM_LAYERS ; i=i+1) begin
maggie maggie_[i](
.clk ( clk ),
.pc_ena_in ( pc_ena[3:0] ), // Synchronous sub-pixel clock divider
.hw_regs ( GPU_HW_Control_regs ), // MAGGIE controls
.HV_trig ( HV_triggers_in ), // H&V sync and top left window coordinates going into MAGGIE
.cmd_in ( GPU_ram_cmd_out[i-1] ), // comand coming in from previous MAGGIE channel
.ram_din ( GPU_ram_data_out[i-1] ), // GPU ram read data comand coming in from previous MAGGIE channel
.read_addr ( GPU_ram_addr_in[i] ), // current MAGGIE directed pixel/pixel or tile/tile read address going out
.cmd_out ( GPU_ram_cmd_in[i] ), // current MAGGIE directed real time pixel/pixel command going out
.bp_2_rast_cmd ( maggie_to_bp2r[i] ) ); // once per frame BART controls going out
defparam maggie_[i].H_RESET_TRIG = 6 , // H&V trigger which defines when the MAGGIE resets and increments it's internal registers
maggie_[i].H_POS_TRIG = 8+2*i, // H&V trigger which defines the beginning top left coordinate of the MAGGIE's open window
maggie_[i].HW_REG_BASE = 64+16*i, // Base address for the 16 bytes which controls the MAGGIE and paired BART modules.
maggie_[i].RAM_READ_CYCLES = 3 ; // Defines the GPU_ram module's read pixel clock cycles.
end
--- End code ---
Now obviously this cant function, but, are there verilog compiler directives or shortcut which would allow me to initiate 30 of these MAGGIE modules without having to copy and paste 30 of these into the beginning of my code and editing all the integer values incrementing 1 for each instance?
BrianHG:
Found it, it was the 'generate' command:
--- Code: ---genvar x;
generate
for (x=1 ; x<NUM_LAYERS ; x=x+1) begin : maggie_inst
maggie maggie_inst (
.clk ( clk ),
.pc_ena_in ( pc_ena[3:0] ), // Synchronous sub-pixel clock divider
.hw_regs ( GPU_HW_Control_regs ), // MAGGIE controls
.HV_trig ( HV_triggers_in ), // H&V sync and top left window coordinates going into MAGGIE
.cmd_in ( GPU_ram_cmd_out[x-1] ), // comand coming in from previous MAGGIE channel
.ram_din ( GPU_ram_data_out[x-1] ), // GPU ram read data comand coming in from previous MAGGIE channel
.read_addr ( GPU_ram_addr_in[x] ), // current MAGGIE directed pixel/pixel or tile/tile read address going out
.cmd_out ( GPU_ram_cmd_in[x] ), // current MAGGIE directed real time pixel/pixel command going out
.bp_2_rast_cmd ( maggie_to_bp2r[x] ) ); // once per frame BART controls going out
defparam maggie_inst.H_RESET_TRIG = 6 , // H&V trigger which defines when the MAGGIE resets and increments it's internal registers
maggie_inst.H_POS_TRIG = 8+2*x, // H&V trigger which defines the beginning top left coordinate of the MAGGIE's open window
maggie_inst.HW_REG_BASE = 64+16*x, // Base address for the 16 bytes which controls the MAGGIE and paired BART modules.
maggie_inst.RAM_READ_CYCLES = 3 ; // Defines the GPU_ram module's read pixel clock cycles.
end
endgenerate
--- End code ---
Sorry to waste anyone's time, but at least this may help others...
asmi:
This is how real engineers are supposed to work. Ran into a problem, and solved it himself shortly thereafter :-+
I would add that there is also "generate if/else" statement which is useful for conditional inclusion of submodules or pieces of code based on parameters.
Also instead of using defparam you can specify parameters directly via #() construct:
--- Code: ---module_type #(
.PARAM1("STR"),
.PARAM2(42)
) inst_name (
...
);
--- End code ---
This makes code more readable in my opinion as all parameters are defined right at instantiation.
rstofer:
Is the following line correct? The code will only generate NUM_LAYERS - 1 instances. If NUM_LAYERS is 5, the loop executes for 1..4
for (x=1 ; x<NUM_LAYERS ; x=x+1) begin : maggie_inst
BrianHG:
Yes, this is correct as I'm actually beginning with module #0 which is counted, but, because of the following 2 lines:
--------------------
.cmd_in ( GPU_ram_cmd_out[x-1] ), // comand coming in from previous MAGGIE channel
.ram_din ( GPU_ram_data_out[x-1] ), // GPU ram read data comand coming in from previous MAGGIE channel
--------------------
The first MAGGIE module I have manually defined just prior in the code, but not shown, takes in place of the 'x-1' the value of 'NUM_LAYERS - 1', wrapping around from the top MAGGIE module. This creates a circular chain. Yes, there may have been a way to mathematically insert module #0 into the for loop and make that 'x-1' = to 'NUM_LAYERS - 1' for module #0 alone.
Navigation
[0] Message Index
Go to full version