2024-10-19 00:01:38 +02:00
|
|
|
module dvi #(
|
2024-10-25 20:26:58 +02:00
|
|
|
parameter [23:0] BASE_ADDR = 24'h000000,
|
2024-10-19 00:01:38 +02:00
|
|
|
|
|
|
|
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,
|
2024-10-25 20:26:58 +02:00
|
|
|
output reg [23:0] bus_addr,
|
2024-10-19 00:01:38 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2024-10-19 20:23:33 +02:00
|
|
|
if (~reset) output_state <= OUTPUT_BLANK;
|
2024-10-19 00:01:38 +02:00
|
|
|
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
|
2024-10-19 20:23:33 +02:00
|
|
|
if (output_state == OUTPUT_IDLE) ck <= 0;
|
|
|
|
else ck <= ~ck;
|
|
|
|
|
|
|
|
if (y == 11'b0) begin
|
|
|
|
bus_addr <= BASE_ADDR;
|
|
|
|
|
|
|
|
fetch_state <= FETCH_LOW;
|
|
|
|
end
|
2024-10-19 00:01:38 +02:00
|
|
|
|
|
|
|
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
|