moduleveriloginstantiationicarus

Unexpected high impedance state


I've encountered a problem of unexpected high impedance state on output ports of my modules. Code of the module that instantiates other modules is following:

`timescale 1ns/1ps

module column(
    input wire clk,
    input wire reset,
    input wire trigger,
    input wire [7:0] latency
    );

localparam AMOUNT_OF_REGIONS = 3;

wire [24:0] o_data [0:AMOUNT_OF_REGIONS-1];
wire [1:0] up_in [0:AMOUNT_OF_REGIONS-1];
//same declarations for do_in, up_out, do_out

assign up_in[0] = 0;
assign do_in[AMOUNT_OF_REGIONS-1] = 0;

generate
    genvar i;
    for (i = 0; i < AMOUNT_OF_REGIONS; i = i + 1) begin : multiple_regions_instantiation
        if ((i == 0) || (i == AMOUNT_OF_REGIONS-1)) begin
            region tmp(
                clk,
                reset,
                trigger,
                latency,
                up_in[i],
                do_in[i],
                up_out[i],
                do_out[i],
                o_data[i]
            );
        end
        else begin
            region tmp(
                clk,
                reset,
                trigger,
                latency,
                do_out[i-1],
                up_out[i+1],
                do_in[i-1],
                up_in[i+1],
                o_data[i]
            );
        end
    end
endgenerate

endmodule

Port declaration of instantiatable modules is like this:

module region(
    input wire clk,
    input wire reset,
    input wire trigger,
    input wire [7:0] latency,
    input wire [1:0] up,
    input wire [1:0] do,
    output reg [1:0] to_up,
    output reg [1:0] to_do,
    output reg [24:0] odata
    );

Assignment of an output is made in initial block and looks like this:

initial begin
    latency_cnt = 255;
    start_cnt = 0;
    preset = 0;
    read_out = 0;
    begin: hit_generation
        cnt = 0;
        forever begin
            cnt = cnt + 1;
            fork
                #20 hit0 = ($random > 0) ? 1 : 0;
                #20 hit1 = ($random > 0) ? 1 : 0;
                #20 hit2 = ($random > 0) ? 1 : 0;
                #20 hit3 = ($random > 0) ? 1 : 0;
                to_up = {hit1, hit0};
                to_do = {hit3, hit2};
            join
            if (cnt == 10000) disable hit_generation;
        end
    end
end

So, now the problem is, if it AMOUNT_OF_REGIONS == 3 or 2 then everything works fine, but if i'm trying to increase its value then for all the regions that are between 1 and AMOUNT_OF_REGIONS-2 (including), their inputs and outputs are messed up (2'bzz). But 0 region sends info to region 1 pretty well, and AMOUNT_OF_REGIONS-1 region sends the info properly to it's neighbor. Test bench is just instantiating a column and generates a trigger and clk signals. I've read that if there are only wires connections without attachment to the registers that can cause high impedance state, but as far as i can see, i'm connecting wires to the output registers...Dear all, what could be a problem of it? I'm using Icarus Verilog, if it matters.


Solution

  • Accidentally, i've found the root of my problem. I will leave an answer, may be it will help some day to somebody who will be stuck in situation like this.

    I made the wrong port assignment, so, i guess, they was cycled or something like that. The problem was that here:

    region tmp(
        clk,
        reset,
        trigger,
        latency,
        do_out[i-1],
        up_out[i+1],
        do_in[i-1],
        up_in[i+1],
        o_data[i]
    );
    

    I assigned input ports of module to output of another and it was the mistake...

    So the proper way of assigning ports in such situation is like this (full code of instantiation cycle):

    generate
        genvar i;
        for (i = 0; i < AMOUNT_OF_REGIONS; i = i + 1) begin : multiple_regions_instantiation
            if (i == 0) begin
                region tmp(
                    clk,
                    reset,
                    trigger,
                    latency,
                    up_in[i],
                    do_in[i],
                    up_out[i],
                    up_in[i+1], //CHANGED
                    o_data[i]
                );
            end
            else if (i == AMOUNT_OF_REGIONS-1) begin
                region tmp(
                    clk,
                    reset,
                    trigger,
                    latency,
                    up_in[i],
                    do_in[i],
                    do_in[i-1], //CHANGED
                    do_out[i],
                    o_data[i]
                );
            end
            else begin
                region tmp(
                    clk,
                    reset,
                    trigger,
                    latency,
                    up_in[i], //CHANGED
                    do_in[i], //CHANGED
                    do_in[i-1],
                    up_in[i+1],
                    o_data[i]
                );
            end
        end
    endgenerate
    

    Hope it will help somebody!