How to design a module that counts logic 1s in multiple inputs in Verilog?
Use a for loop to add up within a cycle. Depending on the clock frequency and number of inputs, you may be able to directly increment the counter or you may have to store the intermediate sum in a register and pipeline adding that to the accumulator on the next cycle.

Handling multiple clocks is a different issue. What you could do is count in each clock domain separately, then dump the counters and synchronize the value every n (say 128) clock cycles into one clock domain where you accumulate all of these counts as they arrive.

I have a little PRBS checker module that does exactly this to count up errors at like 400 MHz, I'll have to dig it up. 

Edit: Here we go:

// snip...

reg prbs_invert_reg = 1'b0, prbs_invert_next;
reg prbs_gate_en_reg = 1'b0, prbs_gate_en_next;

reg gate_sync_reg_1 = 1'b0, gate_sync_reg_2 = 1'b0, gate_sync_reg_3 = 1'b0;

always @(posedge output_clk) begin
    gate_sync_reg_1 &lt;= gate;
    gate_sync_reg_2 &lt;= gate_sync_reg_1;
    gate_sync_reg_3 &lt;= gate_sync_reg_2;
end

wire [WIDTH*4-1:0] data_err;

// lfsr_prbs_check #(
//     .LFSR_WIDTH(7),
//     .LFSR_POLY(7'h41),
//     .LFSR_INIT(7'h7f),
//     .LFSR_CONFIG("FIBONACCI_FF"),
//     .REVERSE(1),
//     .INVERT(0),
//     .DATA_WIDTH(WIDTH*4),
//     .STYLE("AUTO")
// )
// lfsr_prbs_check_inst (
//     .clk(output_clk),
//     .rst(1'b0),
//     .data_in(output_q),
//     .data_in_valid(1'b1),
//     .data_out(data_err)
// );

