charcole / NeoGeoHDMI

Verilog project that takes the digital video and audio from a Neo Geo MVS before going through the DACs and outputs the signals over HDMI
Other
105 stars 21 forks source link

Love your work, just have a question... #4

Open rogloh opened 6 years ago

rogloh commented 6 years ago

This is a really great project charcole!

I have been hugely impressed by your entire project and digging into your code hoping I can get some ideas for a similar FPGA project. Eventually I am trying to get something like this going on my own setup which is Lattice ECP5 based and where I might one day hope to boost it to 75MHz for 720p resolutions and use 44.1kHz sampled audio. However in studying your particular implementation I can't quite understand one aspect related to the audio and was wondering if you might perhaps be able to shed some light....?

I see in your case with 27MHz pixel clock and 32kHz audio you are generating new audio samples every 3375/4 pixel clocks and you are cycling through updating 4 different sub packets in the same audio packet. But the strange thing that I don't follow is that you are ORing the last value of audioPacketHeader to the new value. Won't this then (eventually after 4 samples have been computed) end up with all logic ones in the audioPacketHeader flags indicating that all four sub packets contain audio and also that all four sub packets channel status are starting their 192 bit sequence? This is the line I mean...

audioPacketHeader<=audioPacketHeader|24'h000002|((channelStatusIdx==0?24'h100100:24'h000100)<<samplesHead);

It always bitwise ORs the prior value so it can't clear the set bits but only add to them as they shift up by 0-3 bits each time this is computed and latched.

To me this seems that for every HDMI audio sample packet you are sending, the packet header would indicate that it contains 4 valid audio samples, thus increasing the output rate by a factor of approximately 4. Does it always work out okay or does it generate some duplicate or outdated samples I wonder? Perhaps I've misunderstood how HDMI audio works, or perhaps the sink is automatically throwing away lots of these extra samples by using the CTS/N parameters to only sample whatever it currently has received, at a slower and correct rate?

Given that you are outputting 32kHz audio sample every ~843 pixels and the scan line is effectively 858 pixels wide between audio packets going out I'd have thought it should mainly need to just send either 1 and occasionally 2 valid audio samples per audio packet, but it looks like it always sends 4 samples based on the state of the header bits. Not sure why there, and if that was intended as designed or potentially some (perhaps minor) issue that was not audibly identified. Something just seems a bit weird there...

Thanks for anything you may add to enlighten me. Cheers, rogloh.

rogloh commented 6 years ago

Ok, so in digging into the code a bit more I see you are resetting samplesHead to zero later every time you actually have to send out the audio packet, so it won't actually ever need to reach four samples. I also notice that the audio packet header is cleared after it is sent out. That explains why it would be working.

I just hadn't noticed that part further down in the code where the audioPacketHeader register is cleared because it was part of another task and getting passed as another name so I got a little lost in the logic there unfortunately when I was searching around for it.

All good now - I've figured it out and it makes a lot more sense now, rogloh.

charcole commented 6 years ago

Glad you got it sorted. I took a look and I think your explanation is correct. The audioPacketHeader gets cleared when it shifts out. Best of luck with your modifications. Let me know what you manage to build with it :)

rogloh commented 6 years ago

Thanks Charlie. I’ve been playing a little more with it today and had a partial success with getting parts of it working on my Lattice ECP5 FPGA and outputting a video signal (as DVI). There are still problems however unfortunately. Some of it is likely my own setup limitations.

Basically the Synopsis Synplify Pro synthesizer in the Lattice tools does not like a mix of blocking/non-blocking assignment statements both in the Verilog task code for computing the ECCs and also in the SendPacket task and would not compile those. So I have been trying to modify things slightly to allow it to compile but I fear these slight differences may potentially have broken something. For some reason the tools complain the assignment to your inout “code” variable in the ECC tasks is not allowed (“Can’t mix blocking and non-blocking assignments to a variable”). So as work around I now use a separate input and a separate output register for that and pass in the same source register for both input and output parameter in the task call. It also didn’t like the non-blocking assignments in the SendPacket task to the pckData0..3 variables which was weird. After I changed those too by duplicating all the SendPacket task code into the main generation sequence instead, it seems to let that compile, but I am not sure now if that is doing the right thing and if the output packet data is still 100% correct or possibly offset by a clock now if it is now using non-blocking assignments everwhere. The weird thing is that the only actual blocking assignments I ever saw were the three dataChannel0 bits in the SendPacket task. Wasn’t 100% sure if you needed it to be like that or not.

Anyway, I have found when I setup your code to bypass the TERC4 encoding stage entirely and only output the sync control and video using the TMDS encoders, I do get a 720x480 test pattern with the rest of your video logic so at least I know my PLL setup and differential HDMI bus outputs are working okay along with most of the remaining display logic path.

Right now I only have 3 DVI monitors and one HDMI TV and one HDMI projector to try out, so I don’t have a lot to work with yet.

The DVI monitors and projector show the simplified DVI output display variant fine, but neither show the full HDMI variant if the TERC4 path is enabled. I didn't really expect the HDMI to work on an older DVI monitor, but I was hoping the projector input would at least work. Again I found it only works with DVI and reports its input signal is 720x480 at 60Hz (actually it said 59.90) so that looks right. On the other hand, my HDMI TV is not playing nice and does not show anything for DVI or HDMI so there might be input format/resolution limitations there, not sure. I’ve been playing about with various settings on it to no avail so far.

Still plugging away…really hope to get it to sync with some functional TERC4 encoding and get audio working. In the past I’ve had that FPGA4FUN DVI example code working before at VGA resolution (including on that HDMI TV) but never true HDMI encoding as yet.

