Revision 951
Added by markw over 6 years ago
| hdmidataencoder.v | ||
|---|---|---|
|
//---------------------------------------------------------------------------
|
||
|
//-- (c) 2016 Alexey Spirkov
|
||
|
//-- I am happy for anyone to use this for non-commercial use.
|
||
|
//-- If my verilog/vhdl/c files are used commercially or otherwise sold,
|
||
| ... | ... | |
|
#(parameter FREQ=27000000, FS=48000, CTS=27000, N=6144)
|
||
|
(
|
||
|
input i_pixclk,
|
||
|
input i_reset,
|
||
|
input i_hSync,
|
||
|
input i_vSync,
|
||
|
input i_blank,
|
||
| ... | ... | |
|
reg [10:0] audioAvgCnt;
|
||
|
reg [15:0] counterX;
|
||
|
reg firstHSyncChange;
|
||
|
reg firstVSyncChange;
|
||
|
reg oddLine;
|
||
|
reg prevHSync;
|
||
|
reg prevVSync;
|
||
|
reg prevBlank;
|
||
|
reg allowGeneration;
|
||
|
|
||
|
reg packet_sent;
|
||
|
wire packet_needed;
|
||
|
reg start_of_frame;
|
||
|
reg audio_regen_needed;
|
||
|
reg packet_ready;
|
||
|
wire audio_regen;
|
||
|
wire audio_info;
|
||
|
wire video_info;
|
||
|
|
||
|
initial
|
||
|
begin
|
||
|
audioPacketHeader=0;
|
||
| ... | ... | |
|
oddLine=0;
|
||
|
counterX=0;
|
||
|
prevHSync = 0;
|
||
|
prevVSync = 0;
|
||
|
prevBlank = 0;
|
||
|
firstHSyncChange = 0;
|
||
|
firstVSyncChange = 0;
|
||
|
allowGeneration = 0;
|
||
|
audioRAvg = 0;
|
||
|
audioLAvg = 0;
|
||
|
audioRAvgSum = 0;
|
||
|
audioLAvgSum = 0;
|
||
|
audioAvgCnt = 1;
|
||
|
packet_ready = 0;
|
||
|
end
|
||
|
|
||
|
function [7:0] ECCcode; // Cycles the error code generator
|
||
| ... | ... | |
|
end
|
||
|
endtask
|
||
|
|
||
|
infopacketstate infopacketstate1 (
|
||
|
i_pixclk, i_reset, start_of_frame, audio_regen_needed, packet_sent, audio_regen, audio_info, video_info, packet_needed);
|
||
|
|
||
|
task InfoGen;
|
||
|
inout [16:0] _timer;
|
||
|
inout _audio_regen_needed;
|
||
|
inout _packet_ready;
|
||
|
begin
|
||
|
if (_timer >= CTS) begin
|
||
|
_audio_regen_needed <= 1'b1;
|
||
|
_timer <= _timer - CTS + 1;
|
||
|
end
|
||
|
|
||
|
_packet_ready <= 0;
|
||
|
|
||
|
if (audio_regen) begin
|
||
|
packetHeader<=24'h000001; // audio clock regeneration packet
|
||
|
subpacket[0]<=audioRegenPacket;
|
||
|
subpacket[1]<=audioRegenPacket;
|
||
|
subpacket[2]<=audioRegenPacket;
|
||
|
subpacket[3]<=audioRegenPacket;
|
||
|
_timer <= _timer - CTS + 1;
|
||
|
end else begin
|
||
|
if (!oddLine) begin
|
||
|
packetHeader<=24'h0D0282; // infoframe AVI packet
|
||
|
// Byte0: Checksum (256-(S%256))%256
|
||
|
// Byte1: 10 = 0(Y1:Y0=0 RGB)(A0=1 active format valid)(B1:B0=00 No bar info)(S1:S0=00 No scan info)
|
||
|
// Byte2: 19 = (C1:C0=0 No colorimetry)(M1:M0=1 4:3)(R3:R0=9 4:3 center)
|
||
|
// Byte3: 00 = 0(SC1:SC0=0 No scaling)
|
||
|
// Byte4: 00 = 0(VIC6:VIC0=0 custom resolution)
|
||
|
// Byte5: 00 = 0(PR5:PR0=0 No repeation)
|
||
|
subpacket[0]<=56'h00000000191046;
|
||
|
subpacket[1]<=56'h00000000000000;
|
||
|
end else begin
|
||
|
packetHeader<=24'h0A0184; // infoframe audio packet
|
||
|
// Byte0: Checksum (256-(S%256))%256
|
||
|
// Byte1: 11 = (CT3:0=1 PCM)0(CC2:0=1 2ch)
|
||
|
// Byte2: 00 = 000(SF2:0=0 As stream)(SS1:0=0 As stream)
|
||
|
// Byte3: 00 = LPCM doesn't use this
|
||
|
// Byte4-5: 00 Multichannel only (>2ch)
|
||
|
subpacket[0]<=56'h00000000001160;
|
||
|
subpacket[1]<=56'h00000000000000;
|
||
|
end
|
||
|
_packet_ready <= 1;
|
||
|
end
|
||
|
|
||
|
if (audio_info) begin
|
||
|
packetHeader<=24'h0A0184; // infoframe audio packet
|
||
|
// Byte0: Checksum (256-(S%256))%256
|
||
|
// Byte1: 11 = (CT3:0=1 PCM)0(CC2:0=1 2ch)
|
||
|
// Byte2: 00 = 000(SF2:0=0 As stream)(SS1:0=0 As stream)
|
||
|
// Byte3: 00 = LPCM doesn't use this
|
||
|
// Byte4-5: 00 Multichannel only (>2ch)
|
||
|
subpacket[0]<=56'h00000000001160;
|
||
|
subpacket[1]<=56'h00000000000000;
|
||
|
subpacket[2]<=56'h00000000000000;
|
||
|
subpacket[3]<=56'h00000000000000;
|
||
|
end
|
||
|
_packet_ready <= 1;
|
||
|
end
|
||
|
|
||
|
if (video_info) begin
|
||
|
packetHeader<=24'h0D0282; // infoframe AVI packet
|
||
|
// Byte0: Checksum (256-(S%256))%256
|
||
|
// Byte1: 10 = 0(Y1:Y0=0 RGB)(A0=1 active format valid)(B1:B0=00 No bar info)(S1:S0=00 No scan info)
|
||
|
// Byte2: 19 = (C1:C0=0 No colorimetry)(M1:M0=1 4:3)(R3:R0=9 4:3 center)
|
||
|
// Byte3: 00 = 0(SC1:SC0=0 No scaling)
|
||
|
// Byte4: 00 = 0(VIC6:VIC0=0 custom resolution)
|
||
|
// Byte5: 00 = 0(PR5:PR0=0 No repeation)
|
||
|
subpacket[0]<=56'h00000000191046;
|
||
|
subpacket[1]<=56'h00000000000000;
|
||
|
subpacket[2]<=56'h00000000000000;
|
||
|
subpacket[3]<=56'h00000000000000;
|
||
|
_packet_ready <= 1;
|
||
|
end
|
||
|
|
||
|
end
|
||
|
endtask
|
||
|
|
||
| ... | ... | |
|
|
||
|
task SendPackets;
|
||
|
inout dataEnable;
|
||
|
inout _packet_sent;
|
||
|
begin
|
||
|
_packet_sent<=0;
|
||
|
if (counterX<32) begin
|
||
|
// Send first data packet (Infoframe or audio clock regen)
|
||
|
dataEnable<=1;
|
||
|
SendPacket(packetHeader, subpacket[0], subpacket[1], subpacket[2], subpacket[3], 1);
|
||
|
if (packet_needed & packet_ready) begin
|
||
|
dataEnable<=1;
|
||
|
SendPacket(packetHeader, subpacket[0], subpacket[1], subpacket[2], subpacket[3], 1);
|
||
|
end
|
||
|
if (counterX==31) begin
|
||
|
_packet_sent<=packet_needed&packet_ready&dataEnable;
|
||
|
end
|
||
|
end else if (counterX<64) begin
|
||
|
// Send second data packet (audio data)
|
||
|
dataEnable<=1;
|
||
|
SendPacket(audioPacketHeader, audioSubPacket[0], audioSubPacket[1], audioSubPacket[2], audioSubPacket[3], 0);
|
||
|
end else begin
|
||
|
dataEnable<=0;
|
||
| ... | ... | |
|
|
||
|
AudioGen();
|
||
|
|
||
|
packet_sent <= 1'b0;
|
||
|
audio_regen_needed <= 1'b0;
|
||
|
start_of_frame <= 1'b0;
|
||
|
|
||
|
// Send 2 packets each line
|
||
|
if(allowGeneration) begin
|
||
|
SendPackets(tercData);
|
||
|
SendPackets(tercData,packet_sent);
|
||
|
end else begin
|
||
|
tercData<=0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
ctsTimer <= ctsTimer + 1;
|
||
|
|
||
| ... | ... | |
|
|
||
|
if(prevHSync != i_hSync) begin
|
||
|
if(firstHSyncChange) begin
|
||
|
InfoGen(ctsTimer);
|
||
|
InfoGen(ctsTimer,audio_regen_needed,packet_ready);
|
||
|
oddLine <= ! oddLine;
|
||
|
counterX <= 0;
|
||
|
allowGeneration <= 1;
|
||
| ... | ... | |
|
firstHSyncChange <= !firstHSyncChange;
|
||
|
end else
|
||
|
counterX <= counterX + 1;
|
||
|
|
||
|
if(prevVSync != i_vSync) begin
|
||
|
if(firstVSyncChange) begin
|
||
|
start_of_frame <= 1;
|
||
|
end
|
||
|
firstVSyncChange <= !firstVSyncChange;
|
||
|
end
|
||
|
|
||
|
prevBlank <= i_blank;
|
||
|
prevHSync <= i_hSync;
|
||
|
prevVSync <= i_vSync;
|
||
|
end
|
||
|
|
||
|
assign o_d0 = dataChannel0;
|
||
Send fewer info packets, spec expects 1/frame