mirror of
https://github.com/MiSTer-devel/CDi_MiSTer.git
synced 2026-04-19 03:04:19 +00:00
FMV: Added support for window, screen, display offset and NIS events
- Fixes wrong offset with "Les Guignols de l’Info" - Fixes graphical corruption with "Christmas Crisis" - Fixes "skewed image corruption" with MPEG video - Adds support for NIS video event due to update of sequence parameters - Fixes "Philips Logo Intro" with "Brain Dead 13" Dynamic behavior is probably not yet correct. - "Christmas Crisis" is stuttering in the bonus rides. It should be noted that "Brain Dead 13" is still not working after the company logo.
This commit is contained in:
14
CDi.sdc
14
CDi.sdc
@@ -17,3 +17,17 @@ set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|de
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|pictures_in_fifo_clk_mpeg_gray_q*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|pictures_in_fifo_clk30_gray*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|linecnt*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|linecnt_clkddr*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|altsyncram:ram_rtl_0|altsyncram_g3n1:auto_generated|ram_block1a0~PORT_B_WRITE_ENABLE_REG} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|first_intra_frame_of_gop_clk30}
|
||||
|
||||
# protected by just_decoded_commit_clk30
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|decoder_width_clk_mpeg*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|decoder_width*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|decoder_height_clk_mpeg*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|decoder_height*}
|
||||
|
||||
|
||||
# protected by latch_frame_clkvideo
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|video_ctrl_window_height*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|frame_height_clkddr*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|video_ctrl_window_width*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|frame_width_clkddr*}
|
||||
|
||||
# protected by latch_frame_clkddr
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|video_ctrl_decoder_offset_y*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|window_y_clkddr*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|video_ctrl_decoder_offset_x*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|window_x_clkddr*}
|
||||
|
||||
|
||||
19
README.md
19
README.md
@@ -47,10 +47,10 @@ CD images can be stored as CHD or CUE/BIN format.
|
||||
|
||||
Core Utilization:
|
||||
|
||||
Logic utilization (in ALMs) 22,424 / 41,910 ( 54 % )
|
||||
Total registers 25036
|
||||
Total block memory bits 2,331,040 / 5,662,720 ( 41 % )
|
||||
Total DSP Blocks 96 / 112 ( 86 % )
|
||||
Logic utilization (in ALMs) 22,603 / 41,910 ( 54 % )
|
||||
Total registers 25334
|
||||
Total block memory bits 2,336,208 / 5,662,720 ( 41 % )
|
||||
Total DSP Blocks 98 / 112 ( 88 % )
|
||||
|
||||
Expected synthesis times with Quartus 17.0.2
|
||||
|
||||
@@ -64,10 +64,8 @@ Expected synthesis times with Quartus 17.0.2
|
||||
* Regression of "Historia del Arte Español" (working in DVC rc2)
|
||||
* Blank video?
|
||||
* Fix Christmas Crisis bonus ride
|
||||
* Video is much wider than the CD-i resolution. Window function required
|
||||
* Fix position of MPEG video, relative to base case video
|
||||
* Seems very perceivable with "Les Guignols de l’Info"
|
||||
* Add MPEG audio attenuation
|
||||
* Might still stutter. Analysis required.
|
||||
* Add MPEG audio attenuation (e.g. Lost Eden)
|
||||
* "Mutant Rampage - Bodyslam" has a tendency to freeze?
|
||||
* "The Last Bounty Hunter", "Drug Wars", "Mad Dog 2", "Who Shot Johnny Rock?" have regressions (works in rc2)?
|
||||
* "Chaos Control" has video glitches?
|
||||
@@ -77,11 +75,8 @@ Expected synthesis times with Quartus 17.0.2
|
||||
* "Brain Dead 13" having no video during intro. And hangs afterwards.
|
||||
* The decoding and playback does occur but mv_show() is not done?
|
||||
* "The Secret of Nimh" (Philips Edition) has the wrong frame rate? Sometimes?
|
||||
* "The Secret of Nimh" (VCD) doesn't play
|
||||
* Huffman decoding in state 14 takes too long
|
||||
* Slow motion with VCDs is behaving incorrect
|
||||
* Leaving the cake Puzzle in 7th Guest freezes (everytime?)
|
||||
* Weird shifted graphics with "David and Goliath"
|
||||
* VCD resolution for white book
|
||||
* Sound bugs on the police procedures disk?
|
||||
* Find a better solution for reducing CPU speed
|
||||
@@ -107,7 +102,7 @@ Expected synthesis times with Quartus 17.0.2
|
||||
* RC5 support is added. A test using real hardware is required.
|
||||
* Add 2 player support
|
||||
* CD+G
|
||||
* Check compatibilitiy with CDs that have track index 2 as opposed to the usual 0 and 1
|
||||
* Check compatibility with CDs that have track index 2 as opposed to the usual 0 and 1
|
||||
* Possibly adding support for other PCBs (like Mono II)
|
||||
* Refurbish I2C for the front display and show the content as picture in picture during changes?
|
||||
* It might not even be required at all.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
0x000001EC FMA madriv IN4 (shared)
|
||||
0x00000200 CDIC cdapdriv IN4 (shared)
|
||||
0x00000068 SLAVE IN2
|
||||
MCD212 INT1
|
||||
0x000000F4 MCD212 INT1
|
||||
|
||||
## DMA
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fma/mpeg_audiofifo.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fma/mpeg_input_stream_fifo_8k.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/dct_coeff_huffman_decoder.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/ddr_chroma_line_buffer.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/ddr_to_byte_fifo.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/ddr_luma_line_buffer.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/decoder_firmware_memory.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/dual_port_videoram.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mpeg/fmv/dualport_shared_ram.sv
|
||||
|
||||
@@ -163,8 +163,6 @@ module audiodecoder (
|
||||
bit signed [31:0] mac;
|
||||
bit stop_playback_latch;
|
||||
|
||||
wire inbetween /*verilator public_flat_rd*/ = decoder_state == APPLY_FILTER1;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
disable_audiomap <= 0;
|
||||
|
||||
|
||||
@@ -168,15 +168,10 @@ module cditop (
|
||||
|
||||
|
||||
if ((lds || uds) && attex_cs_mk48)
|
||||
$display(
|
||||
"Access NVRAM %x %x %x %d %d %d",
|
||||
addr[7:1],
|
||||
data_in,
|
||||
cpu_data_out,
|
||||
lds,
|
||||
uds,
|
||||
write_strobe
|
||||
);
|
||||
|
||||
if (write_strobe)
|
||||
$display("Write NVRAM %x %x %d%d", addr[7:1], cpu_data_out, lds, uds);
|
||||
else $display("Read NVRAM %x %x %d%d", addr[7:1], data_in, lds, uds);
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,16 +9,18 @@ module ddr_chroma_line_buffer (
|
||||
input we,
|
||||
// Output
|
||||
input clk_out,
|
||||
input [7:0] raddr, // 256 x 8
|
||||
input [8:0] raddr, // 512 x 8
|
||||
output bit [7:0] q
|
||||
);
|
||||
|
||||
// The maximum resolution for MPEG should be 384
|
||||
// Since U and V are halfed, we need 192 pixels of storage
|
||||
// To be safe, we go for 200
|
||||
// The maximum resolution for MPEG should be 384 for the CD-i
|
||||
// But games like Christmas Crisis have a 528 pixel wide frame and crop it
|
||||
// We will go for 640 pixels here, to be safe.
|
||||
// Since U and V are halfed, we need 320 pixels of storage
|
||||
// To be safe, we go for 512 pixels here
|
||||
|
||||
bit [4:0] waddr; // 32 x 64
|
||||
bit [7:0][7:0] ram[256/8];
|
||||
bit [5:0] waddr; // 64 x 64
|
||||
bit [7:0][7:0] ram[512/8];
|
||||
|
||||
always_ff @(posedge clk_in) begin
|
||||
if (reset) waddr <= 0;
|
||||
@@ -30,7 +32,7 @@ module ddr_chroma_line_buffer (
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_out) begin
|
||||
q <= ram[raddr[7:3]][raddr[2:0]];
|
||||
q <= ram[raddr[8:3]][raddr[2:0]];
|
||||
end
|
||||
|
||||
endmodule : ddr_chroma_line_buffer
|
||||
|
||||
36
rtl/mpeg/fmv/ddr_luma_line_buffer.sv
Normal file
36
rtl/mpeg/fmv/ddr_luma_line_buffer.sv
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
// For buffering of a Y line
|
||||
module ddr_luma_line_buffer (
|
||||
// Input
|
||||
input clk_in,
|
||||
input reset,
|
||||
input [63:0] wdata,
|
||||
input we,
|
||||
// Output
|
||||
input clk_out,
|
||||
input [9:0] raddr, // 640 x 8
|
||||
output bit [7:0] q
|
||||
);
|
||||
|
||||
// The maximum resolution for MPEG should be 384 for the CD-i
|
||||
// But games like Christmas Crisis have a 528 pixel wide frame and crop it
|
||||
// We will go for 640 pixels here, to be safe.
|
||||
|
||||
bit [6:0] waddr; // 128 x 64
|
||||
bit [7:0][7:0] ram[640/8];
|
||||
|
||||
always_ff @(posedge clk_in) begin
|
||||
if (reset) waddr <= 0;
|
||||
|
||||
if (we) begin
|
||||
ram[waddr] <= wdata;
|
||||
waddr <= waddr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_out) begin
|
||||
q <= ram[raddr[9:3]][raddr[2:0]];
|
||||
end
|
||||
|
||||
endmodule : ddr_luma_line_buffer
|
||||
|
||||
@@ -54,7 +54,7 @@ module ddr_to_byte_fifo (
|
||||
|
||||
// The threshold can't be set to exactly half.
|
||||
// There is a latency of this signal because of the clock synchronization above
|
||||
// The supplying machine might always provide more than requested becaues of this!
|
||||
// The supplying machine might always provide more than requested because of this!
|
||||
assign half_empty = cnt_clkin < 100;
|
||||
|
||||
always_ff @(posedge clk_in) begin
|
||||
|
||||
@@ -17,15 +17,19 @@ module frameplayer (
|
||||
input vblank,
|
||||
|
||||
input planar_yuv_s frame,
|
||||
input [8:0] frame_width, // expected to be clocked at clkddr
|
||||
input [8:0] frame_height, // expected to be clocked at clkddr
|
||||
input [8:0] frame_width, // expected to be clocked at clkvideo
|
||||
input [10:0] frame_stride, // expected to be clocked at clkddr
|
||||
input [8:0] frame_height, // expected to be clocked at clkvideo
|
||||
input [8:0] offset_y, // expected to be clocked at clkvideo
|
||||
input [8:0] offset_x, // expected to be clocked at clkvideo
|
||||
input [8:0] window_y, // expected to be clocked at clkvideo
|
||||
input [8:0] window_x, // expected to be clocked at clkvideo
|
||||
|
||||
|
||||
input latch_frame_clkvideo,
|
||||
input latch_frame_clkddr,
|
||||
input invalidate_latched_frame,
|
||||
input show_on_next_video_frame
|
||||
input show_on_next_video_frame // expected to be clocked at clkddr
|
||||
);
|
||||
|
||||
assign ddrif.byteenable = 8'hff;
|
||||
@@ -48,6 +52,11 @@ module frameplayer (
|
||||
bit [8:0] frame_width_clkvideo = 100;
|
||||
bit [8:0] frame_height_clkvideo = 100;
|
||||
|
||||
bit [8:0] frame_width_clkddr = 100;
|
||||
bit [8:0] frame_height_clkddr = 100;
|
||||
bit [8:0] window_x_clkddr;
|
||||
bit [8:0] window_y_clkddr;
|
||||
|
||||
always_ff @(posedge clkvideo) begin
|
||||
if (latch_frame_clkvideo) begin
|
||||
frame_width_clkvideo <= frame_width;
|
||||
@@ -55,25 +64,29 @@ module frameplayer (
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clkddr) begin
|
||||
if (latch_frame_clkddr) begin
|
||||
frame_width_clkddr <= frame_width;
|
||||
frame_height_clkddr <= frame_height;
|
||||
window_x_clkddr <= window_x;
|
||||
window_y_clkddr <= window_y;
|
||||
end
|
||||
end
|
||||
|
||||
bit [28:0] address_y;
|
||||
bit [28:0] address_u;
|
||||
bit [28:0] address_v;
|
||||
|
||||
bit [28:0] address_y_offset;
|
||||
bit [28:0] address_uv_offset;
|
||||
|
||||
enum bit [1:0] {
|
||||
IDLE,
|
||||
WAITING,
|
||||
SETTLE
|
||||
} fetchstate;
|
||||
|
||||
wire y_half_empty;
|
||||
wire u_half_empty;
|
||||
wire v_half_empty;
|
||||
bit luma_fifo_strobe;
|
||||
bit chroma_fifo_strobe;
|
||||
|
||||
wire y_valid;
|
||||
wire u_valid;
|
||||
wire v_valid;
|
||||
yuv_s current_color;
|
||||
|
||||
bit target_y;
|
||||
@@ -86,19 +99,6 @@ module frameplayer (
|
||||
wire reset_clkddr;
|
||||
wire vblank_clkddr;
|
||||
|
||||
ddr_to_byte_fifo fifo_y (
|
||||
.clk_in(clkddr),
|
||||
.reset_in(vblank_clkddr),
|
||||
.reset_out(vblank),
|
||||
.wdata(ddrif.rdata),
|
||||
.we(ddrif.rdata_ready && target_y),
|
||||
.half_empty(y_half_empty),
|
||||
.clk_out(clkvideo),
|
||||
.strobe(luma_fifo_strobe),
|
||||
.valid(y_valid),
|
||||
.q(current_color.y)
|
||||
);
|
||||
|
||||
flag_cross_domain cross_new_line_started (
|
||||
.clk_a(clkvideo),
|
||||
.clk_b(clkddr),
|
||||
@@ -128,7 +128,13 @@ module frameplayer (
|
||||
.signal_out_clk_b(fetch_and_show_frame_clkvideo)
|
||||
);
|
||||
|
||||
bit [7:0] chroma_read_addr;
|
||||
bit [9:0] luma_read_addr;
|
||||
bit [9:0] chroma_read_addr;
|
||||
|
||||
/// Since DD4 access is aligned to 8 byte,
|
||||
/// we need a way of throwing up to 7 byte away
|
||||
bit [2:0] initial_luma_read_addr;
|
||||
bit [3:0] initial_chroma_read_addr;
|
||||
|
||||
ddr_chroma_line_buffer line_buffer_u (
|
||||
.clk_in(clkddr),
|
||||
@@ -137,7 +143,7 @@ module frameplayer (
|
||||
.we(ddrif.rdata_ready && target_u),
|
||||
.clk_out(clkvideo),
|
||||
.q(current_color.u),
|
||||
.raddr(chroma_read_addr)
|
||||
.raddr(chroma_read_addr[9:1])
|
||||
);
|
||||
|
||||
ddr_chroma_line_buffer line_buffer_v (
|
||||
@@ -147,7 +153,17 @@ module frameplayer (
|
||||
.we(ddrif.rdata_ready && target_v),
|
||||
.clk_out(clkvideo),
|
||||
.q(current_color.v),
|
||||
.raddr(chroma_read_addr)
|
||||
.raddr(chroma_read_addr[9:1])
|
||||
);
|
||||
|
||||
ddr_luma_line_buffer line_buffer_y (
|
||||
.clk_in(clkddr),
|
||||
.reset(new_line_started_clkddr),
|
||||
.wdata(ddrif.rdata),
|
||||
.we(ddrif.rdata_ready && target_y),
|
||||
.clk_out(clkvideo),
|
||||
.q(current_color.y),
|
||||
.raddr(luma_read_addr)
|
||||
);
|
||||
|
||||
|
||||
@@ -158,41 +174,50 @@ module frameplayer (
|
||||
bit line_alternate;
|
||||
bit u_requested;
|
||||
bit v_requested;
|
||||
bit y_requested;
|
||||
|
||||
bit [8:0] vertical_offset_wait;
|
||||
bit [8:0] horizontal_offset_wait;
|
||||
bit [10:0] horizontal_offset_wait;
|
||||
bit [8:0] latched_offset_x;
|
||||
|
||||
always_ff @(posedge clkvideo) begin
|
||||
hsync_q <= hsync;
|
||||
|
||||
if (reset || vsync) begin
|
||||
if (reset || vblank) begin
|
||||
linecnt <= 0;
|
||||
vertical_offset_wait <= offset_y;
|
||||
latched_offset_x <= offset_x;
|
||||
end else if (!vblank && hsync && !hsync_q) begin
|
||||
if (vertical_offset_wait != 0) vertical_offset_wait <= vertical_offset_wait - 1;
|
||||
else linecnt <= linecnt + 1;
|
||||
end
|
||||
|
||||
if (chroma_fifo_strobe) chroma_read_addr <= chroma_read_addr + 1;
|
||||
if (luma_fifo_strobe) begin
|
||||
luma_read_addr <= luma_read_addr + 1;
|
||||
chroma_read_addr <= chroma_read_addr + 1;
|
||||
end
|
||||
|
||||
if (vblank) begin
|
||||
initial_luma_read_addr <= window_x[2:0];
|
||||
initial_chroma_read_addr <= window_x[3:0];
|
||||
end
|
||||
|
||||
if (hblank || reset) begin
|
||||
pixelcnt <= 0;
|
||||
chroma_fifo_strobe <= 0;
|
||||
luma_fifo_strobe <= 0;
|
||||
chroma_read_addr <= 0;
|
||||
horizontal_offset_wait <= offset_x;
|
||||
|
||||
luma_read_addr <= {7'b0, initial_luma_read_addr};
|
||||
chroma_read_addr <= {6'b000000, initial_chroma_read_addr};
|
||||
horizontal_offset_wait <= {latched_offset_x, 2'b00};
|
||||
end else if (!vblank && !hblank && pixelcnt < frame_width_clkvideo << 2 && linecnt < frame_height_clkvideo && vertical_offset_wait==0 && fetch_and_show_frame_clkvideo) begin
|
||||
|
||||
if (horizontal_offset_wait != 0) horizontal_offset_wait <= horizontal_offset_wait - 1;
|
||||
else begin
|
||||
pixelcnt <= pixelcnt + 1;
|
||||
luma_fifo_strobe <= pixelcnt[1:0] == 3 - 2;
|
||||
chroma_fifo_strobe <= pixelcnt[2:0] == 7 - 2;
|
||||
assert (y_valid);
|
||||
end
|
||||
end else begin
|
||||
chroma_fifo_strobe <= 0;
|
||||
luma_fifo_strobe <= 0;
|
||||
luma_fifo_strobe <= 0;
|
||||
end
|
||||
|
||||
/*
|
||||
@@ -204,7 +229,7 @@ module frameplayer (
|
||||
*/
|
||||
end
|
||||
|
||||
bit [5:0] data_burst_cnt;
|
||||
bit [6:0] data_burst_cnt;
|
||||
|
||||
// 0011 like the N64 core to force a base of 0x30000000
|
||||
localparam bit [3:0] DDR_CORE_BASE = 4'b0011;
|
||||
@@ -217,13 +242,6 @@ module frameplayer (
|
||||
.signal_out_clk_b(vertical_offset_wait_not_null_clkddr)
|
||||
);
|
||||
|
||||
wire show_on_next_video_frame_clkddr;
|
||||
signal_cross_domain cross_vshow_on_next_video_frame (
|
||||
.clk_a(clkvideo),
|
||||
.clk_b(clkddr),
|
||||
.signal_in_clk_a(show_on_next_video_frame),
|
||||
.signal_out_clk_b(show_on_next_video_frame_clkddr)
|
||||
);
|
||||
|
||||
always_ff @(posedge clkddr) begin
|
||||
linecnt_clkddr <= linecnt;
|
||||
@@ -238,26 +256,32 @@ module frameplayer (
|
||||
ddrif.acquire <= 0;
|
||||
end
|
||||
|
||||
address_y_offset <= frame_stride * window_y_clkddr;
|
||||
address_uv_offset <= 29'(frame_stride / 2) * 29'(window_y_clkddr / 2);
|
||||
|
||||
if (reset_clkddr || vblank_clkddr || vertical_offset_wait_not_null_clkddr) begin
|
||||
fetchstate <= IDLE;
|
||||
address_y <= latched_frame.y_adr;
|
||||
address_u <= latched_frame.u_adr;
|
||||
address_v <= latched_frame.v_adr;
|
||||
fetch_and_show_frame <= latched_frame_valid && show_on_next_video_frame_clkddr;
|
||||
address_y <= latched_frame.y_adr + address_y_offset + 29'(window_x_clkddr);
|
||||
address_u <= latched_frame.u_adr + address_uv_offset + 29'(window_x_clkddr / 2);
|
||||
address_v <= latched_frame.v_adr + address_uv_offset + 29'(window_x_clkddr / 2);
|
||||
fetch_and_show_frame <= latched_frame_valid && show_on_next_video_frame;
|
||||
target_y <= 0;
|
||||
target_u <= 0;
|
||||
target_v <= 0;
|
||||
line_alternate <= 0;
|
||||
line_alternate <= window_y_clkddr[0];
|
||||
u_requested <= 0;
|
||||
v_requested <= 0;
|
||||
y_requested <= 0;
|
||||
end else if (fetch_and_show_frame) begin
|
||||
if (new_line_started_clkddr && linecnt_clkddr < frame_height) begin
|
||||
if (new_line_started_clkddr && linecnt_clkddr < frame_height_clkddr) begin
|
||||
line_alternate <= !line_alternate;
|
||||
|
||||
if (line_alternate) begin
|
||||
u_requested <= 0;
|
||||
v_requested <= 0;
|
||||
end
|
||||
|
||||
y_requested <= 0;
|
||||
end
|
||||
|
||||
case (fetchstate)
|
||||
@@ -267,9 +291,9 @@ module frameplayer (
|
||||
ddrif.addr <= {DDR_CORE_BASE, address_u[27:3]};
|
||||
ddrif.read <= 1;
|
||||
ddrif.acquire <= 1;
|
||||
address_u <= address_u + 29'(frame_width / 2);
|
||||
ddrif.burstcnt <= 8'(frame_width / 16);
|
||||
data_burst_cnt <= 6'(frame_width / 16);
|
||||
address_u <= address_u + 29'(frame_stride / 2);
|
||||
ddrif.burstcnt <= 8'(9'(frame_width_clkddr + 15) / 16) + 1;
|
||||
data_burst_cnt <= 7'(9'(frame_width_clkddr + 15) / 16) + 1;
|
||||
fetchstate <= WAITING;
|
||||
target_u <= 1;
|
||||
end else if (!v_requested) begin
|
||||
@@ -277,18 +301,19 @@ module frameplayer (
|
||||
ddrif.addr <= {DDR_CORE_BASE, address_v[27:3]};
|
||||
ddrif.read <= 1;
|
||||
ddrif.acquire <= 1;
|
||||
address_v <= address_v + 29'(frame_width / 2);
|
||||
ddrif.burstcnt <= 8'(frame_width / 16);
|
||||
data_burst_cnt <= 6'(frame_width / 16);
|
||||
address_v <= address_v + 29'(frame_stride / 2);
|
||||
ddrif.burstcnt <= 8'(9'(frame_width_clkddr + 15) / 16) + 1;
|
||||
data_burst_cnt <= 7'(9'(frame_width_clkddr + 15) / 16) + 1;
|
||||
fetchstate <= WAITING;
|
||||
target_v <= 1;
|
||||
end else if (y_half_empty) begin
|
||||
end else if (!y_requested) begin
|
||||
y_requested <= 1;
|
||||
ddrif.addr <= {DDR_CORE_BASE, address_y[27:3]};
|
||||
ddrif.read <= 1;
|
||||
ddrif.acquire <= 1;
|
||||
ddrif.burstcnt <= 50;
|
||||
data_burst_cnt <= 50;
|
||||
address_y <= address_y + 8 * 50;
|
||||
address_y <= address_y + 29'(frame_stride);
|
||||
ddrif.burstcnt <= 8'(9'(frame_width_clkddr + 7) / 8) + 1;
|
||||
data_burst_cnt <= 7'(9'(frame_width_clkddr + 7) / 8) + 1;
|
||||
fetchstate <= WAITING;
|
||||
target_y <= 1;
|
||||
end
|
||||
|
||||
@@ -23,13 +23,20 @@ module mpeg_video (
|
||||
|
||||
input [8:0] display_offset_y,
|
||||
input [8:0] display_offset_x,
|
||||
input [8:0] window_offset_y,
|
||||
input [8:0] window_offset_x,
|
||||
input [8:0] window_width,
|
||||
input [8:0] window_height,
|
||||
input show_on_next_video_frame,
|
||||
output event_sequence_end,
|
||||
output event_buffer_underflow,
|
||||
output bit event_picture_starts_display,
|
||||
output event_last_picture_starts_display,
|
||||
output bit event_first_intra_frame_starts_display,
|
||||
output [3:0] pictures_in_fifo
|
||||
output [3:0] pictures_in_fifo,
|
||||
output bit [10:0] decoder_width,
|
||||
output bit [8:0] decoder_height
|
||||
|
||||
);
|
||||
|
||||
ddr_if worker_2_ddr ();
|
||||
@@ -756,8 +763,8 @@ module mpeg_video (
|
||||
end
|
||||
|
||||
planar_yuv_s just_decoded;
|
||||
bit [8:0] decoder_width = 100;
|
||||
bit [8:0] decoder_height = 100;
|
||||
bit [10:0] decoder_width_clk_mpeg = 100;
|
||||
bit [8:0] decoder_height_clk_mpeg = 100;
|
||||
|
||||
bit signed [15:0] shared_buffer_level = 0;
|
||||
|
||||
@@ -780,12 +787,9 @@ module mpeg_video (
|
||||
bit dmem_cmd_ready_3_q;
|
||||
bit dmem_cmd_payload_write_3_q;
|
||||
|
||||
bit frame_period_clk_mpeg_set_clk_mpeg;
|
||||
|
||||
always_ff @(posedge clk_mpeg) begin
|
||||
imem_rsp_valid_1 <= 0;
|
||||
dmem_rsp_valid_1 <= 0;
|
||||
frame_period_clk_mpeg_set_clk_mpeg <= 0;
|
||||
|
||||
dmem_cmd_payload_address_1_q <= dmem_cmd_payload_address_1;
|
||||
dmem_cmd_valid_1_q <= dmem_cmd_valid_1;
|
||||
@@ -796,12 +800,6 @@ module mpeg_video (
|
||||
|
||||
event_sequence_end_clk_mpeg <= 0;
|
||||
|
||||
if (dmem_cmd_payload_address_1 >= 32'h00002c10 && dmem_cmd_payload_address_1 <= 32'h0002cc0 && dmem_cmd_payload_write_1 && dmem_cmd_valid_1 && dmem_cmd_ready_1) begin
|
||||
$display("Core 1 SEQ HDR write %x at %x during code address %x",
|
||||
dmem_cmd_payload_data_1, dmem_cmd_payload_address_1,
|
||||
imem_cmd_payload_address_1);
|
||||
end
|
||||
|
||||
if (dmem_cmd_payload_address_1 == 32'h1000000c && dmem_cmd_payload_write_1 && dmem_cmd_valid_1 && dmem_cmd_ready_1)begin
|
||||
$display("Core 1 stopped at %x with code %x", imem_cmd_payload_address_1,
|
||||
dmem_cmd_payload_data_1);
|
||||
@@ -835,9 +833,9 @@ module mpeg_video (
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h3008)
|
||||
just_decoded.v_adr <= dmem_cmd_payload_data_1[28:0];
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h300c)
|
||||
decoder_width <= dmem_cmd_payload_data_1[8:0];
|
||||
decoder_width_clk_mpeg <= dmem_cmd_payload_data_1[10:0];
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h3010)
|
||||
decoder_height <= dmem_cmd_payload_data_1[8:0];
|
||||
decoder_height_clk_mpeg <= dmem_cmd_payload_data_1[8:0];
|
||||
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h2010) begin
|
||||
has_sequence_header <= dmem_cmd_payload_data_1[0];
|
||||
@@ -846,7 +844,6 @@ module mpeg_video (
|
||||
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h3014) begin
|
||||
frame_period_clk_mpeg <= dmem_cmd_payload_data_1[23:0];
|
||||
frame_period_clk_mpeg_set_clk_mpeg <= 1;
|
||||
end
|
||||
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h301c)
|
||||
@@ -1191,24 +1188,34 @@ module mpeg_video (
|
||||
bit vblank_q2;
|
||||
bit for_display_valid;
|
||||
|
||||
wire frame_period_clk_mpeg_set_clk30;
|
||||
wire just_decoded_commit_clk30;
|
||||
|
||||
// frame_period_clk_mpeg is set very infrequently.
|
||||
// frame_period_clk_mpeg_set_clk_mpeg is set for one clk_mpeg tick to indicate change
|
||||
// frame_period_clk_mpeg_set_clk30 is this flag moved over to the clk30 domain
|
||||
// When frame_period_clk_mpeg_set_clk30 is high, the stability of frame_period_clk_mpeg is assumed
|
||||
flag_cross_domain cross_frame_period_clk_mpeg_set (
|
||||
// frame info are set very infrequently.
|
||||
// just_decoded_commit is set for one clk_mpeg tick to indicate change
|
||||
// just_decoded_commit_clk30 is this flag moved over to the clk30 domain
|
||||
// When just_decoded_commit_clk30 is high, the stability of all frame info is assumed
|
||||
flag_cross_domain cross_just_decoded_commit (
|
||||
.clk_a(clk_mpeg),
|
||||
.clk_b(clk30),
|
||||
.flag_in_clk_a(frame_period_clk_mpeg_set_clk_mpeg),
|
||||
.flag_out_clk_b(frame_period_clk_mpeg_set_clk30)
|
||||
.flag_in_clk_a(just_decoded_commit),
|
||||
.flag_out_clk_b(just_decoded_commit_clk30)
|
||||
);
|
||||
|
||||
always_ff @(posedge clk30) begin
|
||||
vblank_q1 <= vblank;
|
||||
vblank_q2 <= vblank_q1;
|
||||
|
||||
if (frame_period_clk_mpeg_set_clk30) frame_period <= frame_period_clk_mpeg;
|
||||
if (just_decoded_commit_clk30) begin
|
||||
frame_period <= frame_period_clk_mpeg;
|
||||
decoder_width <= decoder_width_clk_mpeg;
|
||||
decoder_height <= decoder_height_clk_mpeg;
|
||||
end
|
||||
|
||||
if (!dsp_enable) begin
|
||||
decoder_width <= 0;
|
||||
decoder_height <= 0;
|
||||
frame_period <= 0;
|
||||
end
|
||||
|
||||
for_display_valid <= for_display_valid_clk_mpeg;
|
||||
first_intra_frame_of_gop_clk30 <= for_display.first_intra_frame_of_gop;
|
||||
@@ -1268,12 +1275,20 @@ module mpeg_video (
|
||||
);
|
||||
|
||||
|
||||
wire show_on_next_video_frame_clkddr;
|
||||
signal_cross_domain cross_vshow_on_next_video_frame (
|
||||
.clk_a(clk30),
|
||||
.clk_b(clk_mpeg),
|
||||
.signal_in_clk_a(show_on_next_video_frame),
|
||||
.signal_out_clk_b(show_on_next_video_frame_clkddr)
|
||||
);
|
||||
|
||||
yuv_frame_adr_fifo readyframes (
|
||||
.clk(clk_mpeg),
|
||||
.reset(reset_dsp_enabled_clk_mpeg),
|
||||
.wdata(just_decoded),
|
||||
.we(just_decoded_commit),
|
||||
.strobe(latch_frame_for_display_clk_mpeg),
|
||||
.strobe(latch_frame_for_display_clk_mpeg && show_on_next_video_frame_clkddr),
|
||||
.valid(for_display_valid_clk_mpeg),
|
||||
.q(for_display),
|
||||
.cnt(pictures_in_fifo_clk_mpeg)
|
||||
@@ -1290,14 +1305,17 @@ module mpeg_video (
|
||||
.hblank,
|
||||
.vblank,
|
||||
.frame(for_display),
|
||||
.frame_width(decoder_width),
|
||||
.frame_height(decoder_height),
|
||||
.frame_width(window_width),
|
||||
.frame_stride(decoder_width_clk_mpeg),
|
||||
.frame_height(window_height),
|
||||
.offset_y(display_offset_y),
|
||||
.offset_x(display_offset_x),
|
||||
.window_y(window_offset_y),
|
||||
.window_x(window_offset_x),
|
||||
.latch_frame_clkvideo(latch_frame_for_display),
|
||||
.latch_frame_clkddr(latch_frame_for_display_clk_mpeg),
|
||||
.invalidate_latched_frame(reset_persistent_storage_clk_mpeg),
|
||||
.show_on_next_video_frame(show_on_next_video_frame)
|
||||
.show_on_next_video_frame(show_on_next_video_frame_clkddr)
|
||||
);
|
||||
endmodule
|
||||
|
||||
|
||||
152
rtl/vmpeg.sv
152
rtl/vmpeg.sv
@@ -65,12 +65,9 @@ module vmpeg (
|
||||
wire fmv_data_valid /*verilator public_flat_rd*/ = mpeg_data_valid && !dma_for_fma;
|
||||
wire fma_data_valid /*verilator public_flat_rd*/ = mpeg_data_valid && dma_for_fma;
|
||||
|
||||
wire fmv_word_data_valid /*verilator public_flat_rd*/ = mpeg_word_valid && !dma_for_fma;
|
||||
wire fma_word_data_valid /*verilator public_flat_rd*/ = mpeg_word_valid && dma_for_fma;
|
||||
|
||||
wire event_decoding_started;
|
||||
wire event_frame_decoded;
|
||||
wire event_underflow;
|
||||
wire fma_event_decoding_started;
|
||||
wire fma_event_frame_decoded;
|
||||
wire fma_event_underflow;
|
||||
bit dsp_reset_input_fifo;
|
||||
bit fma_dsp_enable = 0;
|
||||
bit fmv_dsp_enable = 0;
|
||||
@@ -91,9 +88,9 @@ module vmpeg (
|
||||
.audio_right(audio_right),
|
||||
.sample_tick44(sample_tick44),
|
||||
.playback_active(),
|
||||
.event_decoding_started(event_decoding_started),
|
||||
.event_frame_decoded(event_frame_decoded),
|
||||
.event_underflow(event_underflow)
|
||||
.event_decoding_started(fma_event_decoding_started),
|
||||
.event_frame_decoded(fma_event_frame_decoded),
|
||||
.event_underflow(fma_event_underflow)
|
||||
);
|
||||
|
||||
wire fmv_event_picture_starts_display;
|
||||
@@ -134,13 +131,19 @@ module vmpeg (
|
||||
.vidout,
|
||||
.display_offset_x(video_ctrl_x_display[8:0]),
|
||||
.display_offset_y(video_ctrl_y_display[8:0]),
|
||||
.window_offset_y(video_ctrl_decoder_offset_y[8:0]),
|
||||
.window_offset_x(video_ctrl_decoder_offset_x[8:0]),
|
||||
.window_width(video_ctrl_window_width[8:0]),
|
||||
.window_height(video_ctrl_window_height[8:0]),
|
||||
.show_on_next_video_frame(fmv_show_on_next_video_frame),
|
||||
.event_sequence_end(fmv_event_sequence_end),
|
||||
.event_buffer_underflow(fmv_event_buffer_underflow),
|
||||
.event_picture_starts_display(fmv_event_picture_starts_display),
|
||||
.event_last_picture_starts_display(fmv_event_last_picture_starts_display),
|
||||
.event_first_intra_frame_starts_display(fmv_event_first_intra_frame_starts_display),
|
||||
.pictures_in_fifo(fmv_pictures_in_fifo)
|
||||
.pictures_in_fifo(fmv_pictures_in_fifo),
|
||||
.decoder_width(fmv_decoder_width),
|
||||
.decoder_height(fmv_decoder_height)
|
||||
);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
@@ -216,7 +219,7 @@ module vmpeg (
|
||||
typedef struct packed {
|
||||
bit erdv; // ?
|
||||
bit erdd; // ?
|
||||
bit vcup; // ?
|
||||
bit vcup; // Video Clip Update ?
|
||||
bit pai; // Pause Interrupt ?
|
||||
|
||||
bit vsync; // Vertical Synchronization ?
|
||||
@@ -312,17 +315,34 @@ module vmpeg (
|
||||
wire fma_intreq = (fma_interrupt_status_register & fma_interrupt_enable_register) != 0;
|
||||
assign intreq = fma_intreq || fmv_intreq;
|
||||
|
||||
bit [15:0] video_ctrl_y_active = 0;
|
||||
bit [15:0] video_ctrl_x_active = 0;
|
||||
bit [15:0] video_ctrl_y_offset = 0;
|
||||
bit [15:0] video_ctrl_x_offset = 0;
|
||||
bit [15:0] video_ctrl_y_display = 0;
|
||||
bit [15:0] video_ctrl_x_display = 0;
|
||||
bit [15:0] video_data_input_command_register = 0;
|
||||
// Where does this come from? Where is it used?
|
||||
bit [15:0] video_ctrl_y_active = 0;
|
||||
bit [15:0] video_ctrl_x_active = 0;
|
||||
|
||||
bit [15:0] image_height2 = 0;
|
||||
bit [15:0] image_width2 = 0;
|
||||
bit [15:0] image_rt;
|
||||
// Where does this come from? Where is it used?
|
||||
bit [15:0] video_ctrl_y_offset = 0;
|
||||
bit [15:0] video_ctrl_x_offset = 0;
|
||||
|
||||
// Sum of mv_org() + mv_pos()
|
||||
bit [15:0] video_ctrl_y_display = 0;
|
||||
bit [15:0] video_ctrl_x_display = 0;
|
||||
|
||||
// set by mv_window(_,_,x,y,W,H_);
|
||||
bit [15:0] video_ctrl_window_width = 0;
|
||||
bit [15:0] video_ctrl_window_height = 0;
|
||||
|
||||
// set by mv_window(_,_,X,Y,w,h_);
|
||||
bit [15:0] video_ctrl_decoder_offset_y = 0;
|
||||
bit [15:0] video_ctrl_decoder_offset_x = 0;
|
||||
|
||||
wire [10:0] fmv_decoder_width;
|
||||
wire [ 8:0] fmv_decoder_height;
|
||||
|
||||
bit [15:0] video_data_input_command_register = 0;
|
||||
|
||||
bit [15:0] image_height = 0;
|
||||
bit [15:0] image_width = 0;
|
||||
bit [15:0] image_rt;
|
||||
|
||||
typedef struct packed {
|
||||
bit show_next;
|
||||
@@ -360,13 +380,13 @@ module vmpeg (
|
||||
15'h180E: dout = fma_interrupt_enable_register; // 0x0E0301C
|
||||
15'h1812: dout = 16'h0004; // 0x0E03024, HF2 Flag of DSP56001?
|
||||
|
||||
15'h2001: dout = image_width2; // 00E04002 ??
|
||||
15'h2002: dout = image_height2; // 00E04004 ??
|
||||
15'h2001: dout = image_width; // 00E04002 ?? Written then Read
|
||||
15'h2002: dout = image_height; // 00E04004 ?? Written then Read
|
||||
15'h2003: dout = image_rt; // 00E04006 ??
|
||||
15'h2004: dout = fmv_timecode[31:16]; // 00E04008 Temporal time code High. During scan
|
||||
15'h2005: dout = fmv_timecode[15:0]; // 00E0400C Temporal time code Low. During scan
|
||||
15'h2029: dout = image_width2; // e04052 Pic Size High ??
|
||||
15'h202a: dout = image_height2; // e04054 Pic Size Low ??
|
||||
15'h2029: dout = {5'b0, fmv_decoder_width}; // e04052 Picture Width ?? Only read
|
||||
15'h202a: dout = {7'b0, fmv_decoder_height}; // e04054 Picture Height ?? Only read
|
||||
15'h202b: dout = image_rt; // e04056 Pic Rt ??
|
||||
15'h202c: dout = fmv_timecode[31:16]; // 00E04058 Time Code High ??
|
||||
15'h202d: dout = fmv_timecode[15:0]; // 00E0405A Time Code Low ??
|
||||
@@ -375,12 +395,16 @@ module vmpeg (
|
||||
15'h2030: dout = fmv_interrupt_enable_register; // 0E04060
|
||||
15'h2031: dout = fmv_interrupt_status_register; // 0E04062
|
||||
15'h2032: dout = fmv_timer_compare_register; // 0E04064
|
||||
15'h2036: dout = video_ctrl_y_offset; // 0E0406C
|
||||
15'h2037: dout = video_ctrl_x_offset; // 0E0406E
|
||||
15'h2038: dout = video_ctrl_y_active; // 0E04070
|
||||
15'h2039: dout = video_ctrl_x_active; // 0E04072
|
||||
15'h203a: dout = video_ctrl_y_display; // 0E04074
|
||||
15'h203b: dout = video_ctrl_x_display; // 0E04076
|
||||
15'h2036: dout = video_ctrl_y_offset; // 0E0406C FMA_VOFF
|
||||
15'h2037: dout = video_ctrl_x_offset; // 0E0406E FMV_HOFF
|
||||
15'h2038: dout = video_ctrl_y_active; // 0E04070 FMV_VPIX
|
||||
15'h2039: dout = video_ctrl_x_active; // 0E04072 FMV_HPIX
|
||||
15'h203a: dout = video_ctrl_y_display; // 0E04074 FMV_SCRPOS Y
|
||||
15'h203b: dout = video_ctrl_x_display; // 0E04076 FMV_SCRPOS X
|
||||
15'h203c: dout = video_ctrl_window_height; // 0E04078 FMV_DECWIN H
|
||||
15'h203d: dout = video_ctrl_window_width; // 0E0407A FMV_DECWIN W
|
||||
15'h203e: dout = video_ctrl_decoder_offset_y; // 0E0407C FMV_DECOFF Y
|
||||
15'h203f: dout = video_ctrl_decoder_offset_x; // 0E0407E FMV_DECOFF X
|
||||
15'h2044: dout = 0; // E04088 Decoder Command? GEN_DEC_CMD?
|
||||
15'h2046: dout = video_data_input_command_register; // 0E0408C GEN_VDI_CMD
|
||||
15'h204C: dout = fmv_dclk[21:6]; // 0E04098 GEN_SYSCR
|
||||
@@ -447,9 +471,9 @@ module vmpeg (
|
||||
fmv_interrupt_vector_register <= 0;
|
||||
fmv_playback_active <= 0;
|
||||
fmv_stream_number <= 0;
|
||||
image_height2 <= 0;
|
||||
image_height <= 0;
|
||||
image_rt <= 0;
|
||||
image_width2 <= 0;
|
||||
image_width <= 0;
|
||||
mpeg_ram_enabled <= 0;
|
||||
mpeg_ram_enabled_cnt <= 0;
|
||||
timer_cnt <= 0;
|
||||
@@ -459,23 +483,31 @@ module vmpeg (
|
||||
video_ctrl_y_active <= 0;
|
||||
video_ctrl_y_display <= 0;
|
||||
video_ctrl_y_offset <= 0;
|
||||
video_ctrl_window_width <= 0;
|
||||
video_ctrl_window_height <= 0;
|
||||
video_ctrl_decoder_offset_y <= 0;
|
||||
video_ctrl_decoder_offset_x <= 0;
|
||||
video_data_input_command_register <= 0;
|
||||
fmv_show_on_next_video_frame <= 0;
|
||||
pending_fma_stream_change <= 0;
|
||||
|
||||
end else begin
|
||||
|
||||
if (restart_fmv_dsp_enable_q) fmv_dsp_enable <= 1;
|
||||
if (fmv_decoding_timestamp_updated) video_data_input_command_register[14] <= 1;
|
||||
|
||||
if (vsync && !vsync_q) fmv_interrupt_status_register.vsync <= 1;
|
||||
if (vsync && !vsync_q) begin
|
||||
fmv_interrupt_status_register.vsync <= 1;
|
||||
end
|
||||
|
||||
if (fmv_event_sequence_header) begin
|
||||
fmv_interrupt_status_register.seq <= 1;
|
||||
$display("Cause FMV Seq Event");
|
||||
end
|
||||
if (fmv_event_group_of_pictures) fmv_interrupt_status_register.gop <= 1;
|
||||
if (fmv_event_picture) fmv_interrupt_status_register.pic <= 1;
|
||||
if (fmv_event_picture) begin
|
||||
fmv_interrupt_status_register.pic <= 1;
|
||||
|
||||
end
|
||||
if (fmv_event_last_picture_starts_display) fmv_interrupt_status_register.eod <= 1;
|
||||
if (fmv_event_program_end) fmv_interrupt_status_register.eii <= 1;
|
||||
if (fmv_event_sequence_end) fmv_interrupt_status_register.esi <= 1;
|
||||
@@ -484,7 +516,7 @@ module vmpeg (
|
||||
$display("FMV Underflow");
|
||||
end
|
||||
|
||||
if (event_decoding_started) begin
|
||||
if (fma_event_decoding_started) begin
|
||||
// Decoding started
|
||||
fma_status_register[4] <= 1;
|
||||
|
||||
@@ -492,19 +524,19 @@ module vmpeg (
|
||||
fma_interrupt_status_register[4] <= 1;
|
||||
end
|
||||
|
||||
if (event_frame_decoded) begin
|
||||
if (fma_event_frame_decoded) begin
|
||||
// Frame Header Updated
|
||||
fma_status_register[2] <= 1;
|
||||
fma_status_register[2] <= 1;
|
||||
|
||||
// Frame Header Updated IRQ
|
||||
fma_interrupt_status_register[2] <= 1;
|
||||
|
||||
// Stream change IRQ
|
||||
fma_interrupt_status_register[1] <= pending_fma_stream_change;
|
||||
pending_fma_stream_change <= 0;
|
||||
pending_fma_stream_change <= 0;
|
||||
end
|
||||
|
||||
if (event_underflow) begin
|
||||
if (fma_event_underflow) begin
|
||||
// Underflow
|
||||
fma_status_register[3] <= 1;
|
||||
|
||||
@@ -698,6 +730,10 @@ module vmpeg (
|
||||
|
||||
if (din[3]) begin // 0008 Play
|
||||
fmv_playback_active <= 1;
|
||||
|
||||
// Really correct?
|
||||
image_width <= {5'b0, fmv_decoder_width};
|
||||
image_height <= {7'b0, fmv_decoder_height};
|
||||
end
|
||||
|
||||
if (din[4]) begin // 0010 Pause
|
||||
@@ -746,18 +782,28 @@ module vmpeg (
|
||||
$display("FMV Write VIDCMD Register %x %x", address[15:1], din);
|
||||
/*
|
||||
according to fmvd.txt
|
||||
0008 RegsUpd
|
||||
000c Scroll + RegsUpd
|
||||
0020 VidOn
|
||||
0100 Hide
|
||||
0200 Show
|
||||
*/
|
||||
fmv_video_command_register <= din;
|
||||
|
||||
// 0008 RegsUpd
|
||||
if (din[3]) begin
|
||||
$display("RegsUpd");
|
||||
end
|
||||
|
||||
// Hide 0100
|
||||
if (din[8]) fmv_show_on_next_video_frame <= 0;
|
||||
|
||||
// Show Window 0200
|
||||
if (din[9]) fmv_show_on_next_video_frame <= 1;
|
||||
// Show Window on next picture change 0400
|
||||
if (din[10]) fmv_show_on_next_video_frame <= 1;
|
||||
if (din[10]) begin
|
||||
fmv_show_on_next_video_frame <= 1;
|
||||
end
|
||||
|
||||
// TODO this might not be right
|
||||
end
|
||||
@@ -793,6 +839,24 @@ module vmpeg (
|
||||
$display("FMV Write X Display %x %x ?", address[15:1], din);
|
||||
video_ctrl_x_display <= din;
|
||||
end
|
||||
|
||||
15'h203c: begin
|
||||
$display("FMV Write FMV_DECWIN H %x %x ?", address[15:1], din);
|
||||
video_ctrl_window_height <= din;
|
||||
end
|
||||
15'h203d: begin
|
||||
$display("FMV Write FMV_DECWIN W %x %x ?", address[15:1], din);
|
||||
video_ctrl_window_width <= din;
|
||||
end
|
||||
15'h203e: begin
|
||||
$display("FMV Write FMV_DECOFF Y %x %x ?", address[15:1], din);
|
||||
video_ctrl_decoder_offset_y <= din;
|
||||
end
|
||||
15'h203f: begin
|
||||
$display("FMV Write FMV_DECOFF X %x %x ?", address[15:1], din);
|
||||
video_ctrl_decoder_offset_x <= din;
|
||||
end
|
||||
|
||||
15'h2046: begin
|
||||
$display("FMV Write GEN_VDI_CMD %x %x ?", address[15:1], din);
|
||||
video_data_input_command_register <= din;
|
||||
@@ -807,11 +871,11 @@ module vmpeg (
|
||||
end
|
||||
15'h2001: begin
|
||||
$display("FMV Write Image Width2 %x %x", address[15:1], din);
|
||||
image_width2 <= din;
|
||||
image_width <= din;
|
||||
end
|
||||
15'h2002: begin
|
||||
$display("FMV Write Image Height2 %x %x", address[15:1], din);
|
||||
image_height2 <= din;
|
||||
image_height <= din;
|
||||
end
|
||||
15'h2003: begin
|
||||
$display("FMV Write Image RT? %x %x", address[15:1], din);
|
||||
|
||||
@@ -872,12 +872,12 @@ class CDi {
|
||||
std::chrono::duration<double> elapsed_seconds = current - start;
|
||||
sprintf(filename, "%d/video_%03d.png", instanceid, frame_index);
|
||||
write_png_file(filename);
|
||||
printf("Written %s %d\n", filename, pixel_index);
|
||||
printf("We are at time30mhz=%ld\n", time30mhz);
|
||||
printf("Written video_%03d.png\n", frame_index);
|
||||
// printf("We are at time30mhz=%ld\n", time30mhz);
|
||||
|
||||
uint32_t mpeg_frequency = mpeg_clk_calc_ticks * 30 / mpeg_clk_calc_ticks30;
|
||||
|
||||
printf("Written %s after %.2fs. FMV at %d MHz\n", filename, elapsed_seconds.count(), mpeg_frequency);
|
||||
// printf("Written %s after %.2fs. FMV at %d MHz\n", filename, elapsed_seconds.count(), mpeg_frequency);
|
||||
fprintf(stderr, "Written %s after %.2fs. FMV at %d MHz\n", filename, elapsed_seconds.count(),
|
||||
mpeg_frequency);
|
||||
|
||||
@@ -1225,7 +1225,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
switch (machineindex) {
|
||||
case 0:
|
||||
f_cd_bin = fopen("images/david.bin", "rb");
|
||||
f_cd_bin = fopen("images/guignols.bin", "rb");
|
||||
break;
|
||||
case 1:
|
||||
f_cd_bin = fopen("images/braindead13.bin", "rb");
|
||||
|
||||
@@ -53,7 +53,7 @@ main:
|
||||
move.w #$0100,$303C06 ; File Register
|
||||
move.l #$ffffffff,$303C08 ; Channel Register
|
||||
move.w #$0000,$303C0C ; Audio Channel Register
|
||||
move.l #$09235200,$303C02 ; Timer Register
|
||||
move.l #$00323400,$303C02 ; Timer Register
|
||||
move.w #$C000,$303FFE ; Start the Read by setting bit 15 of the data buffer
|
||||
|
||||
; Usually one would use the DTS and SCR to start playback
|
||||
@@ -135,7 +135,7 @@ video:
|
||||
move.l #$300c,$8000400c ; Memory Address Counter
|
||||
move.w #$484,$8000404a ; Memory Transfer Counter
|
||||
move.b #$04,$80004046 ; SCR, MAC Count Up, DAC No Change (like the CDIC on CH1)
|
||||
move.b #$12,$80004045 ; Dev. to Mem., 16 Bit Words,
|
||||
move.b #$12,$80004045 ; Mem to Dev.., 16 Bit Words,
|
||||
move.b #$30,$80004044 ; ACK/RDY device (like the CDIC on CH1)
|
||||
move.b #$80,$80004047 ; start DMA
|
||||
|
||||
|
||||
Reference in New Issue
Block a user