verilogsystem-verilogfpga5g

How to run iterations through a module instance without using generate in Verilog


I'm a complete beginner when it comes to Verilog. I have a block ROM which is as follows:

module CDbram_2_0_32 (clk, en, addr, dout);
input clk;
input en;
input [9:0] addr;
output [9:0] dout [0:37];

(*rom_style = "block" *) reg [9:0] data [0:37];

always @(posedge clk)
begin
if (en)
case(addr)
10'd0:data<={10'd19,10'd7,10'd27,-10'd1,10'd14,-10'd1,10'd11,10'd11,-10'd1,10'd19,-10'd1,10'd19,-10'd1,-10'd1,10'd28,10'd23,-10'd1,10'd12,-10'd1,10'd23,-10'd1,10'd4,-10'd1,10'd8,-10'd1,10'd18,-10'd1,-10'd1,10'd18,-10'd1,10'd19,-10'd1,10'd12,-10'd1,-10'd1,10'd15,-10'd1,-10'd1};
10'd1:data<={10'd22,10'd9,-10'd1,10'd1,10'd30,10'd11,10'd25,-10'd1,10'd31,10'd2,10'd19,-10'd1,10'd11,10'd30,-10'd1,10'd20,10'd26,-10'd1,10'd30,-10'd1,10'd14,-10'd1,-10'd1,-10'd1,10'd2,-10'd1,-10'd1,10'd10,-10'd1,-10'd1,-10'd1,10'd25,-10'd1,-10'd1,10'd31,-10'd1,-10'd1,10'd1};
10'd2:data<={-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,-10'd1,10'd31,-10'd1,10'd11,-10'd1,10'd29,-10'd1,10'd5,-10'd1,10'd7,-10'd1,-10'd1,10'd4,-10'd1,-10'd1,10'd6,-10'd1,-10'd1,-10'd1,10'd0,-10'd1};
....(and so on till addr 13)
endcase
end

assign dout = data;

endmodule

What I want to do is run 38 instances of a module (CN) in parallel. Each address of BROM has 38 values, so at each posedge, I want all the module instances to read their respective dout[index] and save the output in P2[index], like this:

for (j=0; j<14; j=j+1) begin: cn_instances
CN inst0 (.data_in(m[j]), .shift_amt(dout[0]), .data_out(p2_temp[0]));  assign p2[0] = p2[0]^p2_temp[0];

I'm sure my code is completely wrong, but I'm not sure where. I know that generating a for loop will only generate more instances, which is not what I want, but a regular for loop doesn't run with module instances. I'm so confused.

`timescale 1ns / 1ps


module P2_inst (
    input clk,             // Clock signal
    input rst,             // Reset signal (active high)
    input en,              // Enable reading (active high)
    input [447:0] message,
    output reg [9:0] dout [0:13],  // Output data from ROM
    output reg [9:0] addr,          // Current address
    output reg [31:0] p2 [0:37]
);

reg [31:0] m [0:13];
assign {m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13] }= message;
reg [31:0] p2_temp [0:37];

CDbram_2_0_32 rom (
    .clk(clk),
    .en(en),       // Enable ROM read
    .addr(addr),   // Current address
    .dout(dout)    // Output data
);
always @(posedge clk or posedge rst) begin
    if (rst) begin
        addr <= 10'd0;  // Reset to address 0
    end
    else if (en) begin
        if (addr < 10'd531) begin  // Stop at last address (531)
        addr <= 10'd0;
genvar j;
for (j=0; j<14; j=j+1)begin: cn_instances
j<=addr;
CN inst0 (.data_in(m[j]), .shift_amt(dout[0]), .data_out(p2_temp[0]));  assign p2[0] = p2[0]^p2_temp[0];
CN inst1 (.data_in(m[j]), .shift_amt(dout[1]), .data_out(p2_temp[1]));  assign p2[1] = p2[1]^p2_temp[1];
....
CN inst37 (.data_in(m[j]), .shift_amt(dout[37]), .data_out(p2_temp[37]));  assign p2[37] = p2[37]^p2_temp[37];

        end
        else begin
            addr <= 10'd0;   // Wrap around (optional)
        end
    end
end

endmodule

Any help is appreciated.


Solution

  • There are two parts to verilog program: dynamic and static.

    Dynamic is similar to any programming language, like c/c++. This programming is contained within procedural blocks: always..., initial, final. They can use conditional statements and loops in a dynamic manner. There are certain limitation on styles, imposed by the synthesis tools if you want to synthesize that code. But other than that it is just a regular programming language with additional simulation control statements enclosed within begin/end of an always or other blocks.

    Static part is a statical hierarchical structure of a design which includes module instances, procedural blocks. As you can imagine, one has to manually define every instance, every always block there statically. 'generate' blocks actually help you with creating this static structure. It allows you to use limited conditional statements and limited types of loops to generate this static structure. They only accept constants, i.e., parameters or special 'genvar' variables as arguments. A result of such a generate block is just a set of instances or always blocks.

    So, here is an example:

    module top(input myvar[2:0]);
    for(genvar i = 0; i < 2; i++) begin: myloop
       mymodule myinst(myvar[i]);
    end
    endmodule: top
    

    it is equivalent to

    module top(input myvar[2:0]);
       mymodule myinst[0](myvar[0]);
       mymodule myinst[1](myvar[1]);
       mymodule myinst[2](myvar[2]);
    endmodule: top
    

    So, in your example you created not 38 instance, but 38x14 = 532 instances:

    CN inst0[0] (.data_in(m[0]), .shift_amt(dout[0]), .data_out(p2_temp[0]));  
    assign p2[0] = p2[0]^p2_temp[0];
    CN inst1[0] (.data_in(m[0]), .shift_amt(dout[1]), .data_out(p2_temp[1]));  
    assign p2[1] = p2[1]^p2_temp[1];
    ....
    CN inst37[13] (.data_in(m[13]), .shift_amt(dout[37]), .data_out(p2_temp[37]));  
    assign p2[37] = p2[37]^p2_temp[37];
    

    You also created 532 assign statements, among those there are 14 which assign to p2[0], then 14 assigning to p2[1] snf do on. In other words every element in assign has 14 inputs. With a large probability the result will be 'x', unless all of the 14 inputs have the same value. Same story with the output of the module, data_out.

    Having that in mind, you should be able to design your generate loop in a better manner.

    It looks to me that you can use something like the following:

    for (genvar j = 0; j < 38; j++) begin: loop
        CN inst (.data_in(m), .shift_amt(dout[j]), .data_out(p2_temp[j]));  
        assign p2[j] = p2[j]^p2_temp[j];
    end
    

    The above will create 38 instances of CN. It will pass m as the whole vector and other array elements to it as ports. You have to deal with m within the module or some other way.

    It will not create any multiple-driven situation there.