verilogvga

CPLD Pins not being driven


I'm building a VGA controller from a Lattice CPLD using Verilog. I have had a decent amount of exposure to Verilog in the past, but it's been a while and I'm rusty and at a point where the sync lines needed to control the monitor are not being driven (checking with O.Scope), and I'm not sure why not.

I have tried to simulate the code in Active-HDL but I get a strange error message (Failed to allocate memory for non-blocking transaction) and get warnings that the counters have no load (which I believe that I can ignore in this case?) The code follows below:

module CtrlLines(NRST, CLK, H_SYNC, V_SYNC);
    input  wire CLK;        /*< CLK input from Top module   >*/
    input  wire NRST;       /*< Reset input from Top module >*/
    output reg  H_SYNC;
    output reg  V_SYNC;

    reg [10:0] h_counter;   /*< Tracks amount of pulses from CLK    >*/
    reg [10:0] v_counter;   /*< Tracks amount of pulses from H_SYNC >*/

    `define H_FRONT_PORCH   10'd95
    `define H_BACK_PORCH    10'd720
    `define H_COUNT_MAX     10'd800

    `define V_FRONT_PORCH   10'd2
    `define V_BACK_PORCH    10'd514
    `define V_COUNT_MAX     10'd528

    always @(negedge NRST, posedge CLK) begin
        if (!NRST) begin
            h_counter <= 10'b00;
        end
        else begin
            h_counter <= h_counter + 1'b1;
            case (h_counter)
                `H_FRONT_PORCH: H_SYNC <= 1;    /*< If the counter has reached Front Porch, go High >*/
                `H_BACK_PORCH : H_SYNC <= 0;    /*< If the counter has reached Back Porch, go Low   >*/
                `H_COUNT_MAX  : h_counter <= 0; /*< If the counter has reached Max, Reset   >*/
            endcase                             /*< Else, remain at current level           >*/
        end
    end

    always @(negedge NRST, negedge H_SYNC) begin
        if (!NRST) begin
            v_counter <= 10'b00;
        end
        else begin
            v_counter <= v_counter +1'b1;
            case (v_counter)
                `V_FRONT_PORCH  : V_SYNC <= 1;
                `V_BACK_PORCH   : V_SYNC <= 0;
                `V_COUNT_MAX    : v_counter <= 0;
            endcase
        end
    end
endmodule

Solution

  • This code is problematic because you have multiple nonblocking assignments to the same reg (h_counter). It is nondeterministic which one will be executed first, which leads to simulation race conditions:

        h_counter <= h_counter + 1'b1;
        case (h_counter)
            `H_FRONT_PORCH: H_SYNC <= 1;    /*< If the counter has reached Front Porch, go High >*/
            `H_BACK_PORCH : H_SYNC <= 0;    /*< If the counter has reached Back Porch, go Low   >*/
            `H_COUNT_MAX  : h_counter <= 0; /*< If the counter has reached Max, Reset   >*/
    

    My guess is that your synthesis tool has a problem with this as well.

    Perhaps you meant for the increment to occur in thedefault clause of the case statement.

    The same applies to v_counter.