VGA (Video Graphics Array)





module clock_divider (
  	input clk_i,
  	input rst_i,
  	output clk_o
  );

  reg clk_d, clk_q;
  assign clk_o = clk_q;

  always @(*) begin
  	clk_d = ~clk_q;
  end

  always @(posedge clk_i) begin
  	if (rst_i)
  		clk_q <= 1'b0;
  	else
  		clk_q <= clk_d;
  end

  endmodule
  

module vertical_counter (
          input clk_i,
          input increment_i,
          input rst_i,
          output [8:0] y_o
        );

        reg [8:0] y_d, y_q;
        assign y_o = y_q;

        always @(*) begin
          if (increment_i)
            y_d = y_q + 1;
          else
            y_d = y_q;
        end

        always @(posedge clk_i) begin
          if (rst_i)
            y_q <= 9'b000000000;
          else
            y_q <= y_d;
        end

        endmodule
        

module horizontal_counter (
          input clk_i,
          input rst_i,
          output [9:0] x_o
        );

        reg [9:0] x_d, x_q;
        assign x_o = x_q;

        always @(*) begin
          x_d = x_q + 1;
        end

        always @(posedge clk_i) begin
          if (rst_i)
            x_q <= 8'd0;
          else
            x_q <= x_d;
        end

        endmodule
        

