FMV: Improved frame pacing

- 25 fps hard coded for experiments
- Presentation time utilized to define start of playback
  - Makes use of FIFO structure for stable frame rate
- Firmware
  - Provides all 3 planar framebuffers to hardware for playback
This commit is contained in:
Andre Zeps
2025-09-14 21:03:00 +02:00
parent b8f2a4852b
commit f7bd5d3d73
17 changed files with 452 additions and 274 deletions

View File

@@ -33,9 +33,9 @@ CD images can be stored as CHD or CUE/BIN format.
Core Utilization:
Logic utilization (in ALMs) 24,631 / 41,910 ( 59 % )
Total registers 29008
Total block memory bits 1,896,711 / 5,662,720 ( 33 % )
Logic utilization (in ALMs) 24,331 / 41,910 ( 58 % )
Total registers 28509
Total block memory bits 1,897,911 / 5,662,720 ( 34 % )
Total DSP Blocks 92 / 112 ( 82 % )
Expected synthesis times with Quartus 17.0.2

View File

@@ -30,6 +30,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/mpeg_input_stream_fi
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/mpeg_video_start_code_decoder.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/mpeg_video.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/worker_firmware_memory.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/yuv_frame_adr_fifo.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/VexiiRiscv.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/pointing_device.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/resetdelay.sv
@@ -49,4 +50,4 @@ set_global_assignment -name VHDL_FILE tg68k/tg68dotc_verilog_wrapper.vhd
set_global_assignment -name VHDL_FILE tg68k/TG68K_ALU.vhd
set_global_assignment -name VHDL_FILE tg68k/TG68K_Pack.vhd
set_global_assignment -name VHDL_FILE tg68k/TG68K.vhd
set_global_assignment -name VHDL_FILE tg68k/TG68KdotC_Kernel.vhd
set_global_assignment -name VHDL_FILE tg68k/TG68KdotC_Kernel.vhd

View File

