Files
CDi_MiSTer/rtl/mpeg/fmv/mpeg_video_start_code_decoder.sv
Andre Zeps cdcd64d6f5 FMV: Fixed timecode extracted from GOP header
- Fixes human readable time code with VCDs
2025-11-13 19:45:25 +01:00

133 lines
4.7 KiB
Systemverilog

module mpeg_video_start_code_decoder (
input clk,
input reset,
input [7:0] mpeg_data,
input data_valid,
output bit event_sequence_header,
output bit event_group_of_pictures,
output bit event_picture,
output bit [15:0] tmpref,
output bit [31:0] timecode
);
bit [9:0] temporal_sequence_number;
bit [9:0] next_sequence_number;
bit [9:0] gop_cnt = 0;
bit [2:0] coding_type;
bit [15:0] vbv_delay;
enum bit [4:0] {
IDLE,
MAGIC0,
MAGIC1,
MAGIC2,
MAGIC3,
MAGIC_MATCH,
GOP0,
GOP1,
GOP2,
GOP3,
PIC0,
PIC1,
PIC2,
PIC3,
PIC4,
SLICE0,
SEQHDR
} finder_state = IDLE;
always @(posedge clk) begin
event_picture <= 0;
event_group_of_pictures <= 0;
event_sequence_header <= 0;
if (data_valid) begin
// $display ("MPEG %x",mpeg_data);
casez ({
finder_state, mpeg_data
})
// verilog_format: off
{PIC4, 8'h??}: begin
finder_state <= IDLE;
$display ("PIC4 %d %d %d", temporal_sequence_number, coding_type, vbv_delay);
event_picture <= 1;
end
{PIC3, 8'h??}: begin
finder_state <= PIC4;
//$display ("PIC3");
vbv_delay[4:0] <= mpeg_data[7:3];
end
{PIC2, 8'h??}: begin
finder_state <= PIC3;
if (next_sequence_number == temporal_sequence_number)
begin
tmpref[11:2] <= temporal_sequence_number;
$display ("PIC2 %d", temporal_sequence_number);
next_sequence_number <= next_sequence_number + 1;
end
vbv_delay[12:5] <= mpeg_data;
end
{PIC1, 8'h??}: begin
finder_state <= PIC2;
//$display ("PIC1 %x",mpeg_data);
temporal_sequence_number[1:0] <= mpeg_data[7:6];
coding_type <= mpeg_data[5:3];
vbv_delay[15:13] <= mpeg_data[2:0];
end
{PIC0, 8'h??}: begin
finder_state <= PIC1;
//$display ("PIC0 %x",mpeg_data);
temporal_sequence_number[9:2] <= mpeg_data;
end
{GOP3, 8'h??}: begin // P???????
finder_state <= IDLE;
$display ("GOP3 %x",mpeg_data);
event_group_of_pictures <= 1;
next_sequence_number <= 0;
timecode[16] <= mpeg_data[7]; // last bit of pictures
$display ("Timecode %d:%d:%d",timecode[5:0],timecode[27:22], timecode[21:16]);
end
{GOP2, 8'h??}: begin // SSSPPPPP
finder_state <= GOP3;
$display ("GOP2 %x",mpeg_data);
timecode[24:22] <= mpeg_data[7:5]; // lower 3 bits of seconds
timecode[21:17] <= mpeg_data[4:0]; // upper 5 bits of pictures
gop_cnt <= gop_cnt + 1;
end
{GOP1, 8'h??}: begin // MMMM?SSS
finder_state <= GOP2;
$display ("GOP1 %x",mpeg_data);
timecode[3:0] <= mpeg_data[7:4]; // lower 4 bits of minutes
timecode[27:25] <= mpeg_data[2:0]; // upper 3 bits of seconds
end
{GOP0, 8'h??}: begin // ?HHHHHMM
finder_state <= GOP1;
$display ("GOP0 %x",mpeg_data);
timecode[10:6] <= mpeg_data[6:2]; // 5 bit hours
timecode[5:4] <= mpeg_data[1:0]; // upper 2 bits of minutes
end
{SEQHDR, 8'h??}: begin
finder_state <= IDLE;
$display ("SEQHDR %x",mpeg_data);
event_sequence_header <= 1;
end
{MAGIC_MATCH, 8'hb3} : begin finder_state <= SEQHDR;end
{MAGIC_MATCH, 8'hb8} : finder_state <= GOP0;
{MAGIC_MATCH, 8'h00} : finder_state <= PIC0;
{MAGIC_MATCH, 8'h01} : finder_state <= SLICE0;
{MAGIC2, 8'h01} : finder_state <= MAGIC_MATCH;
{MAGIC2, 8'h00} : finder_state <= MAGIC2;
{MAGIC0, 8'h00} : finder_state <= MAGIC2;
{IDLE, 8'h00} : finder_state <= MAGIC0;
default: finder_state <= IDLE;
// verilog_format: on
endcase
end
end
endmodule