hdl-util / hdmi Goto Github PK
View Code? Open in Web Editor NEWSend video/audio over HDMI on an FPGA
Home Page: https://purisa.me/blog/hdmi-released/
License: Other
Send video/audio over HDMI on an FPGA
Home Page: https://purisa.me/blog/hdmi-released/
License: Other
Hi, i tested project with some older DVI monitors and seems there is a small incompatibility. I tried VIDEO_ID_CODE=1 and DVI_OUTPUT =1. E.g LG M1921TA monitor doesn't display an image. Original Mike Field's project works well on this monitor.
What exactly should the Pin assignment be in a top level entity as such since I can can see HDMI port has a lot more ports. Thanks
Not apply
When using a resolution of 720p and a sampling rate of 44.1kHz, the current calculation formula generates an excessively large value.
The diff with the correct calculation formula is as follows:
--- a/src/hdmi/audio_clock_regeneration_packet.sv
+++ b/src/hdmi/audio_clock_regeneration_packet.sv
@@ -16,7 +16,7 @@ module audio_clock_regeneration_packet
);
// See Section 7.2.3, values derived from "Other" row in Tables 7-1, 7-2, 7-3.
-localparam bit [19:0] N = AUDIO_RATE % 125 == 0 ? 20'(16 * AUDIO_RATE / 125) : AUDIO_RATE % 225 == 0 ? 20'(196 * AUDIO_RATE / 225) : 20'(AUDIO_RATE * 16 / 125);
+localparam bit [19:0] N = AUDIO_RATE % 125 == 0 ? 20'(16 * AUDIO_RATE / 125) : AUDIO_RATE % 225 == 0 ? 20'(32 * AUDIO_RATE / 225) : 20'(AUDIO_RATE * 16 / 125);
localparam int CLK_AUDIO_COUNTER_WIDTH = $clog2(N / 128);
localparam bit [CLK_AUDIO_COUNTER_WIDTH-1:0] CLK_AUDIO_COUNTER_END = CLK_AUDIO_COUNTER_WIDTH'(N / 128 - 1);
The modified calculation formula will correctly calculate the value of N, ensuring it falls within the recommended range.
Hi Sameer, thanks so much for this amazing project. I've been porting bits of it into someone else's input lag tester project which I'm currently modifying to output proper HDMI (instead of DVI). I'm really just after the AVI InfoFrame functionality so I can force the HDMI sink I want to test (some FPV goggles) into RGB mode since it unfortunately defaults to expect the YCbCr video format. I've made good progress but I've noticed a discrepancy in the code which doesn't seem to match the HDMI Spec when it comes to the timing for the preamble:
Section 5.2.5.3 - Island Placement and Duration says:
All TMDS Control Periods shall be at least tS,min (12) characters (pixels) long.
Since the preamble is sent using a control period, it should always be preceded by at least a 4 pixel control period as show in the spec's timing diagram:
However the code seems to assume that data island preamble starts immediately after the video data period:
Line 293 in b5bc3d7
Instead, souldn't this be:
data_island_preamble <= num_packets_alongside > 0 && cx >= screen_width + 4 && cx < screen_width + 12;
This of course would have flow effects for the calculations of guard period and data island period.
Anyhow, thanks again for all your hard work and apologies if I'm completely misinterpreting the spec. :)
Hi, very nice project. Clean sources. Thanks a lot. Please, could you and info about pixel and tmds frequency per video modes?
Greetings, thanks for the great project.
I am porting the project onto an ebaz4205 ZYNQ 7010 board and nearly everything is now working, however there is a problem with the sawtooth sound module which I do not understand.
If I remove the instance of the sawtooth module and replaced it with inline equivalent code in the top module then everything works and sound is heard, when the sawtooth module is used there is silence.
My system is Vivado 2020.2, a bit more recent than the other Xilinx project which is perhaps 2019. I have successfully built 640x480 and 720p versions. These both show video and both suffer the same audio problem.
Working code from top with sawtooth placed inline. The sawtooth module is a direct copy of your own version in Github.
localparam int NUM_PCM_STEPS = (AUDIO_BIT_WIDTH + 1)'(2)**(AUDIO_BIT_WIDTH + 1)'(AUDIO_BIT_WIDTH) - 1;
localparam real FREQUENCY_RATIO = real'(WAVE_RATE) / real'(AUDIO_RATE);
localparam bit [AUDIO_BIT_WIDTH-1:0] INCREMENT = AUDIO_BIT_WIDTH'(NUM_PCM_STEPS * FREQUENCY_RATIO);
always @(posedge clk_audio)
audio_sample_word <= audio_sample_word + INCREMENT;
There are some issues with picture stability when running at the higher resolution but the problem exists at 640x480 too where the stability is not a problem. The clock frequencies are as close as I can get them sing a 33.333 MHz input to the Zynq clock generator. I used the clock wizard to derive the factors.
Any ideas how to debug this problem gratefully received. I have also made a rom lookup sinewave generator based on the sawtooth module layout, this too only works when used inline. The current sources are in my Github fork of the demo repo.
Kind regards, David.
I'm not sure about other synthesizers but Quartus doesn't like 0 width in these lines:
Lines 100 to 101 in 7ef7129
this
24'(audio_sample_word_transfer_mux[0])<<(24-AUDIO_BIT_WIDTH)
works correct.
Adding the tmds sync chain in f182e6e broke tests. The code still works fine, but the end-to-end testbench with a faked HDMI sink needs to watch ONLY tmds_clk
and tmds_data
. It can't rely on any clocks created by the HDMI source, and needs to be fully black-box now, since the sync chain can't be easily compensated for.
At serializer.v line 275, i found that signals tmds
and tmds_clock
are driven by mutiple signals. It made code unsynthesised and wrong simulation.
It would be helpful if you post your algorithm about this seder
Hi Sameer,
I have a problem with audio output. I would like to use 16 bits resolution, but it sounds with very low volume in compare 24 bit. I uses same data (i suppose proper) in follow examples:
16-bits:
hdmi #(.VIDEO_ID_CODE(17), .VIDEO_REFRESH_RATE(50), .AUDIO_RATE(48000), .AUDIO_BIT_WIDTH(16)) hdmi(.clk_pixel_x10(clk_tmds), .clk_pixel(clk_pixel), .clk_audio(audio_clk), .rgb(rgb), .audio_sample_word('{{audio_l}, {audio_r}}), .tmds_p(data_p), .tmds_clock_p(clk_p), .tmds_n(data_n), .tmds_clock_n(clk_n), .cx(cx), .cy(cy));
24-bits:
hdmi #(.VIDEO_ID_CODE(17), .VIDEO_REFRESH_RATE(50), .AUDIO_RATE(48000), .AUDIO_BIT_WIDTH(24)) hdmi(.clk_pixel_x10(clk_tmds), .clk_pixel(clk_pixel), .clk_audio(audio_clk), .rgb(rgb), .audio_sample_word('{{audio_l,8'b0}, {audio_r,8'b0}}), .tmds_p(data_p), .tmds_clock_p(clk_p), .tmds_n(data_n), .tmds_clock_n(clk_n), .cx(cx), .cy(cy));
24bits sounds good, but 16bit not. Thanks for help.
Disclaimer: I'm a noob when it comes to FPGAs. I've been trying to use your project on a Tang Nano 9K. Using their GOWIN FPGA Designer (1.9.8.05), I get an error in serializer.sv:
Net 'tmds[2]' is constantly driven from multiple places("src\serializer.sv":230)
Found another driver
here("src\serializer.sv":232)`
The project is configured to use System Verilog 2017.
TIA.
from any AC coupled signal to HDMI: (LVDS or GTP,GTX,etc... transceiver)
TI SN65DP159
NXP PTN336x PTN3300
Hello Sameer! Great project.
I would like to propose adding to the project an option for working not with LVDS outputs, but with regular outputs in DDR mode. I came across two different FPGA boards with the HDMI connector connected to the wrong differential pair outputs. Because of this, ALTLVDS_TX cannot be used.
I was able to transfer serializer.sv to altddio_out. The work has been tested on Cyclone 10LP and MAX10.
I think this approach can also be used with the Lattice FPGA.
But the module requires output of all eight TMDS signals, and not four as now.
Hi,
The SPD Infoframe checksum is missing the 25th byte (packet_bytes[25]) thus checksum is incorrect if SOURCE_DEVICE_INFORMATION is not 0.
Istvan
Hi,
Would it be possible to rework a version of the HDMI video transmitter to accept a LCD bus compatible input?
That would be and input of RGB[D:0] (for bit depth D), hsync, vsync, clk, and de (data enable).
I have an application where I would like to be able to drive the transmission externally with the signals above, however, it appears that there is additional logic which relies on the frame size.
Thanks.
I'm seeing issues with HDMI output not being compatible with capture devices. Tested with Elgato Cam Link 4K as well as a Blackmagic capture device). Using the Tang Nano 20K. If I use the default HDMI firmware for the Tang, video is captured correctly. Any idea why this wouldn't work? The Elgato software claims that it is trying to put out an incompatible resolution of 720x481 (not 480).
Hi, @sameer I have Spartan Edge Accelerator, and have a project in progress that would be able to use it (a high quality, live stream showcasing free discussions between senior hardware engineers discussing tips/procedures for EE/RF/Aerospace) where I could possibly output some translated waveforms - and I have a complex professional/prosumer OBS Studio setup. I sent you Linked In invite and would like to know if there is a writeup on the process by which you adapted Spartan Edge Accelerator with HDMI interface where I can add in my contributions,
Ref: Hackster.io article
Hi,
Thanks a lot for new version and changes.
I tried last version and there is small problem to synthesis it.
First, Vivado doesn't support parameter string, bud it easy to resolve it by deleting "string" words.
Second, there is general problem if use 16bits audio bit width instead of 24bit there is error:
[Synth 8-659] type mismatch in assignment: bit [15:0]A[1:0] vs. bit [23:0]B[1:0] ["C:/temp/DV/DV.srcs/sources_1/new/packet_picker.sv":78]
with 24bits is synthesizable.
Thanks
Hi !
Filing this to report that I've been able to get this to work on the ULX3S board (based on Lattice ECP5, 12K gates).
Due to compile issues with the open source toolchain of the ULX3S, I ended up using Lattice Diamond...
Tested default settings - 640x480, and 48k stereo audio (externally driven). Had to make some changes to suit the ECP5 (in the serializer module). Also some changes for compilation.
Will be updating with more results & changes soon.
Thanks
-- Shree
I'm trying to use this code in a Spartan 6 board, however ISE14.7 does not support System Verilog.
Vivado supports SV but not Spartan 6 family :-(
I tried to translate this code to Verilog but packed assignaments like this get me confussed and don't know how to do it.
Any clue to translate it? Is there any tool to convert it to Verilog? Thanks.
logic [23:0] audio_sample_word_packet [3:0] [1:0];...
logic [23:0] audio_sample_word_buffer [1:0] [3:0] [1:0];...
audio_sample_word_packet <= audio_sample_word_buffer[!sample_buffer_current];
Hello,
I noticed you listed the pixel clocks for 4k60, but I was curious if you know of any boards capable of generating that signal. I'm looking at an Artix-7 and using the GTP engines. I've got a bit of a side project trying to build my own graphics card for retro computers (ISA bus and all), and I wanted to possibly product a 4k60 output on the board. (It would be integer scaling of whatever mode the old computer set, also a higher resolution helps emulate non-square pixels).
It would also be neat to do soundblaster emulation and pass it out over HDMI, but I'm looking to stay within the DVI spec because I don't think I'd have enough interest to warrant licensing HDMI.
Hi, this is only a note. I use this code and make long time test and have to say works very well. Thanks for you work Sameer. I am looking forward for Audio features. How is going with this, please?
Hi, there is a small typing error on line 163:
162 data_island_data[3] <= cx != screen_start_x;
163 data_island[2] <= data[0];
164 data_island_data[1:0] <= {vsync, hsync};
there should be : data_island_data[2]
If you speak another language, I would appreciate your help in translating the README.md
.
For tables, checklists, or other data that might change, please indicate that that information is in the main README. Otherwise every change to the main README will need to be replicated to the other READMEs.
^ I've tried to do this a bit in the French README. The only thing you need to replicate when adding a new language is the line that lists all the languages.
Thank you!
Hello,
Version I use:
Vivado v2022.2 (64-bit)
**** SW Build 3671981 on Fri Oct 14 04:59:54 MDT 2022
**** IP Build 3669848 on Fri Oct 14 08:30:02 MDT 2022
I try to use your project on the zybo-z7-20 board and I get the following error using hdlmake:
INFO: [Common 17-349] Got license for feature 'Synthesis' and/or device 'xc7z020'
INFO: [Device 21-403] Loading part xc7z020clg400-1
INFO: [Synth 8-7079] Multithreading enabled for synth_design using a maximum of 4 processes.
INFO: [Synth 8-7078] Launching helper process for spawning children vivado processes
INFO: [Synth 8-7075] Helper process launched with PID 162190
INFO: [Synth 8-11241] undeclared symbol 'REGCCE', assumed default net type 'wire' [/sdd_storage/xilinx/Vivado/2022.2/data/verilog/src/unimacro/BRAM_SINGLE_MACRO.v:2170]
WARNING: [Synth 8-11014] non-net output port 'tmds' cannot be initialized at declaration in SystemVerilog mode [/hdmi-demo/ip_cores/hdmi/src/tmds_channel.sv:16]
WARNING: [Synth 8-9661] initial value of parameter 'VIDEO_RATE' is omitted [/hdmi-demo/ip_cores/hdmi/src/serializer.sv:4]
WARNING: [Synth 8-11014] non-net output port 'level' cannot be initialized at declaration in SystemVerilog mode [/hdmi-demo/ip_cores/sound/src/sawtooth.sv:9]
ERROR: [Synth 8-10863] illegal size casting of a 'real' expression [/hdmi-demo/ip_cores/sound/src/sawtooth.sv:14]
INFO: [Synth 8-10285] module 'sawtooth' is ignored due to previous errors [/hdmi-demo/ip_cores/sound/src/sawtooth.sv:18]
INFO: [Synth 8-9084] Verilog file '/hdmi-demo/ip_cores/sound/src/sawtooth.sv' ignored due to errors
Failed to read verilog '/hdmi-demo/ip_cores/sound/src/sawtooth.sv'
I think the problem is this one: ERROR: [Synth 8-10863] illegal size casting of a 'real' expression [/hdmi-demo/ip_cores/sound/src/sawtooth.sv:14]
Hi, I have something strange in audio signal. It looks like some bits are not reflected or are mixed up. I tried sawtooth example with some changes. Code is here:
logic signed [15:0] audio_sample_word = 16'sd0;
logic signed [15:0] audio_sample_word_minus = 16'sd0;
always @(posedge audio_clk) // Sawtooth wave
begin
audio_sample_word <= audio_sample_word + 16'sd1;
audio_sample_word_minus <= audio_sample_word_minus - 16'sd128;
end
..
hdmi #(.VIDEO_ID_CODE(17), .VIDEO_REFRESH_RATE(50), .AUDIO_RATE(48000), .AUDIO_BIT_WIDTH(16)) hdmi(
...
.clk_pixel(clk_pixel),
.clk_audio(audio_clk),
.rgb(rgb),
.audio_sample_word({audio_sample_word,audio_sample_word_minus}),
This exaple is for 16bits audio. I have found when want use 24bits the highest two bits are not reflected and have to use this:
.audio_sample_word({{2'b0,audio_r,6'b0},{2'b0,audio_l,6'b0}}),
Could you help me with this issue, please.
Hi Sameer, I only propose to replace parameters in hdmi.sv module by inputs. It will be more handy for implementation. These values is useful to change as a option in project mainly:
VIDEO_ID_CODE
DVI_OUTPUT
VIDEO_REFRESH_RATE
Thanks a lot.
Hi @sameer,
I have studied several repos of related projects.
https://github.com/charcole/NeoGeoHDMI/blob/master/HDMIDirect.v
My monitor was CHIMEI 24SH-L, also tested with BENQ GW2480, but no luck (no signal).
https://imgur.com/ArIkfPk
The first block of the picture is "video guardband", and is the second white block "wrong audio block"?
After some reworking, I use this repo and others, to simplify the problem.
https://imgur.com/fWueDsr
Now I can get the "wrong audio block" disappeared, but no audio comes out.
Scenario (720x480, 27M pixel clock):
If the 12 pixels prior to the transition contain any pixels not encoded with Control Period Coding then FAIL, (Control Period too short) (HDMI 1.4b CTS page 148)
If TMDS channel 0 for either of these pixels does not equal one of the 4 permitted Data Island Guard Band characters (0xC, 0xD, 0xE, 0xF) [HDMI: 5.2.3.3] then FAIL (HDMI 1.4b CTS page 148)
If first character following the Leading Guard Band has TERC4 ch. 0, bit 3 == 1 then FAIL (HDMI 1.4b CTS page 148)
If any other character prior to Trailing Guard Band has TERC4 ch. 0, bit 3 != 1 then FAIL (HDMI 1.4b CTS page 148)
Length of Data Island is equal to number of pixels following Leading Guard Band and prior to Trailing Guard Band. Number of packets = Length of Data Island / 32. (HDMI 1.4b CTS page 148)
If any two video fields occur with no AVI InfoFrame then FAIL (HDMI 1.4b CTS page 168)
If Audio InfoFrame Packet is detected at least once per two video fields then continue else then FAIL (HDMI 1.4b CTS page 177)
If any character following the Leading Guard Band but preceding the Trailing Guard Band is not a legal TERC4 code then FAIL (HDMI 1.4b CTS page 148)
CounterX(cx) >= 720 + 4 + 8 + 2 + 32 + 2 && CounterX(cx) < 858 - 8 - 2
---> Do nothing, CTL[3:0] = 4'b0000
CounterX(cx) >= 858 - 8 - 2 && CounterX(cx) < 858 - 2
---> Video Preamble, CTL[3:0] = 4'b0001
CounterX(cx) >= 858 - 2 && CounterX(cx) < 858
---> Video Guardband, Channel 0 = 10'b1011001100, Channel 1 = 10'b0100110011, Channel 2 = 10'b1011001100
CounterX(cx) >= 0 && CounterX(cx) < 720
---> Video Data
If any character following Video Guard Band up to transition is not a correctly encoded Video Data code then FAIL (HDMI 1.4b CTS page 149)
Did I miss something?
Could you let me know how to get started?
Thank you very much.
The project does not declare an open source (or any other) license. This makes it impossible to know whether I can use it inside my own project.
Ideally, the project's root should have a license file, and each file in the project should have a short header declaring that this file is governed by that license. This would avoid confusion about whether the project can be used.
Adding a license can only be done by the actual copyright holder.
Hello,
In file test\top_tb\top_tb.sv there is casting that is illegal according to LRM (size casting is legal only with integer types, not unpacked arrays - IEEE 1800-2017, p. 133):
logic [7:0] packet_bytes [0:27];
...
assert(112'(packet_bytes[14:27]) == 0) else $fatal("Reserved bytes not 0");
It would be good to change that.
Regards,
Piotr
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.