lfsr_prbs_check_sel #(
    .REVERSE(1),
    .DATA_WIDTH(WIDTH*4),
    .STYLE("AUTO")
)
lfsr_prbs_check_inst (
    .clk(output_clk),
    .rst(1'b0),
    .select(prbs_select_reg),
    .invert(prbs_invert_reg),
    .data_in(output_q),
    .data_in_valid(1'b1),
    .data_out(data_err)
);

// sum errors
// reg [$clog2(WIDTH*4)+1-1:0] cycle_error_count_reg = 0;
// reg [$clog2(WIDTH*4)+1-1:0] cycle_error_count_temp = 0;

// // probably will need to pipeline this
// integer i;

// always @* begin
//     cycle_error_count_temp = 0;
//     for (i = 0; i &lt; WIDTH*4; i = i + 1) begin
//         cycle_error_count_temp = cycle_error_count_temp + data_err[i];
//     end
// end

// always @(posedge output_clk) begin
//     cycle_error_count_reg &lt;= cycle_error_count_temp;
// end

reg [$clog2(WIDTH*4)+1-1:0] cycle_error_count_reg = 0;
reg [$clog2(WIDTH*2)+1-1:0] cycle_error_count_1_reg = 0;
reg [$clog2(WIDTH*2)+1-1:0] cycle_error_count_2_reg = 0;
reg [$clog2(WIDTH*2)+1-1:0] cycle_error_count_1_temp = 0;
reg [$clog2(WIDTH*2)+1-1:0] cycle_error_count_2_temp = 0;

// probably will need to pipeline this
integer i;

always @* begin
    cycle_error_count_1_temp = 0;
    cycle_error_count_2_temp = 0;
    for (i = 0; i &lt; WIDTH*2; i = i + 1) begin
        cycle_error_count_1_temp = cycle_error_count_1_temp + data_err[i];
        cycle_error_count_2_temp = cycle_error_count_2_temp + data_err[i+WIDTH*2];
    end
end

always @(posedge output_clk) begin
    cycle_error_count_1_reg &lt;= cycle_error_count_1_temp;
    cycle_error_count_2_reg &lt;= cycle_error_count_2_temp;
    cycle_error_count_reg &lt;= cycle_error_count_1_reg + cycle_error_count_2_reg;
end

// accumulate errors, dump every 256 cycles
reg [7:0] count_reg = 8'd0;
reg [8:0] word_count_acc_reg = 0;
reg [8:0] word_count_reg = 0;
reg [8+$clog2(WIDTH*4)+1:0] error_count_acc_reg = 0;
reg [8+$clog2(WIDTH*4)+1:0] error_count_reg = 0;
reg error_count_flag_reg = 0;

always @(posedge output_clk) begin
    if (count_reg == 8'd255) begin
        count_reg &lt;= 8'd0;
        word_count_acc_reg &lt;= 0;
        error_count_acc_reg &lt;= 0;
        if (!prbs_gate_en_reg || gate_sync_reg_3) begin
            word_count_acc_reg &lt;= 1;
            error_count_acc_reg &lt;= cycle_error_count_reg;
        end
        word_count_reg &lt;= word_count_acc_reg;
        error_count_reg &lt;= error_count_acc_reg;
        error_count_flag_reg &lt;= ~error_count_flag_reg;
    end else begin
        count_reg &lt;= count_reg + 1;
        if (!prbs_gate_en_reg || gate_sync_reg_3) begin
            word_count_acc_reg &lt;= word_count_acc_reg + 1;
            error_count_acc_reg &lt;= error_count_acc_reg + cycle_error_count_reg;
        end
    end
end

// synchronize dumped counts to control clock domain
reg flag_sync_reg_1 = 1'b0;
reg flag_sync_reg_2 = 1'b0;
reg flag_sync_reg_3 = 1'b0;

always @(posedge clk) begin
    flag_sync_reg_1 &lt;= error_count_flag_reg;
    flag_sync_reg_2 &lt;= flag_sync_reg_1;
    flag_sync_reg_3 &lt;= flag_sync_reg_2;
end

// snip...

always @* begin

    // snip...

    cycle_count_next = cycle_count_reg + 1;
    if (cycle_count_reg[31] &amp;&amp; ~cycle_count_next[31]) begin
        cycle_count_next = 32'hffffffff;
    end

    update_count_next = update_count_reg;
    prbs_word_count_next = prbs_word_count_reg;
    prbs_error_count_next = prbs_error_count_reg;
    if (flag_sync_reg_2 ^ flag_sync_reg_3) begin
        update_count_next = update_count_reg + 1;
        prbs_word_count_next = word_count_reg + prbs_word_count_reg;
        prbs_error_count_next = error_count_reg + prbs_error_count_reg;

        // saturate
        if (update_count_reg[31] &amp;&amp; ~update_count_next[31]) begin
            update_count_next = 32'hffffffff;
        end
        if (prbs_word_count_reg[31] &amp;&amp; ~prbs_word_count_next[31]) begin
            prbs_word_count_next = 32'hffffffff;
        end
        if (prbs_error_count_reg[31] &amp;&amp; ~prbs_error_count_next[31]) begin
            prbs_error_count_next = 32'hffffffff;
        end
    end

    // snip...

end

// snip...

always @(posedge clk) begin
    if (rst) begin
        // snip...
        cycle_count_reg &lt;= 32'd0;
        update_count_reg &lt;= 32'd0;
        prbs_word_count_reg &lt;= 32'd0;
        // snip...
        prbs_error_count_reg &lt;= 32'd0;
        prbs_select_reg &lt;= 2'b00;
        prbs_invert_reg &lt;= 1'b0;
        prbs_gate_en_reg &lt;= 1'b0;
        // snip...
    end else begin
        // snip...
        cycle_count_reg &lt;= cycle_count_next;
        update_count_reg &lt;= update_count_next;
        prbs_word_count_reg &lt;= prbs_word_count_next;
        // snip...
        prbs_error_count_reg &lt;= prbs_error_count_next;
        prbs_select_reg &lt;= prbs_select_next;
        prbs_invert_reg &lt;= prbs_invert_next;
        prbs_gate_en_reg &lt;= prbs_gate_en_next;
        // snip...
    end

    // snip...
end

// snip...


Where this was used, WIDTH was set to 16, so it's doing a PRBS check and error count accumulation of a 64 bit input.  And it was running at around 20 Gbps, so output_clk was around 300 MHz.  However, it passed timing analysis with a clock constraint of closer to 400 MHz (assuming a data rate of 25 Gbps).  The internal clock clk was 125 MHz.  The target was a Virtex Ultrascale FPGA.  Readout and clearing of the final accumulators is not shown, but the counters are set up to saturate at 0xffffffff if they do not get read out and cleared before overflowing.  Clock domain crossing is a simple one-way pulse synchronizer (no two-way handshake) with a copy of the count being directly read from the internal clock domain.  This might not be the most robust way to do this, but is simple and it worked fine for the application.