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
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
.