module dvi #( parameter [23:0] BASE_ADDR = 24'h000000, parameter H_ACTIVE_START = 136, parameter H_BLANK_START = 792, parameter H_DATA_START = 306, parameter H_DATA_END = 622, parameter H_SYNC_ACTIVE = 0, parameter H_SYNC_TIME = 96, parameter H_TOTAL = 800, parameter V_ACTIVE_START = 27, parameter V_BLANK_START = 523, parameter V_DATA_START = 157, parameter V_DATA_END = 394, parameter V_SYNC_ACTIVE = 0, parameter V_SYNC_TIME = 2, parameter V_TOTAL = 525 ) ( input bus_clk, input [15:0] bus_data, output reg [23:0] bus_addr, input reset, output reg [11:0] d, output reg ck, output reg de, output hs, output vs ); localparam OUTPUT_IDLE = 2'b00; localparam OUTPUT_BLANK = 2'b01; localparam OUTPUT_DATA = 2'b10; localparam FETCH_LOW = 2'b00; localparam FETCH_MID = 2'b01; localparam FETCH_HIGH = 2'b10; localparam FETCH_SWAP = 2'b11; reg [1:0] output_state; reg fetch_en; reg [1:0] fetch_state; reg [47:0] data [1:0]; reg active_data; reg [11:0] x; reg [10:0] y; assign hs = x < H_SYNC_TIME ? H_SYNC_ACTIVE : ~H_SYNC_ACTIVE; assign vs = y < V_SYNC_TIME ? V_SYNC_ACTIVE : ~V_SYNC_ACTIVE; initial begin bus_addr <= BASE_ADDR; d <= 12'b0; ck <= 0; de <= 0; output_state <= OUTPUT_IDLE; fetch_en <= 0; fetch_state <= FETCH_LOW; data[0] <= 48'b0; data[1] <= 48'b0; active_data <= 0; x <= 12'b0; y <= 11'b0; end always @(posedge bus_clk) begin de <= 0; fetch_en <= 0; if (~ck) x <= x + 1; if (reset) output_state <= OUTPUT_IDLE; case (output_state) OUTPUT_IDLE: begin x <= 12'b0; y <= 11'b0; if (~reset) output_state <= OUTPUT_BLANK; end OUTPUT_BLANK: begin if (y >= V_ACTIVE_START && y < V_BLANK_START && x == H_ACTIVE_START-1) output_state <= OUTPUT_DATA; if (~ck && x == H_TOTAL-1) begin x <= 12'b0; y <= y + 1; if (y == V_TOTAL-1) begin y <= 11'b0; end end end OUTPUT_DATA: begin d <= 12'b0; de <= 1; if (y == V_DATA_START && (~ck && x == H_DATA_START-3 || x >= H_DATA_START-2) && x < H_DATA_START) fetch_en <= 1; if (y >= V_DATA_START && y < V_DATA_END && x >= H_DATA_START && x < H_DATA_END) begin d <= data[active_data][11:0]; fetch_en <= 1; end if (x == H_BLANK_START-1) begin output_state <= OUTPUT_BLANK; end end default: begin output_state <= OUTPUT_IDLE; end endcase end always @(negedge bus_clk) begin if (output_state == OUTPUT_IDLE) ck <= 0; else ck <= ~ck; if (y == 11'b0) begin bus_addr <= BASE_ADDR; fetch_state <= FETCH_LOW; end if (fetch_en) begin data[active_data] <= {12'b0, data[active_data][47:12]}; if (fetch_state != FETCH_SWAP) bus_addr <= bus_addr + 1; case (fetch_state) FETCH_LOW: begin fetch_state <= FETCH_MID; data[~active_data][15:0] <= bus_data; end FETCH_MID: begin fetch_state <= FETCH_HIGH; data[~active_data][31:16] <= bus_data; end FETCH_HIGH: begin fetch_state <= FETCH_SWAP; data[~active_data][47:32] <= bus_data; end FETCH_SWAP: begin fetch_state <= FETCH_LOW; active_data <= ~active_data; end endcase end end endmodule