Skip to content

Commit 1cbde77

Browse files
authored
Xilinx support on master branch (#20)
xilinx oserdese2 + 4k30fps
1 parent 6502305 commit 1cbde77

File tree

3 files changed

+98
-83
lines changed

3 files changed

+98
-83
lines changed

README.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ Most free and open source HDMI source (computer/gaming console) implementations
2626
### Platform Support
2727

2828
- [x] Altera (tested on [MKR Vidor 4000](https://store.arduino.cc/usa/mkr-vidor-4000))
29-
- [x] Xilinx
30-
- Confirmed for [v1.1](https://github.com/hdl-util/hdmi/releases/tag/v1.1) by community
31-
- Master will be tested soon using [Spartan Edge Accelerator Board](https://www.seeedstudio.com/Spartan-Edge-Accelerator-Board-p-4261.html)
29+
- [x] Xilinx (tested on [Spartan Edge Accelerator Board](https://www.seeedstudio.com/Spartan-Edge-Accelerator-Board-p-4261.html))
3230
- [ ] Lattice (unknown)
3331

3432
### To-do List (upon request)
@@ -61,23 +59,24 @@ Most free and open source HDMI source (computer/gaming console) implementations
6159

6260
You'll need to set up a PLL for producing the two HDMI clocks. The pixel clock for each supported format is shown below:
6361

64-
|Video Resolution|Video ID Code(s)|Refresh Rate|Pixel Clock Frequency|
62+
|Video Resolution|Video ID Code(s)|Refresh Rate|Pixel Clock Frequency|[Progressive](https://en.wikipedia.org/wiki/Progressive_scan)/[Interlaced](https://en.wikipedia.org/wiki/Interlaced_video)|
6563
|---|---|---|---|
66-
|640x480|1|60Hz|25.2MHz|
67-
|640x480|1|59.94Hz|25.175MHz|
68-
|720x480|2, 3|60Hz|27.027MHz|
69-
|720x480|2, 3|59.94Hz|27MHz|
70-
|1280x720|4|60Hz|74.25MHz|
71-
|1280x720|4|59.94Hz|74.176MHz|
72-
|1920x1080|16|60Hz|148.5MHz|
73-
|1920x1080|16|59.94Hz|148.352MHz|
74-
|1920x1080|34|30Hz|74.25MHz|
75-
|1920x1080|34|29.97Hz|74.176MHz|
76-
|720x576|17, 18|50Hz|27MHz|
77-
|1280x720|19|50Hz|74.25MHz|
78-
|3840x2160|97, 107|60Hz|594MHz|
79-
80-
The second clock is a clock 5 times as fast as the pixel clock. Even if your FPGA only has a single PLL, the Altera MegaWizard (or the Xilinx equivalent) should still be able to produce both.
64+
|640x480|1|60Hz|25.2MHz|P|
65+
|640x480|1|59.94Hz|25.175MHz|P|
66+
|720x480|2, 3|60Hz|27.027MHz|P|
67+
|720x480|2, 3|59.94Hz|27MHz|P|
68+
|720x576|17, 18|50Hz|27MHz|P|
69+
|1280x720|4|60Hz|74.25MHz|P|
70+
|1280x720|4|59.94Hz|74.176MHz|P|
71+
|1280x720|19|50Hz|74.25MHz|P|
72+
|1920x1080|16|60Hz|148.5MHz|P|
73+
|1920x1080|16|59.94Hz|148.352MHz|P|
74+
|1920x1080|34|30Hz|74.25MHz|P|
75+
|1920x1080|34|29.97Hz|74.176MHz|P|
76+
|3840x2160 (not ready)|97, 107|60Hz|594MHz|P|
77+
|3840x2160|95, 105|30Hz|297MHz|P|
78+
79+
The second clock is a clock 5 times as fast as the pixel clock. Even if your FPGA only has a single PLL, the Altera MegaWizard (or the Xilinx equivalent) should still be able to produce both. See [hdl-util/hdmi-demo](https://github.com/hdl-util/hdmi-demo/) for example PLLs.
8180

8281
### L-PCM Audio Bitrate / Sampling Frequency
8382

src/hdmi.sv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ generate
126126
assign hsync = cx >= 440 && cx < 440 + 40;
127127
assign vsync = cy >= 5 && cy < 5 + 5;
128128
end
129-
97, 107:
129+
95, 105, 97, 107:
130130
begin
131131
assign frame_width = 4400;
132132
assign frame_height = 2250;
@@ -147,7 +147,7 @@ localparam real VIDEO_RATE = (VIDEO_ID_CODE == 1 ? 25.2E6
147147
: VIDEO_ID_CODE == 17 || VIDEO_ID_CODE == 18 ? 27E6
148148
: VIDEO_ID_CODE == 19 ? 74.25E6
149149
: VIDEO_ID_CODE == 34 ? 74.25E6
150-
: VIDEO_ID_CODE == 97 || VIDEO_ID_CODE == 107 ? 594E6
150+
: VIDEO_ID_CODE == 95 || VIDEO_ID_CODE == 105 || VIDEO_ID_CODE == 97 || VIDEO_ID_CODE == 107 ? 594E6
151151
: 0) * (VIDEO_REFRESH_RATE == 59.94 || VIDEO_REFRESH_RATE == 29.97 ? 1000.0/1001.0 : 1); // https://groups.google.com/forum/#!topic/sci.engr.advanced-tv/DQcGk5R_zsM
152152

153153
// Wrap-around pixel position counters indicating the pixel to be generated by the user in THIS clock and sent out in the NEXT clock.

src/serializer.sv

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,74 +14,90 @@ module serializer
1414
`ifndef VERILATOR
1515
`ifdef SYNTHESIS
1616
`ifndef ALTERA_RESERVED_QIS
17-
// Based on VHDL implementation by Furkan Cayci, 2010
17+
// https://www.xilinx.com/support/documentation/user_guides/ug471_7Series_SelectIO.pdf
18+
logic tmds_plus_clock [NUM_CHANNELS:0];
19+
assign tmds_plus_clock = '{tmds_clock, tmds[2], tmds[1], tmds[0]};
1820
logic [9:0] tmds_internal_plus_clock [NUM_CHANNELS:0];
19-
assign tmds_internal_plus_clock =tmds_internal_plus_clock '{10'b0000011111, tmds_internal[2], tmds_internal[1], tmds_internal[0]};
21+
assign tmds_internal_plus_clock = '{10'b0000011111, tmds_internal[2], tmds_internal[1], tmds_internal[0]};
2022
logic [1:0] cascade [NUM_CHANNELS:0];
2123
genvar i;
2224
generate
2325
for (i = 0; i <= NUM_CHANNELS; i++)
2426
begin: xilinx_serialize
25-
OSERDES2 #(.DATA_RATE_OQ("DDR"), .DATA_RATE_TQ("SDR"), .DATA_WIDTH(10), .SERDES_MODE("MASTER"), .TRISTATE_WIDTH(1))
26-
primary (
27-
.OQ(i == NUM_CHANNELS ? tmds_clock : tmds[i]),
28-
.OFB(),
29-
.TQ(),
30-
.TFB(),
31-
.SHIFTOUT1(),
32-
.SHIFTOUT2(),
33-
.TBYTEOUT(),
34-
.CLK(clk_pixel_x5),
35-
.CLKDIV(clk_pixel),
36-
.D1(tmds_internal_plus_clock[i][0]),
37-
.D2(tmds_internal_plus_clock[i][1]),
38-
.D3(tmds_internal_plus_clock[i][2]),
39-
.D4(tmds_internal_plus_clock[i][3]),
40-
.D5(tmds_internal_plus_clock[i][4]),
41-
.D6(tmds_internal_plus_clock[i][5]),
42-
.D7(tmds_internal_plus_clock[i][6]),
43-
.D8(tmds_internal_plus_clock[i][7]),
44-
.TCE(1'b0),
45-
.OCE(1'b1),
46-
.TBYTEIN(1'b0),
47-
.RST(),
48-
.SHIFTIN1(cascade[i][0]),
49-
.SHIFTIN2(cascade[i][1]),
50-
.T1(1'b0),
51-
.T2(1'b0),
52-
.T3(1'b0),
53-
.T4(1'b0)
54-
);
55-
OSERDES2 #(.DATA_RATE_OQ("DDR"), .DATA_RATE_TQ("SDR"), .DATA_WIDTH(10), .SERDES_MODE("SLAVE"), .TRISTATE_WIDTH(1))
56-
secondary (
57-
.OQ(),
58-
.OFB(),
59-
.TQ(),
60-
.TFB(),
61-
.SHIFTOUT1(cascade[i][0]),
62-
.SHIFTOUT2(cascade[i][1]),
63-
.TBYTEOUT(),
64-
.CLK(clk_pixel_x5),
65-
.CLKDIV(clk_pixel),
66-
.D1(1'b0),
67-
.D2(1'b0),
68-
.D3(tmds_internal_plus_clock[i][8]),
69-
.D4(tmds_internal_plus_clock[i][9]),
70-
.D5(1'b0),
71-
.D6(1'b0),
72-
.D7(1'b0),
73-
.D8(1'b0),
74-
.TCE(1'b0),
75-
.OCE(1'b1),
76-
.TBYTEIN(1'b0),
77-
.RST(),
78-
.SHIFTIN1(1'b0),
79-
.SHIFTIN2(1'b0),
80-
.T1(1'b0),
81-
.T2(1'b0),
82-
.T3(1'b0),
83-
.T4(1'b0)
84-
);
27+
OSERDESE2 #(
28+
.DATA_RATE_OQ("DDR"),
29+
.DATA_RATE_TQ("SDR"),
30+
.DATA_WIDTH(10),
31+
.SERDES_MODE("MASTER"),
32+
.TRISTATE_WIDTH(1),
33+
.TBYTE_CTL("FALSE"),
34+
.TBYTE_SRC("FALSE")
35+
) primary (
36+
.OQ(tmds_plus_clock[i]),
37+
.OFB(),
38+
.TQ(),
39+
.TFB(),
40+
.SHIFTOUT1(),
41+
.SHIFTOUT2(),
42+
.TBYTEOUT(),
43+
.CLK(clk_pixel_x5),
44+
.CLKDIV(clk_pixel),
45+
.D1(tmds_internal_plus_clock[i][0]),
46+
.D2(tmds_internal_plus_clock[i][1]),
47+
.D3(tmds_internal_plus_clock[i][2]),
48+
.D4(tmds_internal_plus_clock[i][3]),
49+
.D5(tmds_internal_plus_clock[i][4]),
50+
.D6(tmds_internal_plus_clock[i][5]),
51+
.D7(tmds_internal_plus_clock[i][6]),
52+
.D8(tmds_internal_plus_clock[i][7]),
53+
.TCE(1'b0),
54+
.OCE(1'b1),
55+
.TBYTEIN(1'b0),
56+
.RST(1'b0),
57+
.SHIFTIN1(cascade[i][0]),
58+
.SHIFTIN2(cascade[i][1]),
59+
.T1(1'b0),
60+
.T2(1'b0),
61+
.T3(1'b0),
62+
.T4(1'b0)
63+
);
64+
OSERDESE2 #(
65+
.DATA_RATE_OQ("DDR"),
66+
.DATA_RATE_TQ("SDR"),
67+
.DATA_WIDTH(10),
68+
.SERDES_MODE("SLAVE"),
69+
.TRISTATE_WIDTH(1),
70+
.TBYTE_CTL("FALSE"),
71+
.TBYTE_SRC("FALSE")
72+
) secondary (
73+
.OQ(),
74+
.OFB(),
75+
.TQ(),
76+
.TFB(),
77+
.SHIFTOUT1(cascade[i][0]),
78+
.SHIFTOUT2(cascade[i][1]),
79+
.TBYTEOUT(),
80+
.CLK(clk_pixel_x5),
81+
.CLKDIV(clk_pixel),
82+
.D1(1'b0),
83+
.D2(1'b0),
84+
.D3(tmds_internal_plus_clock[i][8]),
85+
.D4(tmds_internal_plus_clock[i][9]),
86+
.D5(1'b0),
87+
.D6(1'b0),
88+
.D7(1'b0),
89+
.D8(1'b0),
90+
.TCE(1'b0),
91+
.OCE(1'b1),
92+
.TBYTEIN(1'b0),
93+
.RST(1'b0),
94+
.SHIFTIN1(1'b0),
95+
.SHIFTIN2(1'b0),
96+
.T1(1'b0),
97+
.T2(1'b0),
98+
.T3(1'b0),
99+
.T4(1'b0)
100+
);
85101
end
86102
endgenerate
87103
`endif

0 commit comments

Comments
 (0)