module horizontal_state_machine (
          input clk_i,
          input rst_i,
          input vertical_active_video_i,
          input [9:0] horizontal_counter_i,

          // Mealy Outputs
          output reg horizontal_counter_rst_o,
          output reg vertical_counter_increment_o,

          // Moore Outputs
          output reg horizontal_active_video_o,
          output reg sync_pulse_o
        );

        reg [1:0] state, nextstate;

        localparam STATE_FRONT_PORCH = 0;
        localparam STATE_SYNC_PULSE = 1;
        localparam STATE_BACK_PORCH = 2;
        localparam STATE_ACTIVE_VIDEO = 3;

        always @(posedge clk_i) begin
        	if (rst_i) begin
        		state <= STATE_FRONT_PORCH;
        	end else begin
        		state <= nextstate;
        	end
        end

        // Mealy Outputs and nextstate
        always @(*) begin
          horizontal_counter_rst_o = 1'b0;
          vertical_counter_increment_o = 1'b0;

          case (state)
            STATE_FRONT_PORCH:
              if (horizontal_counter_i == 10'd16) begin
                horizontal_counter_rst_o = 1'b1;
                nextstate = STATE_SYNC_PULSE;
              end else begin
                nextstate = STATE_FRONT_PORCH;
              end

            STATE_SYNC_PULSE:
              if (horizontal_counter_i == 10'd96) begin
                horizontal_counter_rst_o = 1'b1;
                nextstate = STATE_BACK_PORCH;
              end else begin
                nextstate = STATE_SYNC_PULSE;
              end

            STATE_BACK_PORCH:
              if (horizontal_counter_i == 10'd48) begin
                horizontal_counter_rst_o = 1'b1;
                nextstate = STATE_ACTIVE_VIDEO;
              end else begin
                nextstate = STATE_BACK_PORCH;
              end

            STATE_ACTIVE_VIDEO:
              if (horizontal_counter_i == 10'd640) begin
                horizontal_counter_rst_o = 1'b1;
                vertical_counter_increment_o = 1'b1;
                nextstate = STATE_FRONT_PORCH;
              end else begin
                nextstate = STATE_ACTIVE_VIDEO;
              end
          endcase
        end

        // Moore Outputs
        always @(*) begin
          horizontal_active_video_o = 1'b0;
          sync_pulse_o = 1'b1;

          case (state)
            STATE_SYNC_PULSE:
            begin
              sync_pulse_o = 1'b0;
            end
            STATE_ACTIVE_VIDEO:
            begin
              horizontal_active_video_o = 1'b1;
            end
          endcase
        end

        endmodule
        

module vertical_state_machine (
          input clk_i,
          input rst_i,
          input [8:0] vertical_counter_i,

          // Mealy Outputs
          output reg horizontal_state_machine_rst_o,
          output reg vertical_counter_rst_o,

          // Moore Outputs
          output reg vertical_active_video_o,
          output reg sync_pulse_o
        );

        reg [1:0] state, nextstate;

        localparam STATE_FRONT_PORCH = 0;
        localparam STATE_SYNC_PULSE = 1;
        localparam STATE_BACK_PORCH = 2;
        localparam STATE_ACTIVE_VIDEO = 3;

        always @(posedge clk_i) begin
        	if (rst_i) begin
        		state <= STATE_FRONT_PORCH;
        	end else begin
        		state <= nextstate;
        	end
        end

        // Mealy Outputs and nextstate
        always @(*) begin
          horizontal_state_machine_rst_o = 1'b0;
          vertical_counter_rst_o = 1'b0;

          case (state)
            STATE_FRONT_PORCH:
              if (vertical_counter_i == 9'd10) begin
                vertical_counter_rst_o = 1'b1;
                nextstate = STATE_SYNC_PULSE;
              end else begin
                nextstate = STATE_FRONT_PORCH;
              end

            STATE_SYNC_PULSE:
              if (vertical_counter_i == 9'd2) begin
                vertical_counter_rst_o = 1'b1;
                nextstate = STATE_BACK_PORCH;
              end else begin
                nextstate = STATE_SYNC_PULSE;
              end

            STATE_BACK_PORCH:
              if (vertical_counter_i == 9'd33) begin
                vertical_counter_rst_o = 1'b1;
                horizontal_state_machine_rst_o = 1'b1;
                nextstate = STATE_ACTIVE_VIDEO;
              end else begin
                nextstate = STATE_BACK_PORCH;
              end

            STATE_ACTIVE_VIDEO:
              if (vertical_counter_i == 9'd480) begin
                vertical_counter_rst_o = 1'b1;
                nextstate = STATE_FRONT_PORCH;
              end else begin
                nextstate = STATE_ACTIVE_VIDEO;
              end
          endcase
        end

        // Moore Outputs
        always @(*) begin
          vertical_active_video_o = 1'b0;
          sync_pulse_o = 1'b1;

          case (state)
            STATE_SYNC_PULSE:
            begin
              sync_pulse_o = 1'b0;
            end
            STATE_ACTIVE_VIDEO:
            begin
              vertical_active_video_o = 1'b1;
            end
          endcase
        end

        endmodule
        

module chip_top (
          input clk_i,
          input rst_i,
          output hsync_o,
          output vsync_o,
          output r_o,
          output g_o,
          output b_o
        );

        wire hsync;
        wire vsync;
        wire r;
        wire g;
        wire b;
        wire [9:0] x;
        wire [8:0] y;
        wire active_video_horizontal;
        wire active_video_vertical;
        wire horizontal_state_machine_rst;
        wire horizontal_counter_rst;
        wire vertical_counter_increment;
        wire vertical_counter_rst;
        wire clk;

        assign hsync_o = hsync;
        assign vsync_o = vsync;
        assign r_o = active_video_horizontal & active_video_vertical & r;
        assign g_o = active_video_horizontal & active_video_vertical & g;
        assign b_o = active_video_horizontal & active_video_vertical & b;

        clock_divider clock_divider0 (
        	.clk_i(clk_i),
        	.rst_i(rst_i),
        	.clk_o(clk)
        );

        horizontal_counter horizontal_counter0 (
          .clk_i(clk),
          .rst_i(horizontal_counter_rst | rst_i),
          .x_o(x)
        );

        vertical_counter vertical_counter0 (
          .clk_i(clk),
          .increment_i(vertical_counter_increment),
          .rst_i(vertical_counter_rst | rst_i),
          .y_o(y)
        );

        horizontal_state_machine horizontal_state_machine0 (
          .clk_i(clk),
          .rst_i(horizontal_state_machine_rst | rst_i),
          .vertical_active_video_i(active_video_vertical),
          .horizontal_counter_i(x),
          .horizontal_counter_rst_o(horizontal_counter_rst),
          .vertical_counter_increment_o(vertical_counter_increment),
          .horizontal_active_video_o(active_video_horizontal),
          .sync_pulse_o(hsync)
        );

        vertical_state_machine vertical_state_machine0 (
          .clk_i(clk),
          .rst_i(rst_i),
          .vertical_counter_i(y),
          .horizontal_state_machine_rst_o(horizontal_state_machine_rst),
          .vertical_counter_rst_o(vertical_counter_rst),
          .vertical_active_video_o(active_video_vertical),
          .sync_pulse_o(vsync)
        );

        kord_logo_lut kord_logo_lut0 (
        	.x_i(x),
        	.y_i(y),
        	.red_o(r),
        	.green_o(g),
        	.blue_o(b)
        );

        endmodule