Progressive video generator

Rainy weekend resulted in this basic Video Generator for Verilog.
It can be user-adjusted for progressive timings (total line length, total
line count; number of active pixels per line and lines in frame; HS and VS
duration, backporches and frontporches; hv offset, and polarity of
outputs: hs, vs, de;

I wrote it under linux using iVerilog; GTKWave to simulate results. See
some of pictures below. Source is .ZIPped on the bottom along with makefile.

Source:

/* Written by Witold Kaczurba, www.witold.kaczurba.pl, Oct 2011; */
module sync_gen(reset, clk_in, load, total_ll, total_lc, h_bp, h_sync, h_fp, h_active, v_active,
               hv_offset, v_bp, v_sync, v_fp, v_pol, h_pol, de_pol, hs, vs, de);
/*
 TODO: Check this for positive syncs. Negative syncs checked ok.
*/
 input reset;             // reset
 input clk_in;            // clock
 input load;              // loads parameters into internal FF
 input [12:0] total_ll;   // total line length
 input [11:0] total_lc;   // total line count
 input [8:0] h_bp;        // hsync backporch
 input [8:0] h_sync;      // hsync length
 input [8:0] h_fp;        // hsync frontporch
 input [12:0] h_active;    // de length (horizontal)
 input [11:0] v_active;   // de length (vertical, lines)
 input [8:0] v_bp;        // vsync backporch
 input [8:0] v_sync;      // vsync length
 input [8:0] v_fp;        // vsync frontporch
 input v_pol;             // vsync polarity
 input h_pol;             // hsync polarity
 input de_pol;            // de polarity
 input [11:0] hv_offset;  // hv offset

 output hs;               // hs
 output vs;               // vs
 output de;               // de

 reg [12:0] hcount; // horizontal counter (12/13/14/15 bits: 4096/8192/16384/32768)
 reg [11:0] lcount; // line counter (10/11/12/13 bits = 1024/2048/4096/8192)

 reg [12:0] hcount_r;// delayed hcount
 reg [11:0] lcount_r;// delayed lcount

 reg de; // de output
 reg hs; // hs output
 reg vs; // vs output

 /* internal flip flops */
 reg [12:0] max_hcount;
 reg [11:0] max_lcount;
 reg [8:0]  hs_beg;
 reg [9:0]  hs_end;
 reg [9:0]  de_beg;
 reg [12:0] de_end;
 reg [9:0]  de_vbeg;
 reg [11:0] de_vend;
 reg [8:0]  vs_beg;
 reg [9:0]  vs_end;

 /* async loading data */
 always @(posedge load)
 begin
   /* predef - optimization: */
   max_hcount <= total_ll - 1;
   max_lcount <= total_lc - 1;
   hs_beg <= h_fp;
   hs_end <= h_fp + h_sync;
   de_beg <= h_fp + h_sync + h_bp;
   de_end <= h_fp + h_sync + h_bp + h_active;
   de_vbeg <= v_fp + v_sync + v_bp;
   de_vend <= v_fp+v_sync+v_bp + v_active;
   vs_beg <= v_fp;
   vs_end <= v_fp + v_sync;
 end

 /* horizontal & line counter */
 always @(posedge clk_in)
 begin
   if (reset) begin
      hcount <= 0;
      lcount <= 0;
   end else begin
      if (hcount < max_hcount)
         hcount <= hcount + 1;
      else begin
         hcount <= 0;
         if (lcount < max_lcount)
            lcount <= lcount +1;
         else
            lcount <= 0;
      end
   end
 end

 /* delay of +1FF */
 always @(posedge clk_in)
 begin
   lcount_r <= lcount;
   hcount_r <= hcount;
 end

 /* hsync output + 1FF */
 always @(posedge clk_in)
 begin
   if ((hcount >= hs_beg) && (hcount < hs_end))
       hs <= h_pol;
   else
       hs <= !h_pol;
 end

 // de output + 1FF
 always @(posedge clk_in)
 begin
   if ((hcount >= de_beg) && (hcount < de_end))
   begin
       if ((lcount >= de_vbeg) && (lcount < de_vend))
           de <= de_pol;
   end else
       de <= !de_pol;
 end

 // vsync output
 always @(posedge clk_in)
 begin
     /* below should be simplified */
     if (((lcount < vs_beg) || (lcount == vs_beg && hcount < hs_beg + hv_offset)) ||
        ((lcount > vs_end) || (lcount == vs_end && hcount >= hs_beg + hv_offset)))
        vs <= !v_pol;
     else
        vs <= v_pol;
 end

endmodule

Testbench:

/* Written by Witold Kaczurba, www.witold.kaczurba.pl, Oct 2011; */
`timescale 1ns/100ps
module gen1_tb;

reg clk;
reg reset;
reg load;

// internal wires from sync_gen to other instances (e.g. syncn_det1)
wire hs;
wire vs;
wire de;

initial begin
 clk = 0;
 load = 0;
 reset = 1;
 $dumpfile("gen1_tb");
 $dumpvars;
 #1 load = 1;
 #5 load = 0;
 #13 reset=0;
 #5000000 $finish;
end

/* this one below generates 640 x 480p */
sync_gen sync_gen(.reset(reset),
       .clk_in(clk),
       .load(load),
       .total_ll(12'd800), // ok
       .total_lc(11'd525), // ok
       .h_bp(9'd48), // ok
       .h_sync(9'd96), // ok
       .h_fp(9'd16), // ok
       .h_active(12'd640), // h_active = 640
       .v_active(11'd480), // v_active = 480
       .v_bp(33), // ok
       .v_sync(2), // ok
       .v_fp(10),
       .v_pol(1'b0),
       .h_pol(1'b0),
       .de_pol(1'b1),
       .hv_offset(12'd0), // looks ok
       .hs(hs),
       .vs(vs),
       .de(de)
       );

always @*
 #5 clk <= !clk;

endmodule