feat: add display driver

This commit is contained in:
Luca 2024-10-19 00:01:38 +02:00
parent a362cff8ca
commit f651a31f04
4 changed files with 191 additions and 1 deletions

View File

@ -22,5 +22,5 @@ pixelflut.frames: pixelflut.fasm
pixelflut.fasm: arty_a7_35t.xdc pixelflut.json
nextpnr-xilinx --chipdb "$(CHIPDB_DIR)/$(PART).bin" --fasm $@ --json pixelflut.json --xdc arty_a7_35t.xdc
pixelflut.json: pixelflut.v
pixelflut.json: pixelflut.v dvi.v
yosys -q -p 'synth_xilinx -top pixelflut; write_json $@' $^

View File

@ -41,23 +41,39 @@ set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports led0_r]
## Pmod Header JA
#set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports ja[0]] #IO_0_15 Sch=ja[1]
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports dvi_d[11]]
#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports ja[1]] #IO_L4P_T0_15 Sch=ja[2]
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports dvi_d[9]]
#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports ja[2]] #IO_L4N_T0_15 Sch=ja[3]
set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports dvi_d[7]]
#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports ja[3]] #IO_L6P_T0_15 Sch=ja[4]
set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports dvi_d[5]]
#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports ja[4]] #IO_L6N_T0_VREF_15 Sch=ja[7]
set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports dvi_d[10]]
#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports ja[5]] #IO_L10P_T1_AD11P_15 Sch=ja[8]
set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports dvi_d[8]]
#set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports ja[6]] #IO_L10N_T1_AD11N_15 Sch=ja[9]
set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports dvi_d[6]]
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports ja[7]] #IO_25_15 Sch=ja[10]
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports dvi_d[4]]
## Pmod Header JB
#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports jb[0]] #IO_L11P_T1_SRCC_15 Sch=jb_p[1]
set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports dvi_d[3]]
#set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports jb[1]] #IO_L11N_T1_SRCC_15 Sch=jb_n[1]
set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports dvi_d[1]]
#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports jb[2]] #IO_L12P_T1_MRCC_15 Sch=jb_p[2]
set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports dvi_ck]
#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports jb[3]] #IO_L12N_T1_MRCC_15 Sch=jb_n[2]
set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports dvi_hs]
#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports jb[4]] #IO_L23P_T3_FOE_B_15 Sch=jb_p[3]
set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports dvi_d[2]]
#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports jb[5]] #IO_L23N_T3_FWE_B_15 Sch=jb_n[3]
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports dvi_d[0]]
#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports jb[6]] #IO_L24P_T3_RS1_15 Sch=jb_p[4]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports dvi_de]
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports jb[7]] #IO_L24N_T3_RS0_15 Sch=jb_n[4]
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports dvi_vs]
## Pmod Header JC
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports jc[0]] #IO_L20P_T3_A08_D24_14 Sch=jc_p[1]

154
dvi.v Normal file
View File

@ -0,0 +1,154 @@
module dvi #(
parameter [15:0] BASE_ADDR = 16'h0000,
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 [15: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) begin
ck <= 0;
output_state <= OUTPUT_BLANK;
end
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
bus_addr <= BASE_ADDR;
fetch_state <= FETCH_LOW;
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 <= ~ck;
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

View File

@ -4,6 +4,12 @@ module pixelflut (
output led0_r,
output led0_g,
output led0_b,
output [11:0] dvi_d,
output dvi_ck,
output dvi_de,
output dvi_hs,
output dvi_vs,
);
reg [31:0] ctr;
reg [2:0] led0_state = 3'b0;
@ -20,4 +26,18 @@ module pixelflut (
ctr <= ctr + 1'b1;
end
end
wire [15:0] dvi_bus;
dvi display (
.bus_clk (sys_clk),
.bus_data(dvi_bus),
.bus_addr(dvi_bus),
.reset (1'b0),
.d (dvi_d),
.ck (dvi_ck),
.de (dvi_de),
.hs (dvi_hs),
.vs (dvi_vs),
);
endmodule