Cheers, Roger

ps. Also I don't think it is an FPGA timing limitation problem as the place and route timing analysis tool reports the FPGA can hit 375MHz on the TMDS clock and 106 MHz for the pixel clock domain. It's still a pretty lightly loaded FPGA (4% slice usage).

rogloh commented 6 years ago

Very happy to say after a couple more hours of tweaking I've got a variant of your code running on my board and it works! I'm getting a stable 720x480p60 picture + 32kHz audio working on my TV over HDMI. I am just running a simple 16 bit sawtooth counter test pattern using the pixel clock yielding ~ 411Hz tone. In the end it also does work on my DVI monitor too which is great.

All I had to do to fix things was expand out all the task code and put it back into your main sequential loop that is currently determining the data outputs and drive it all synchronously with no blocking statements anywhere. The Synplify synthesis tool is happy now and it runs well!

This is so cool and I'm really happy to see it going on this board, thanks so much for your work! Will plan to try a higher resolution and 44.1kHz audio soon.

rogloh commented 6 years ago

So with more work I was able to get 720p going using a 75 MHz pixel clock, but still no luck with higher quality audio other than your original 32kHz sample rate using 27MHz dot clock. Not sure why. The E-EDID field from my plasma TV reports it supports 32, 44.1 and 48kHz rates. I have adjusted the channel status info bits 24-27 info accordingly to identify the higher sample rate and the N/CTS fields as well to suitable values for the higher sample rate, but it only works when it is configured for 32kHz and remains silent otherwise. It also does not work at 32kHz with a 75MHz pixel clock either which seems strange. Can't quite figure it out...

migry commented 3 years ago

Hi @rogloh . In simulation I see the same thing, that is audioPacketheader is always 0x100302. Perhaps this is only a problem in simulation?

I have to say that I do not understand "tasks" (i.e. SendPacket) using inout. In hardware the circuit behaves as expected as far as I can tell. I was hoping to get a clearer picture of how this important value changed from audio packet to packet.

I haven't dug deeper to see if the TERC packets are sensible or not.

rogloh commented 3 years ago

Hello @migry, I’ve not looked at this in a long time now. I found that audio worked at one 32kHz sample rate only on my HDMI TV and I was hoping to get other sample rates running. I also found I had more luck later with a cheap PC monitor that accepted HDMI when I created another implementation. That device was more forgiving and I heard a test tone. Since then I’ve moved onto other things, but one day I might get back into this again…

On 23 Apr 2021, at 12:33 am, Gary Morton @.***> wrote:

view it on GitHub https://github.com/charcole/NeoGeoHDMI/issues/4#issuecomment-824895880

mopplayer commented 2 years ago

Hi,

l think you are successful to set up and show.

I use the test pattern to test, there are always two block shown.

Is my screen not supported? or something wrong? (I can not set up 720X480, just use 640X480)

Did you have some ideas?

https://imgur.com/ArIkfPk

charcole commented 2 years ago

Yeah, I would think you’re seeing the audio packets. DVI is a subset of HDMI. To add audio for HDMI they encoded the data in the sync signal. If it doesn’t like it, monitors will sometimes show you that part of the sync as more line data. In fact it was quite useful for debugging as when the audio wasn’t quite right yet my monitor would do the same and I could see my audio packets at the side of the screen.

Charlie

On 3 Sep 2022, at 03:17, mopplayer @.***> wrote:

 Hi,

l think you are successful to set up and show.

I use the test pattern to test, there are always two block shown.

Is my screen not supported? or something wrong? (I can not set up 720X480, just use 640X480)

Did you have some ideas?

https://imgur.com/ArIkfPk

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.

mopplayer commented 2 years ago

Hi @charcole,

If so, how to debug this?

I try to change the preamble and guardband.

I get something changed (no colored pattern) if videodata starts with a data guardband.

But the preamble (data <-> video exchange) did not change anything.

This is just a test for my monitor. (The first block of picture is "video guardband", and the second white block is audio block?)

I also have checked the packet definition of HDMI and CEA861-D.

CT[3:0] should be 0, but the result is the same.

I could not get rid of the white block (wrong audio block?)

Could you let me know how to get started?

So If I change with your monitor (i.e. GW2455H), will I get the same result?

Thank you very much.

charcole commented 2 years ago

I might not be too much help as this was all a long time ago.

If you want it to work over DVI then I think you’ll have to remove the audio packets from the sync. So you instead always go through the “Back to normal DVI” branch. Which you might be able to do by settings DATA_PREABLE, DATA_GUARDBAND and DATA_SIZE to 0. It looks like that’d get you back to a normal DVI signal (from what I remember anyway).

Charlie

On 3 Sep 2022, at 17:17, mopplayer @.***> wrote:

 Hi @charcole,

If so, how to debug this?

I try to change the preamble and guardband.

I get something changed (no colored pattern) if videodata starts with a data guardband.

But the preamble (data <-> video exchange) did not change anything.

This is just a test for my monitor.

I also have checked the packet definition of HDMI and CEA861-D.

CT[3:0] should be 0, but the result is the same.

I could not get rid of the white block (wrong audio block?)

Could you let me know how to get started?

So If I change with your monitor (i.e. GW2455H), will I get the same result?

Thank you very much.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.

mopplayer commented 2 years ago

Hi @charcole,

Yes, I know this way.

But I want to work with audio.

Could you let me know how to debug this?

Is there a wrong preamble or guard band or audio packet itself?

Thank you very much.