4x16 decoder using 2x4 decoders not working correctly

474 Views Asked by At

I'm currently working on a Verilog project where I'm attempting to run a testbench for a 4x16 decoder using a 2x4 decoder. However, I'm encountering problems with the output. I've provided the code below, and I believe I've correctly connected all the ports. If anyone could help me identify and resolve the issue, and possibly explain the problem, I would greatly appreciate it.

Code:

module decoder4x16_with_2x4(Y, d, e);
    output [15:0] Y;
    input [3:0] d;
    input e;
    wire [3:0] w;

    decoder2_to_4 De0(.F({w[3],w[2],w[1],w[0]}), .i({d[1],d[0]}), .e(e)),
                  De1(.F({Y[3],Y[2],Y[1],Y[0]}), .i({d[3],d[2]}), .e(w[0])),
                  De2(.F({Y[7],Y[6],Y[5],Y[4]}), .i({d[3],d[2]}), .e(w[1])),
                  De3(.F({Y[11],Y[10],Y[9],Y[8]}), .i({d[3],d[2]}), .e(w[2])),
                  De4(.F({Y[15],Y[14],Y[13],Y[12]}), .i({d[3],d[2]}), .e(w[3]));
endmodule

module decoder4x16_with_2x4_tb();
    reg [3:0] i;
    wire [15:0] f;

    decoder4x16_with_2x4 muxi(.Y(f), .d(i), .e(1'b1));

    initial begin
        $monitor("d = %b --> Y = %b", i, f);
        repeat(10) begin
            i = $random; #1;
        end
    end
endmodule

module decoder2_to_4(F, i, e);
    output reg [3:0] F;
    input [1:0] i;
    input e;

    always@(i) begin
        if (e == 1'b1) begin
            case(i)
                2'b00 : F = 4'b0001;
                2'b01 : F = 4'b0010;
                2'b10 : F = 4'b0100;
                2'b11 : F = 4'b1000;
                default : $display("Invalid data received!!");
            endcase
        end
        else begin
            F = 1'b0;
        end
    end
endmodule

Testbench Output:

# d = 0100 --> Y = 0000000000000000 
# d = 0001 --> Y = 0000000000000001
# d = 1001 --> Y = 0000000001000000
# d = 0011 --> Y = 0000000000010000
# d = 1101 --> Y = 1000000000000000
# d = 0101 --> Y = 0000000000100000
# d = 0010 --> Y = 0000000000010000
# d = 0001 --> Y = 0000000000010000
# d = 1101 --> Y = 0000000010000000

Description:

I've used the provided Verilog code, and despite carefully connecting all the ports, I'm not getting the expected output. Any help in identifying the issue and providing a solution would be greatly appreciated.

1

There are 1 best solutions below

0
toolic On

You should also look at waveforms of internal signals when debugging problematic simulations. Displaying values to the output file/console is usually insufficient.

When I look at waveforms of the decoder2_to_4 instances, I see that it is behaving properly (when applying the fix mentioned in the comment on your question). Since your port connections in your testbench are also correct, I conclude that you made a mistake somewhere in the decoder4x16_with_2x4 module. There are many port connections there, so you need to compare those code connections to whatever schematic model you have.

A better approach is to model your design at a higher level of abstraction. You should use behavioral modeling instead of trying to wire up instances of basic blocks. Here is a complete code example which shows the expected output:

module decoder4x16_with_2x4(Y, d, e);
    output reg [15:0] Y;
    input [3:0] d;
    input e;

    always @* begin
        for (int i=0; i<16; i++) begin
            Y[i] = e & (d == i);
        end
    end
endmodule

module decoder4x16_with_2x4_tb();
    reg [3:0] i;
    wire [15:0] f;

    decoder4x16_with_2x4 muxi(.Y(f), .d(i), .e(1'b1));

    initial begin
        $monitor("d = %02d --> Y = %b", i, f);
        repeat(10) begin
            i = $random; #1;
        end
    end
endmodule

Output:

d = 04 --> Y = 0000000000010000
d = 01 --> Y = 0000000000000010
d = 09 --> Y = 0000001000000000
d = 03 --> Y = 0000000000001000
d = 13 --> Y = 0010000000000000
d = 05 --> Y = 0000000000100000
d = 02 --> Y = 0000000000000100
d = 01 --> Y = 0000000000000010
d = 13 --> Y = 0010000000000000