pixelflut/dvi.v

155 lines
3.3 KiB
Verilog

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