Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,20 @@ You can also see the full output from the [Python model](model/tmds-test-python.


## Resource Utilization
The display controller is lightweight, fitting into even the smallest FPGA:
The display controller is lightweight, fitting comfortably into even small FPGAs.

Artix-7
Demo LUT FF
---------------------------
DVI on FPGA 125 76
DVI BML 3-bit 67 32
DVI BML 24-bit TBC TBC
VGA 67 32
The following table shows utilization of the display-controller with the gradient test card at a resolution of 640x480.

For reference an Artix A35T has 20,800 LUT6 and 41,600 FF, so even full TMDS uses well under 1% of the LUTs. Values are for demos using the simple test card module. Synthesized using Vivado 2018.3 with default options.
Artix-7
Interface LUT FF
-----------------------------
DVI on FPGA 278 78
DVI BML 3-bit 49 32
DVI BML 24-bit TBC TBC
VGA 12-bit 67 32
-----------------------------
Synthesized and implemented with Vivado 2019.1 using default options.

For comparison an Artix A35T has 20,800 LUT6 and 41,600 FF, while the tiny Spartan 7S6 has 3,752 LUT6 and 7,500 FF.

NB. If you drive the "DVI on FPGA" display controller with a few fixed colours, such as the simple test bench, the optimizer removes a significant part of the design, resulting in misleadingly low utilization.
48 changes: 36 additions & 12 deletions hdl/demo/display_demo_dvi.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
// * display_timings
// * dvi_generator
// * serializer_10to1
// * test_card
// * tmds_encoder_dvi
// * test_card_simple or another test card

module display_demo_dvi(
input wire CLK, // board clock: 100 MHz on Arty/Basys3/Nexys
Expand Down Expand Up @@ -83,20 +83,44 @@ module display_demo_dvi(
.o_y(y)
);

// Test Card Generation
wire red, green, blue;
test_card #(
.H_RES(1280),
.V_RES(720)
)
test_card_inst (
// test card colour output
wire [7:0] red;
wire [7:0] green;
wire [7:0] blue;

// Test Card: Simple - ENABLE ONE TEST CARD INSTANCE ONLY
test_card_simple #(
.H_RES(1280) // horizontal resolution
) test_card_inst (
.i_x(x),
.i_y(y),
.o_red(red),
.o_green(green),
.o_blue(blue)
);

// // Test Card: Squares - ENABLE ONE TEST CARD INSTANCE ONLY
// test_card_squares #(
// .H_RES(1280), // horizontal resolution
// .V_RES(720) // vertical resolution
// )
// test_card_inst (
// .i_x(x),
// .i_y(y),
// .o_red(red),
// .o_green(green),
// .o_blue(blue)
// );

// // Test Card: Gradient - ENABLE ONE TEST CARD INSTANCE ONLY
// localparam GRAD_STEP = 2; // step right shift: 480=2, 720=2, 1080=3
// test_card_gradient test_card_inst (
// .i_y(y[GRAD_STEP+7:GRAD_STEP]),
// .i_x(x[5:0]),
// .o_red(red),
// .o_green(green),
// .o_blue(blue)
// );

// TMDS Encoding and Serialization
wire tmds_ch0_serial, tmds_ch1_serial, tmds_ch2_serial, tmds_chc_serial;
dvi_generator dvi_out (
Expand All @@ -105,9 +129,9 @@ module display_demo_dvi(
.i_clk_lock(clk_lock),
.i_rst(rst),
.i_de(de),
.i_data_ch0({8{blue}}),
.i_data_ch1({8{green}}),
.i_data_ch2({8{red}}),
.i_data_ch0(blue),
.i_data_ch1(green),
.i_data_ch2(red),
.i_ctrl_ch0({v_sync, h_sync}),
.i_ctrl_ch1(2'b00),
.i_ctrl_ch2(2'b00),
Expand Down
49 changes: 37 additions & 12 deletions hdl/demo/display_demo_dvi_pmod3.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// This demo requires the following Verilog modules:
// * display_clocks
// * display_timings
// * test_card
// * test_card_simple or another test card

module display_demo_dvi_pmod3(
input wire CLK, // board clock: 100 MHz on Arty/Basys3/Nexys
Expand Down Expand Up @@ -78,26 +78,51 @@ module display_demo_dvi_pmod3(
.o_y(y)
);

// Test Card Generation
wire red, green, blue;
test_card #(
.H_RES(640),
.V_RES(480)
)
test_card_inst (
// test card colour output
wire [7:0] red;
wire [7:0] green;
wire [7:0] blue;

// Test Card: Simple - ENABLE ONE TEST CARD INSTANCE ONLY
test_card_simple #(
.H_RES(640) // horizontal resolution
) test_card_inst (
.i_x(x),
.i_y(y),
.o_red(red),
.o_green(green),
.o_blue(blue)
);

// // Test Card: Squares - ENABLE ONE TEST CARD INSTANCE ONLY
// test_card_squares #(
// .H_RES(640), // horizontal resolution
// .V_RES(480) // vertical resolution
// )
// test_card_inst (
// .i_x(x),
// .i_y(y),
// .o_red(red),
// .o_green(green),
// .o_blue(blue)
// );

// // Test Card: Gradient - ENABLE ONE TEST CARD INSTANCE ONLY
// localparam GRAD_STEP = 2; // step right shift: 480=2, 720=2, 1080=3
// test_card_gradient test_card_inst (
// .i_x(x[5:0]),
// .i_y(y[GRAD_STEP+7:GRAD_STEP]),
// .o_red(red),
// .o_green(green),
// .o_blue(blue)
// );

// 3-bit DVI Output
// Only 1 bit per colours, so we take the MSB of each colour
assign DVI_HS = h_sync;
assign DVI_VS = v_sync;
assign DVI_CLK = pix_clk;
assign DVI_DE = de;
assign DVI_R = de & red;
assign DVI_G = de & green;
assign DVI_B = de & blue;
assign DVI_R = de ? red[7] : 1'b0;
assign DVI_G = de ? green[7] : 1'b0;
assign DVI_B = de ? blue[7] : 1'b0;
endmodule
49 changes: 37 additions & 12 deletions hdl/demo/display_demo_vga.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// This demo requires the following Verilog modules:
// * display_clocks
// * display_timings
// * test_card
// * test_card_simple or another test card

module display_demo_vga(
input wire CLK, // board clock: 100 MHz on Arty/Basys3/Nexys
Expand Down Expand Up @@ -76,24 +76,49 @@ module display_demo_vga(
.o_y(y)
);

// Test Card Generation
wire red, green, blue;
test_card #(
.H_RES(640),
.V_RES(480)
)
test_card_inst (
// test card colour output
wire [7:0] red;
wire [7:0] green;
wire [7:0] blue;

// Test Card: Simple - ENABLE ONE TEST CARD INSTANCE ONLY
test_card_simple #(
.H_RES(640) // horizontal resolution
) test_card_inst (
.i_x(x),
.i_y(y),
.o_red(red),
.o_green(green),
.o_blue(blue)
);

// // Test Card: Squares - ENABLE ONE TEST CARD INSTANCE ONLY
// test_card_squares #(
// .H_RES(640), // horizontal resolution
// .V_RES(480) // vertical resolution
// )
// test_card_inst (
// .i_x(x),
// .i_y(y),
// .o_red(red),
// .o_green(green),
// .o_blue(blue)
// );

// // Test Card: Gradient - ENABLE ONE TEST CARD INSTANCE ONLY
// localparam GRAD_STEP = 2; // step right shift: 480=2, 720=2, 1080=3
// test_card_gradient test_card_inst (
// .i_x(x[5:0]),
// .i_y(y[GRAD_STEP+7:GRAD_STEP]),
// .o_red(red),
// .o_green(green),
// .o_blue(blue)
// );

// VGA Output
// VGA Pmod is 12-bit so we take the upper nibble of each colour
assign VGA_HS = h_sync;
assign VGA_VS = v_sync;
assign VGA_R = {4{de & red}};
assign VGA_G = {4{de & green}};
assign VGA_B = {4{de & blue}};
assign VGA_R = de ? red[7:4] : 4'b0;
assign VGA_G = de ? green[7:4] : 4'b0;
assign VGA_B = de ? blue[7:4] : 4'b0;
endmodule
23 changes: 23 additions & 0 deletions hdl/demo/test_card_gradient.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
`timescale 1ns / 1ps
`default_nettype none

// Project F: Display Controller Test Card: Gradient
// (C)2019 Will Green, Open Source Hardware released under the MIT License
// Learn more at https://projectf.io

module test_card_gradient (
input wire [5:0] i_x,
input wire [7:0] i_y,
output wire [7:0] o_red,
output wire [7:0] o_green,
output wire [7:0] o_blue
);

localparam base_red = 8'h00;
localparam base_green = 8'h10;
localparam base_blue = 8'h4C;

assign o_red = base_red + i_y + i_x;
assign o_green = base_green + i_y;
assign o_blue = base_blue + i_y;
endmodule
37 changes: 17 additions & 20 deletions hdl/demo/test_card_simple.v
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,27 @@
// (C)2019 Will Green, Open Source Hardware released under the MIT License
// Learn more at https://projectf.io

module test_card_simple #(
H_RES=640,
V_RES=480
)
(
module test_card_simple #(H_RES=640) (
input wire [15:0] i_x,
input wire [15:0] i_y,
output wire o_red,
output wire o_green,
output wire o_blue
output wire [7:0] o_red,
output wire [7:0] o_green,
output wire [7:0] o_blue
);

localparam HR = H_RES; // horizontal resolution (pixels)
localparam VR = V_RES; // vertical resolution (lines)
localparam BW = 16; // border width
localparam HW = H_RES >> 3; // horizontal colour width = H_RES / 8

// Borders
wire top = (i_x >= 0) & (i_y >= 0) & (i_x < HR) & (i_y < BW);
wire btm = (i_x >= 0) & (i_y >= VR-BW) & (i_x < HR) & (i_y < VR);
wire lft = (i_x >= 0) & (i_y >= 0) & (i_x < BW) & (i_y < VR);
wire rgt = (i_x >= HR-BW) & (i_y >= 0) & (i_x < HR) & (i_y < VR);
// Bands
wire b0 = (i_x >= 0 ) & (i_x < HW );
wire b1 = (i_x >= HW ) & (i_x < HW * 2);
wire b2 = (i_x >= HW * 2) & (i_x < HW * 3);
wire b3 = (i_x >= HW * 3) & (i_x < HW * 4);
wire b4 = (i_x >= HW * 4) & (i_x < HW * 5);
wire b5 = (i_x >= HW * 5) & (i_x < HW * 6);
wire b6 = (i_x >= HW * 6) & (i_x < HW * 7);
wire b7 = (i_x >= HW * 7) & (i_x < HW * 8);

// Colour Output
assign o_red = lft | top;
assign o_green = btm | top;
assign o_blue = rgt | top;
assign o_red = {8{b0 | b1 | b5}} + {1'b0,{7{b6}}} + {2'b0,{6{b7}}};
assign o_green = {8{b1 | b2 | b3}} + {1'b0,{7{b6}}} + {2'b0,{6{b7}}};
assign o_blue = {8{b3 | b4 | b5}} + {1'b0,{7{b6}}} + {2'b0,{6{b7}}};
endmodule
19 changes: 9 additions & 10 deletions hdl/demo/test_card.v → hdl/demo/test_card_squares.v
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
`timescale 1ns / 1ps
`default_nettype none

// Project F: Display Controller Test Card
// Project F: Display Controller Test Card: Squares
// (C)2019 Will Green, Open Source Hardware released under the MIT License
// Learn more at https://projectf.io

module test_card #(
module test_card_squares #(
H_RES=640,
V_RES=480
)
(
) (
input wire [15:0] i_x,
input wire [15:0] i_y,
output wire o_red,
output wire o_green,
output wire o_blue
output wire [7:0] o_red,
output wire [7:0] o_green,
output wire [7:0] o_blue
);

localparam HR = H_RES; // horizontal resolution (pixels)
Expand Down Expand Up @@ -49,7 +48,7 @@ module test_card #(
wire lns_8 = (i_y >= SY) & (i_y <= SY + 2*SQ) & ((i_x == SX + 8*SQ + 3*LS) | (i_x == SX + 10*SQ - 3*LS));

// Colour Output
assign o_red = lft | top | lns_1 | lns_4 | lns_5 | lns_8 | sq_b | sq_e;
assign o_green = btm | top | lns_2 | lns_4 | lns_6 | lns_8 | sq_a | sq_d | sq_e;
assign o_blue = rgt | top | lns_3 | lns_4 | lns_7 | lns_8 | sq_c | sq_e;
assign o_red = {8{ lft | top | lns_1 | lns_4 | lns_5 | lns_8 | sq_b | sq_e }};
assign o_green = {8{ btm | top | lns_2 | lns_4 | lns_6 | lns_8 | sq_a | sq_d | sq_e }};
assign o_blue = {8{ rgt | top | lns_3 | lns_4 | lns_7 | lns_8 | sq_c | sq_e }};
endmodule
Loading