@@ -1243,9 +1243,6 @@ module mcd212 (
end
vsd = backdrop_pixel && image_coding_method_register.ev;
`ifdef VERILATOR
vsd = 1;
`endif
end
// Implementation of Table 5-13 Register Map

View File

@@ -8,48 +8,49 @@ module mpeg_demuxer (
output bit signed [32:0] system_clock_reference_start_time,
output bit system_clock_reference_start_time_valid
);
parameter string unit = "";
enum bit [4:0] {
FMA_IDLE,
FMA_MAGIC0,
FMA_MAGIC1,
FMA_MAGIC2,
FMA_MAGIC3,
FMA_MAGIC_MATCH,
FMA_PACK0,
FMA_PACK1,
FMA_PACK2,
FMA_PACK3,
FMA_PACK4,
FMA_PACK5,
FMA_PES0,
FMA_PES1,
FMA_PES2,
FMA_PES3,
FMA_PES4,
FMA_PES5,
FMA_PES6,
FMA_PES7,
FMA_PES8,
FMA_PES_DTS0,
FMA_PES_DTS1,
FMA_PES_DTS2,
FMA_PES_DTS3,
FMA_PES_DTS4
IDLE,
MAGIC0,
MAGIC1,
MAGIC2,
MAGIC3,
MAGIC_MATCH,
PACK0,
PACK1,
PACK2,
PACK3,
PACK4,
PACK5,
PES0,
PES1,
PES2,
PES3,
PES4,
PES5,
PES6,
PES7,
PES8,
PES_DTS0,
PES_DTS1,
PES_DTS2,
PES_DTS3,
PES_DTS4
} demux_state = FMA_IDLE;
} demux_state = IDLE;
bit packet_length_decreasing;
bit [15:0] packet_length;
bit signed [32:0] system_clock_reference;
bit [9:0] pack_cnt = 0;
bit [32:0] presentation_time_stamp;
bit [32:0] decoding_time_stamp;
bit signed [32:0] presentation_time_stamp;
bit signed [32:0] decoding_time_stamp;
bit dts_present;
always_ff @(posedge clk) begin
if (reset) begin
demux_state <= FMA_IDLE;
demux_state <= IDLE;
system_clock_reference_start_time_valid <= 0;
end else if (data_valid) begin
@@ -64,140 +65,144 @@ module mpeg_demuxer (
casez ({
demux_state, mpeg_data
})
// verilog_format: off
{FMA_PACK5, 8'h??}: begin
demux_state <= FMA_IDLE;
$display ("FMA PACK %x %d",mpeg_data,system_clock_reference);
{PACK5, 8'h??}: begin
demux_state <= IDLE;
$display ("%s PACK %d", unit, system_clock_reference);
end
{FMA_PACK4, 8'h??}: begin
demux_state <= FMA_PACK5;
{PACK4, 8'h??}: begin
demux_state <= PACK5;
system_clock_reference[6:0] <= mpeg_data[7:1];
pack_cnt <= pack_cnt +1;
end
{FMA_PACK3, 8'h??}: begin
demux_state <= FMA_PACK4;
{PACK3, 8'h??}: begin
demux_state <= PACK4;
system_clock_reference[14:7] <= mpeg_data;
end
{FMA_PACK2, 8'h??}: begin
demux_state <= FMA_PACK3;
{PACK2, 8'h??}: begin
demux_state <= PACK3;
system_clock_reference[21:15] <= mpeg_data[7:1];
end
{FMA_PACK1, 8'h??}: begin
demux_state <= FMA_PACK2;
{PACK1, 8'h??}: begin
demux_state <= PACK2;
system_clock_reference[29:22] <= mpeg_data;
end
{FMA_PACK0, 8'h??}: begin
demux_state <= FMA_PACK1;
{PACK0, 8'h??}: begin
demux_state <= PACK1;
system_clock_reference[32:30] <= mpeg_data[3:1];
end
{FMA_PES8, 8'h??}: begin
demux_state <= FMA_IDLE;
$display ("FMA PES %x %d",mpeg_data,presentation_time_stamp);
{PES8, 8'h??}: begin
demux_state <= IDLE;
if (dts_present)
$display ("%s PES %d %d", unit, presentation_time_stamp, decoding_time_stamp);
else
$display ("%s PES %d", unit, presentation_time_stamp);
// verilog_format: on
if (!system_clock_reference_start_time_valid) begin
system_clock_reference_start_time_valid <= 1;
system_clock_reference_start_time[32:1] <= dclk + presentation_time_stamp[32:1] - system_clock_reference[32:1];
end
// verilog_format: off
end
{FMA_PES_DTS4, 8'b???????1}: begin // DTS
{PES_DTS4, 8'b???????1}: begin // DTS
decoding_time_stamp[6:0] <= mpeg_data[7:1];
mpeg_packet_body <= 1;
demux_state <= FMA_PES8;
demux_state <= PES8;
end
{FMA_PES_DTS3, 8'h??}: begin // DTS
demux_state <= FMA_PES_DTS4;
{PES_DTS3, 8'h??}: begin // DTS
demux_state <= PES_DTS4;
decoding_time_stamp[14:7] <= mpeg_data;
end
{FMA_PES_DTS2, 8'b???????1}: begin // DTS
{PES_DTS2, 8'b???????1}: begin // DTS
decoding_time_stamp[21:15] <= mpeg_data[7:1];
demux_state <= FMA_PES_DTS3;
demux_state <= PES_DTS3;
end
{FMA_PES_DTS1, 8'h??}: begin // DTS
demux_state <= FMA_PES_DTS2;
{PES_DTS1, 8'h??}: begin // DTS
demux_state <= PES_DTS2;
decoding_time_stamp[29:22] <= mpeg_data;
end
{FMA_PES_DTS0, 8'b0001???1}: begin // DTS
{PES_DTS0, 8'b0001???1}: begin // DTS
decoding_time_stamp[32:30] <= mpeg_data[3:1];
demux_state <= FMA_PES_DTS1;
demux_state <= PES_DTS1;
end
{FMA_PES7, 8'b???????1}: begin // PTS
{PES7, 8'b???????1}: begin // PTS
presentation_time_stamp[6:0] <= mpeg_data[7:1];
if (dts_present) begin
demux_state <= FMA_PES_DTS0;
demux_state <= PES_DTS0;
end else begin
mpeg_packet_body <= 1;
demux_state <= FMA_PES8;
demux_state <= PES8;
end
end
{FMA_PES6, 8'h??}: begin // PTS
demux_state <= FMA_PES7;
{PES6, 8'h??}: begin // PTS
demux_state <= PES7;
presentation_time_stamp[14:7] <= mpeg_data;
end
{FMA_PES5, 8'b???????1}: begin // PTS
{PES5, 8'b???????1}: begin // PTS
presentation_time_stamp[21:15] <= mpeg_data[7:1];
demux_state <= FMA_PES6;
demux_state <= PES6;
end
{FMA_PES4, 8'h??}: begin // PTS
demux_state <= FMA_PES5;
{PES4, 8'h??}: begin // PTS
demux_state <= PES5;
presentation_time_stamp[29:22] <= mpeg_data;
end
{FMA_PES2, 8'b0010???1}: begin // PTS (no DTS)
{PES2, 8'b0010???1}: begin // PTS (no DTS)
presentation_time_stamp[32:30] <= mpeg_data[3:1];
dts_present <= 0;
demux_state <= FMA_PES4;
demux_state <= PES4;
end
{FMA_PES2, 8'b0011???1}: begin // PTS and DTS
{PES2, 8'b0011???1}: begin // PTS and DTS
presentation_time_stamp[32:30] <= mpeg_data[3:1];
dts_present <= 1;
demux_state <= FMA_PES4;
demux_state <= PES4;
end
{FMA_PES2, 8'b00001111}: begin // Neither PTS nor DTS
demux_state <= FMA_IDLE;
{PES2, 8'b00001111}: begin // Neither PTS nor DTS
demux_state <= IDLE;
mpeg_packet_body <= 1;
$display ("%s PES ...", unit);
end
{FMA_PES3, 8'h??}: begin
{PES3, 8'h??}: begin
// just ignore STD buffer size second byte
demux_state <= FMA_PES2;
demux_state <= PES2;
end
{FMA_PES2, 8'b01??????}: begin // STD buffer size
demux_state <= FMA_PES3;
{PES2, 8'b01??????}: begin // STD buffer size
demux_state <= PES3;
end
{FMA_PES2, 8'hff}: begin // stuffing byte
demux_state <= FMA_PES2;
{PES2, 8'hff}: begin // stuffing byte
demux_state <= PES2;
end
{FMA_PES1, 8'h??}: begin
demux_state <= FMA_PES2;
{PES1, 8'h??}: begin
demux_state <= PES2;
packet_length[7:0] <= mpeg_data;
packet_length_decreasing <= 1;
end
{FMA_PES0, 8'h??}: begin
demux_state <= FMA_PES1;
{PES0, 8'h??}: begin
demux_state <= PES1;
packet_length[15:8] <= mpeg_data;
end
{FMA_MAGIC_MATCH, 8'hba} : begin
demux_state <= FMA_PACK0;
{MAGIC_MATCH, 8'hba} : begin
demux_state <= PACK0;
end
{FMA_MAGIC_MATCH, 8'hC?} : begin
demux_state <= FMA_PES0;
{MAGIC_MATCH, 8'hC?} : begin
demux_state <= PES0;
end
{FMA_MAGIC_MATCH, 8'hE?} : begin
demux_state <= FMA_PES0;
{MAGIC_MATCH, 8'hE?} : begin
demux_state <= PES0;
end
{FMA_MAGIC2, 8'h01} : demux_state <= FMA_MAGIC_MATCH;
{FMA_MAGIC2, 8'h00} : demux_state <= FMA_MAGIC2;
{FMA_MAGIC0, 8'h00} : demux_state <= FMA_MAGIC2;
{FMA_IDLE, 8'h00} : demux_state <= FMA_MAGIC0;
default: demux_state <= FMA_IDLE;
{MAGIC2, 8'h01} : demux_state <= MAGIC_MATCH;
{MAGIC2, 8'h00} : demux_state <= MAGIC2;
{MAGIC0, 8'h00} : demux_state <= MAGIC2;
{IDLE, 8'h00} : demux_state <= MAGIC0;
default: demux_state <= IDLE;
// verilog_format: on
endcase

View File

@@ -21,13 +21,13 @@ module mpeg_audiofifo (
bit indizes_equal_during_write_d;
bit indizes_equal_during_write_q;
assign out.write = count != 0 && !reset && !indizes_equal_during_write_q;
assign in.strobe = count < 510 && !reset && in.write;
assign out.write = count != 0 && !reset && !indizes_equal_during_write_q;
assign in.strobe = count < 510 && !reset && in.write;
// Every MPEG synthesis will create 32 samples
// Let's have at least 70 samples to not starve during frame change
assign nearly_full = count >= 510;
assign half_full = count >= 70;
assign half_full = count >= 70;
always_comb begin
read_index_d = read_index_q;

View File

@@ -60,4 +60,4 @@ module dual_port_videoram #(
assign data_out2 = data_reg2;
endmodule : dual_port_videoram
endmodule : dual_port_videoram

View File

@@ -1,25 +1,25 @@
00003117
99010113
9b010113
00002517
94050513
95850513
00002597
93858593
95058593
00002617
fd460613
fec60613
00c5fa63
00052283
0055a023
05910511
fec5eae3
00002517
fb850513
fd050513
00002597
55458593
56c58593
00b57763
00052023
6de30511
10effeb5
203965e0
20396760
0001a001
0001a001
00008082
@@ -35,7 +35,7 @@ c66ec86a
4601c398
2bc005b7
20000537
27372ad1
273722f5
431c1000
06934350
078e3e70
@@ -44,116 +44,122 @@ e8638f91
078e4350
fce38f91
4581fef6
09372b69
09372b4d
842a1000
03090913
6b894c81
6d096d89
6d096b89
6c896d89
0b300a93
49a54a09
ef99507c
8a63585c
24830157
85260904
1ee32c01
1ee32425
2a23ff55
85220354
d16d2ca9
d16d2c8d
4c054b0d
2023585c
91630149
9d630149
20231007
85220139
1c6010ef
1de010ef
57442783
0693cff9
44180f84
0713cbfd
44140f84
463d445c
00c92023
a703c298
0785ff0b
a683c314
0785008b
47edc45c
00f92023
08638b05
a7031007
6789ff8d
fe47a783
00371613
0616963a
84638a85
26831206
a783010d
0593ffcd
96130380
96360036
06850616
936397b2
468100b6
00dd2823
11c7a683
458dfef5
100006b7
10b7ae23
cad04605
11c7a603
00b61663
11c7a683
fec68ee3
008ba783
a4230785
f69300fb
c6cd0017
010d2683
ffcda783
03800593
97b20705
00b71363
ac234701
a703feed
ff7511c7
0737458d
00369613
06169636
97b20685
00b69363
28234681
a68300dd
fef511c7
06b7458d
ae231000
460510b7
a603cb50
a603cad0
166311c7
a70300b6
0ee311c7
a783fec7
0785ff0b
fefba823
0017f713
a703cb41
6789ff8d
fe47a783
00371613
0616963a
03800593
97b20705
00b71363
ac234701
a703feed
ff7511c7
0737458d
ae231000
460510b7
a603cb50
166311c7
a70300b6
0ee311c7
47f1fec7
a68300b6
8ee311c7
47f1fec6
00f92023
100007b7
01978023
0c854ad0
cf90cb94
5c1cb5e5
07b74314
c3941000
01472883
02c72803
434c5308
86be4710
37b7ca98
a0231000
a2230117
c7880107
cb90c7cc
5c1cbdc1
03678063
57042783
0693cf99
bf210c84
0713cf99
b7010c84
09042483
20fd8526
2a23fd75
bdd50204
09840693
2823b709
bdf95784
ff4d2603
bdf10204
09840713
2823b5ed
b5d95784
00cca603
a7836789
1593fe07
1593ff87
95b20036
05130596
06050380
036397ae
873200a6
feed2a23
2603bf8d
6789ff4d
fe07a783
86b200a6
00dca623
a603bf99
678900cc
ff87a783
00361593
059695b2
03800513
97ae0605
00a60363
2a238732
bdd5feed
a62386b2
bde900dc
a7036789
1101fec7
11010047
c64ec84a
ce06c452
ca26cc22
@@ -173,11 +179,11 @@ cb158a32
00230731
640900d7
05134485
46715744
a6234581
10effe97
467158c4
a2234581
10ef0097
051347e0
40f25744
40f258c4
20234462
22230125
28230125
@@ -274,7 +280,7 @@ fee78de3
471cc71c
1c078d63
85936589
8313f9c5
8313fb45
461d0405
c50348a1
431c0005
@@ -296,7 +302,7 @@ c50348a1
471cc71c
18078d63
85936589
8313f9c5
8313fb45
461d0405
c50348a1
431c0005
@@ -391,14 +397,14 @@ d78ccfc8
610506a8
45018082
65898082
f5c58593
f7458593
04000613
4f050513
10efc642
48321ee0
6589b599
53080513
f1c58593
f3458593
04000613
10efc642
48321d60
@@ -407,9 +413,9 @@ f1c58593
c226c422
84aa842e
57800613
ffc90513
01490513
09134581
c606ffc9
c6060149
0d4010ef
08892a23
08992823
@@ -424,7 +430,7 @@ fe851ee3
48858082
93336809
081300b8
45019e48
45019fc8
10002737
4354431c
8de3078e
@@ -527,19 +533,19 @@ df934017
73638d1d
80820065
23036509
8a85ff05
8a850085
73138b05
0d630013
6f890403
ff8fa303
010fa303
25036509
1f13fe45
1f13ffc5
9f1a0033
03050f16
03800293
0563957a
ac230653
2303fe6f
a8230653
2303006f
1a6311c5
28230403
d11c0105
@@ -553,15 +559,15 @@ c15001c5
47051000
8082cbd8
af036289
6509ff42
fe052503
650900c2
ff852503
003f1f93
0f969ffa
0f05957e
03800f93
01ff0363
aa23837a
2303fe62
a623837a
23030062
1ee311c5
b765fe03
bf614301
@@ -678,18 +684,18 @@ ce62d05e
ca6acc66
db984721
a7836789
8a2eff07
8a2e0087
84638b85
66892e07
ff86a783
0106a783
28036709
9713fe47
9713ffc7
973e0037
07850716
03800613
8a63983a
ac2342c7
2783fef6
a82342c7
278300f6
916311c8
20232e07
22230008
@@ -764,7 +770,7 @@ ac2342c7
873e00fa
16936789
87930027
070a9487
070a9607
033397b6
a88300e5
2683ff47
@@ -802,8 +808,8 @@ c7901000
10000337
03030313
8293197d
8f93f9c2
45d1edcf
8f93fb42
45d1ef4f
100027b7
03100713
03934e85
@@ -866,15 +872,15 @@ c7637ff0
03960633
00ca2023
6609bf1d
ff462703
00c62703
a8036689
1693fe06
1693ff86
96ba0037
07050696
03800593
03639836
87ba00b7
fef62a23
00f62623
11c82783
bb31fff5
0007aa03
@@ -957,7 +963,7 @@ c86e019a
b525f00c
53050f13
4781b359
fef6ac23
00f6a823
57fdb6f9
97b30705
8fd900c7
@@ -976,11 +982,11 @@ bdd197b2
47391000
c226c606
6709db98
ff072783
00872783
842a6589
28230785
8593fef7
4601d9c5
24230785
859300f7
4601db45
10002737
431c4505
078e4354
@@ -1034,7 +1040,7 @@ d87402f7
4c5c14f7
12f6df63
67895c18
cec78793
d0478793
97ba070a
46014388
10002737
@@ -1072,7 +1078,7 @@ cad1d43c
8b890604
10078563
c04a6589
af458593
b0c58593
27374601
45051000
4354431c
@@ -1457,8 +1463,8 @@ ff010113
00002937
00112623
00912223
94890913
94840413
96090913
96040413
02890263
40890933
40295913
@@ -1470,8 +1476,8 @@ ff010113
ff24e8e3
00002937
00002437
94890913
94840413
96090913
96040413
02890263
40890933
40295913
@@ -1616,9 +1622,9 @@ fed70fa3
00158593
fc079ae3
f01ff06f
0000199c
00001954
00001954
000019b4
0000196c
0000196c
00000002
00000004
00000000
@@ -1850,9 +1856,9 @@ fff50000
002f0000
001f0000
00000000
00001d8c
00001d54
00001cfc
00001da4
00001d6c
00001d14
00000002
00000004
00000006

View File

@@ -16,19 +16,19 @@ module frameplayer (
input hblank,
input vblank,
input [28:0] frame_adr,
input planar_yuv_s frame,
input latch_frame
);
assign ddrif.byteenable = 8'hff;
assign ddrif.write = 0;
bit [28:0] latched_frame_adr = 0;
planar_yuv_s latched_frame;
always_ff @(posedge clkddr) begin
if (latch_frame) begin
latched_frame_adr <= frame_adr;
$display("Latched frame %x", latched_frame_adr);
latched_frame <= frame;
//$display("Latched frame %x", latched_frame);
end
end
@@ -173,9 +173,9 @@ module frameplayer (
if (reset_clkddr || vblank_clkddr) begin
fetchstate <= IDLE;
address_y <= latched_frame_adr + 29'h0;
address_v <= latched_frame_adr + 29'h15900; // 368*240 = 88320
address_u <= latched_frame_adr + 29'h1af40; // 368*240 + 88320/4
address_y <= latched_frame.y_adr;
address_u <= latched_frame.u_adr;
address_v <= latched_frame.v_adr;
target_y <= 0;
target_u <= 0;
target_v <= 0;

View File

@@ -19,4 +19,4 @@ module mpeg_input_stream_fifo_32k (
always_ff @(posedge clkr) begin
q <= ram[raddr];
end
endmodule : mpeg_input_stream_fifo_32k
endmodule : mpeg_input_stream_fifo_32k

View File

@@ -6,6 +6,7 @@ module mpeg_video (
input clk60,
input reset,
input dsp_enable,
input playback_active,
input [7:0] data_byte,
input data_strobe,
@@ -698,12 +699,9 @@ module mpeg_video (
end
endcase
end
end
// Assuming 90 MHz clock rate and 25 Hz frame rate
localparam TICKS_PER_FRAME = 1200000 * 3;
planar_yuv_s just_decoded;
bit signed [15:0] shared_buffer_level = 0;
@@ -761,6 +759,12 @@ module mpeg_video (
4'd4: begin // Shared SRAM region
end
4'd1: begin
if (dmem_cmd_payload_address_1[15:0] == 16'h3000)
just_decoded.y_adr <= dmem_cmd_payload_data_1[28:0];
if (dmem_cmd_payload_address_1[15:0] == 16'h3004)
just_decoded.u_adr <= dmem_cmd_payload_data_1[28:0];
if (dmem_cmd_payload_address_1[15:0] == 16'h3008)
just_decoded.v_adr <= dmem_cmd_payload_data_1[28:0];
end
4'd0: begin
end
@@ -1021,6 +1025,55 @@ module mpeg_video (
end
end
planar_yuv_s for_display;
wire just_decoded_commit = dmem_cmd_payload_write_1 && dmem_cmd_valid_1 && dmem_cmd_ready_1 && dmem_cmd_payload_address_1==32'h10003010;
wire for_display_valid;
bit for_display_strobe;
bit latch_frame_for_display;
wire latch_frame_for_display_clk60;
// Assuming 30 MHz clock rate and 25 Hz frame rate
localparam bit [23:0] TICKS_PER_FRAME = 24'(int'(30e6) / 25);
bit [23:0] playback_frame_cnt;
// In theory this machine could run with clk60.
// But I'm not so sure about the final frequency and timing is vital
always_ff @(posedge clk30) begin
latch_frame_for_display <= 0;
if (!playback_active) playback_frame_cnt <= 0;
else begin
playback_frame_cnt <= playback_frame_cnt + 1;
// Only for simulation. Ensure that frames are always available - no underflow
if (playback_frame_cnt == 0) assert (for_display_valid);
if (playback_frame_cnt == TICKS_PER_FRAME - 1) playback_frame_cnt <= 0;
if (playback_frame_cnt == 0 && for_display_valid) latch_frame_for_display <= 1;
end
end
flag_cross_domain cross_latch_frame (
.clk_a(clk30),
.clk_b(clk60),
.flag_in_clk_a(latch_frame_for_display),
.flag_out_clk_b(latch_frame_for_display_clk60)
);
yuv_frame_adr_fifo readyframes (
.clk_in(clk60),
.reset_in(reset_dsp_enabled_clk60),
.wdata(just_decoded),
.we(just_decoded_commit),
.reset_out(reset_dsp_enabled_clk60),
.clk_out(clk60),
.strobe(latch_frame_for_display_clk60),
.valid(for_display_valid),
.q(for_display)
);
frameplayer frameplayer (
.clk(clk30),
.clkddr(clk60),
@@ -1031,8 +1084,8 @@ module mpeg_video (
.vsync,
.hblank,
.vblank,
.frame_adr(dmem_cmd_payload_data_1[28:0]),
.latch_frame(expose_frame_y_adr_clk60)
.frame(for_display),
.latch_frame(latch_frame_for_display)
);
endmodule

View File

@@ -11,11 +11,13 @@ module mpeg_video_start_code_decoder (
output bit [31:0] timecode
);
bit [9:0] temperal_sequence_number;
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 [3:0] {
enum bit [4:0] {
IDLE,
MAGIC0,
MAGIC1,
@@ -30,6 +32,7 @@ module mpeg_video_start_code_decoder (
PIC1,
PIC2,
PIC3,
PIC4,
SLICE0,
SEQHDR
} finder_state = IDLE;
@@ -46,29 +49,38 @@ module mpeg_video_start_code_decoder (
})
// verilog_format: off
{PIC3, 8'h??}: begin finder_state <= IDLE;
$display ("PIC3 %x",mpeg_data);
{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 == temperal_sequence_number)
if (next_sequence_number == temporal_sequence_number)
begin
tmpref[11:2] <= temperal_sequence_number;
$display ("PIC2 %x %d",mpeg_data,temperal_sequence_number);
tmpref[11:2] <= temporal_sequence_number;
$display ("PIC2 %d", temporal_sequence_number);
next_sequence_number <= next_sequence_number + 1;
end
end
vbv_delay[12:5] <= mpeg_data;
end
{PIC1, 8'h??}: begin
finder_state <= PIC2;
//$display ("PIC1 %x",mpeg_data);
temperal_sequence_number[1:0] <= mpeg_data[7:6];
end
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);
temperal_sequence_number[9:2] <= mpeg_data;
end
temporal_sequence_number[9:2] <= mpeg_data;
end
{GOP3, 8'h??}: begin
finder_state <= IDLE;
$display ("GOP3 %x",mpeg_data);

View File

@@ -64,4 +64,4 @@ module worker_firmware_memory #(
assign data_out2 = data_reg2;
endmodule : worker_firmware_memory
endmodule : worker_firmware_memory

View File

@@ -0,0 +1,80 @@
`include "../util.svh"
module yuv_frame_adr_fifo (
// Input
input clk_in,
input reset_in,
input planar_yuv_s wdata,
input we,
// Output
input reset_out,
input clk_out,
input strobe,
output bit valid,
output planar_yuv_s q
);
planar_yuv_s ram[16];
// Clock domain of output
bit [3:0] raddr; // 512 x 8
// Clock domain of input
bit [3:0] waddr; // 64 x 64
// verilog_format: off
// Transfer waddr from clk_in to clk_out
bit [3:0] waddr_gray;
b2g_converter #(.WIDTH(4)) waddr_to_gray1 (.binary(waddr),.gray(waddr_gray));
bit [3:0] waddr_q;
bit [3:0] waddr_q2;
bit [3:0] waddr_q3;
always @(posedge clk_in) waddr_q <= waddr_gray;
always @(posedge clk_out) waddr_q2 <= waddr_q;
always @(posedge clk_out) waddr_q3 <= waddr_q2;
bit [3:0] waddr_clkout;
g2b_converter #(.WIDTH(4)) waddr_to_binary1 (.binary(waddr_clkout),.gray(waddr_q3));
// Transfer raddr from clk_out to clk_in
bit [3:0] raddr_gray;
b2g_converter #(.WIDTH(4)) raddr_to_gray2 (.binary(raddr),.gray(raddr_gray));
bit [3:0] raddr_q;
bit [3:0] raddr_q2;
bit [3:0] raddr_q3;
always @(posedge clk_out) raddr_q <= raddr_gray;
always @(posedge clk_in) raddr_q2 <= raddr_q;
always @(posedge clk_in) raddr_q3 <= raddr_q2;
bit [3:0] raddr_clkin;
g2b_converter #(.WIDTH(4)) raddr_to_binary2 (.binary(raddr_clkin),.gray(raddr_q3));
// verilog_format: on
wire [3:0] cnt_clkin = waddr - raddr_clkin;
wire [3:0] cnt_clkout = waddr_clkout - raddr;
always_ff @(posedge clk_in) begin
if (reset_in) waddr <= 0;
else if (we) begin
ram[waddr] <= wdata;
waddr <= waddr + 1;
assert (cnt_clkout < 10);
assert (cnt_clkin < 10);
end
end
always_ff @(posedge clk_out) begin
if (reset_out) raddr <= 0;
else if (strobe) begin
raddr <= raddr + 1;
assert (cnt_clkout > 0);
assert (cnt_clkin > 0);
end
q <= ram[raddr];
valid <= cnt_clkout != 0;
end
endmodule : yuv_frame_adr_fifo

View File

@@ -1,6 +1,12 @@
`ifndef HEADER_UTIL
`define HEADER_UTIL
typedef struct {
bit [28:0] y_adr;
bit [28:0] u_adr;
bit [28:0] v_adr;
} planar_yuv_s;
function [31:0] ones_mask(bit [4:0] n);
begin
ones_mask = (32'h1 << n) - 1; // n ones at LSB

View File

@@ -99,12 +99,14 @@ module vmpeg (
// [5:0] 6 Bit Minutes? Not BCD
// Where are the hours?
wire [31:0] fmv_timecode;
bit fmv_playback_active;
mpeg_video video (
.clk30(clk),
.clk60(clk_mpeg),
.reset,
.dsp_enable(1'b1),
.playback_active(fmv_playback_active),
.data_byte(mpeg_data),
.data_strobe(fmv_data_valid && fmv_packet_body),
.fifo_full(video_fifo_full),
@@ -134,29 +136,35 @@ module vmpeg (
);
bit dsp_enable = 0;
wire signed [32:0] system_clock_reference_start_time;
wire system_clock_reference_start_time_valid;
wire signed [32:0] fma_system_clock_reference_start_time;
wire fma_system_clock_reference_start_time_valid;
wire signed [32:0] fmv_system_clock_reference_start_time;
wire fmv_system_clock_reference_start_time_valid;
mpeg_demuxer audio_demuxer (
mpeg_demuxer #(
.unit("FMA")
) audio_demuxer (
.clk,
.reset(reset || (fma_command_register == 1)),
.mpeg_data(mpeg_data),
.data_valid(fma_data_valid),
.mpeg_packet_body(fma_packet_body),
.dclk(fma_dclk),
.system_clock_reference_start_time(system_clock_reference_start_time),
.system_clock_reference_start_time_valid(system_clock_reference_start_time_valid)
.system_clock_reference_start_time(fma_system_clock_reference_start_time),
.system_clock_reference_start_time_valid(fma_system_clock_reference_start_time_valid)
);
mpeg_demuxer video_demuxer (
mpeg_demuxer #(
.unit("FMV")
) video_demuxer (
.clk,
.reset(reset),
.mpeg_data(mpeg_data),
.data_valid(fmv_data_valid),
.mpeg_packet_body(fmv_packet_body),
.dclk(fma_dclk),
.system_clock_reference_start_time(),
.system_clock_reference_start_time_valid()
.system_clock_reference_start_time(fmv_system_clock_reference_start_time),
.system_clock_reference_start_time_valid(fmv_system_clock_reference_start_time_valid)
);
typedef struct packed {
@@ -328,6 +336,8 @@ module vmpeg (
mpeg_ram_enabled_cnt <= 0;
timer_cnt <= 0;
dma_active <= 0;
dsp_enable <= 0;
fmv_playback_active <= 0;
end else begin
if (vsync && !vsync_q) interrupt_status_register.vsync <= 1;
@@ -370,9 +380,14 @@ module vmpeg (
timer_cnt <= timer_cnt + 1;
end
if (system_clock_reference_start_time_valid && fma_dclk == system_clock_reference_start_time[32:1] && !dsp_enable) begin
if (fma_system_clock_reference_start_time_valid && fma_dclk == fma_system_clock_reference_start_time[32:1] && !dsp_enable) begin
dsp_enable <= 1;
end
if (fmv_system_clock_reference_start_time_valid && fma_dclk == fmv_system_clock_reference_start_time[32:1] && !fmv_playback_active) begin
fmv_playback_active <= 1;
end
end else begin
fma_dclk_shadow_cnt <= fma_dclk_shadow_cnt + 1;
end

View File

@@ -4,4 +4,4 @@
cd "$(dirname "$0")/../rtl"
verible-verilog-format --inplace --indentation_spaces 4 \
../rtl/*.v ../rtl/*.sv ../*.v ../*.sv
../rtl/*.v ../rtl/*.sv ../rtl/*/*.sv ../rtl/*/*/*.sv ../*.v ../*.sv

View File

@@ -21,7 +21,7 @@
#define SCC68070
#define SLAVE
#define TRACE
// #define TRACE
// #define SIMULATE_RC5
#define PL_MPEG_IMPLEMENTATION
@@ -638,10 +638,13 @@ class CDi {
} else {
// PAL
if (frame_index == 144) { // Skip Philips Logo
if ((frame_index % 25) == 20)
press_button_signal = true;
if (frame_index == 137) { // Skip Philips Logo
press_button_signal = true;
}
if (frame_index == 430) { // Skip Dragons Lair Intro
press_button_signal = true;
}
}
@@ -869,7 +872,7 @@ class CDi {
start = std::chrono::system_clock::now();
#ifdef TRACE
//do_trace = false;
do_trace = false;
fprintf(stderr, "Trace off!\n");
#endif