mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-07 08:27:07 +00:00
[NES] Add support for YPbPr video.
This commit is contained in:
@@ -175,6 +175,7 @@ wire palette2_osd = status[5];
|
||||
wire reset_osd = status[6];
|
||||
|
||||
wire scandoubler_disable;
|
||||
wire ypbpr;
|
||||
wire ps2_kbd_clk, ps2_kbd_data;
|
||||
|
||||
|
||||
@@ -190,6 +191,7 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io(
|
||||
.switches(switches),
|
||||
.buttons(buttons),
|
||||
.scandoubler_disable(scandoubler_disable),
|
||||
.ypbpr(ypbpr),
|
||||
|
||||
.joystick_0(joyA),
|
||||
.joystick_1(joyB),
|
||||
@@ -407,6 +409,7 @@ video video (
|
||||
.count_v(scanline),
|
||||
.count_h(cycle),
|
||||
.mode(scandoubler_disable),
|
||||
.ypbpr(ypbpr),
|
||||
.smoothing(!smoothing_osd),
|
||||
.scanlines(scanlines_osd),
|
||||
.overscan(overscan_osd),
|
||||
|
||||
@@ -37,6 +37,7 @@ module user_io #(parameter STRLEN=0) (
|
||||
output [1:0] buttons,
|
||||
output [1:0] switches,
|
||||
output scandoubler_disable,
|
||||
output ypbpr,
|
||||
|
||||
output reg [7:0] status,
|
||||
|
||||
@@ -79,6 +80,7 @@ assign sd_mounted = mount_strobe;
|
||||
assign buttons = but_sw[1:0];
|
||||
assign switches = but_sw[3:2];
|
||||
assign scandoubler_disable = but_sw[4];
|
||||
assign ypbpr = but_sw[5];
|
||||
|
||||
wire [7:0] dout = { sbuf, SPI_DI};
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@ set_global_assignment -name VERILOG_FILE src/compat.v
|
||||
set_global_assignment -name VERILOG_FILE src/ppu.v
|
||||
set_global_assignment -name VERILOG_FILE src/mmu.v
|
||||
set_global_assignment -name VERILOG_FILE src/cpu.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE src/video_mixer.sv
|
||||
set_global_assignment -name VERILOG_FILE src/video.v
|
||||
set_global_assignment -name VERILOG_FILE src/nes.v
|
||||
set_global_assignment -name VERILOG_FILE src/MicroCode.v
|
||||
|
||||
@@ -7,6 +7,7 @@ module video(
|
||||
input [8:0] count_h,
|
||||
input [8:0] count_v,
|
||||
input mode,
|
||||
input ypbpr,
|
||||
input smoothing,
|
||||
input scanlines,
|
||||
input overscan,
|
||||
@@ -18,8 +19,8 @@ module video(
|
||||
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
|
||||
output osd_visible
|
||||
@@ -29,6 +30,8 @@ reg clk2 = 1'b0;
|
||||
always @(posedge clk) clk2 <= ~clk2;
|
||||
wire clkv = mode ? clk2 : clk;
|
||||
|
||||
wire [5:0] R_out, G_out, B_out;
|
||||
|
||||
osd #(10'd0, 10'd0, 3'd4) osd (
|
||||
.pclk(clkv),
|
||||
|
||||
@@ -36,16 +39,16 @@ osd #(10'd0, 10'd0, 3'd4) osd (
|
||||
.sdi(sdi),
|
||||
.ss(ss),
|
||||
|
||||
.red_in ({vga_r, 1'b0}),
|
||||
.green_in({vga_g, 1'b0}),
|
||||
.blue_in ({vga_b, 1'b0}),
|
||||
.red_in ({vga_r, vga_r[4]}),
|
||||
.green_in({vga_g, vga_g[4]}),
|
||||
.blue_in ({vga_b, vga_b[4]}),
|
||||
.hs_in(sync_h),
|
||||
.vs_in(sync_v),
|
||||
|
||||
.red_out(VGA_R),
|
||||
.green_out(VGA_G),
|
||||
.blue_out(VGA_B),
|
||||
|
||||
.red_out(R_out),
|
||||
.green_out(G_out),
|
||||
.blue_out(B_out),
|
||||
|
||||
.osd_enable(osd_visible)
|
||||
);
|
||||
|
||||
@@ -103,7 +106,30 @@ wire [4:0] vga_g = ol ? {4'b0, pixel_v[9:9]} : (darker ? {1'b0, pixel_v[9:6
|
||||
wire [4:0] vga_b = ol ? {4'b0, pixel_v[14:14]} : (darker ? {1'b0, pixel_v[14:11]} : pixel_v[14:10]);
|
||||
wire sync_h = ((h >= (512 + 23 + (mode ? 18 : 35))) && (h < (512 + 23 + (mode ? 18 : 35) + 82)));
|
||||
wire sync_v = ((v >= (mode ? 240 + 5 : 480 + 10)) && (v < (mode ? 240 + 14 : 480 + 12)));
|
||||
assign VGA_HS = mode ? ~(sync_h ^ sync_v) : ~sync_h;
|
||||
assign VGA_VS = mode ? 1'b1 : ~sync_v;
|
||||
|
||||
video_mixer video_mixer
|
||||
(
|
||||
.scandoubler_disable(mode),
|
||||
.ypbpr(ypbpr),
|
||||
.ypbpr_full(1),
|
||||
|
||||
.r_i({R_out, R_out[5:4]}),
|
||||
.g_i({G_out, G_out[5:4]}),
|
||||
.b_i({B_out, B_out[5:4]}),
|
||||
.hsync_i(sync_h),
|
||||
.vsync_i(sync_v),
|
||||
|
||||
.r_p({R_out, R_out[5:4]}),
|
||||
.g_p({G_out, G_out[5:4]}),
|
||||
.b_p({B_out, B_out[5:4]}),
|
||||
.hsync_p(sync_h),
|
||||
.vsync_p(sync_v),
|
||||
|
||||
.VGA_HS(VGA_HS),
|
||||
.VGA_VS(VGA_VS),
|
||||
.VGA_R(VGA_R),
|
||||
.VGA_G(VGA_G),
|
||||
.VGA_B(VGA_B)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
98
cores/nes/src/video_mixer.sv
Normal file
98
cores/nes/src/video_mixer.sv
Normal file
@@ -0,0 +1,98 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// Core should provide as much color resolution as possible with normalized 0-255 range
|
||||
// this module will reduce color resolution to 6 bits only at final stage.
|
||||
|
||||
module video_mixer
|
||||
(
|
||||
// 0 = HVSync 31KHz, 1 = CSync 15KHz
|
||||
input scandoubler_disable,
|
||||
|
||||
// YPbPr always uses composite sync
|
||||
input ypbpr,
|
||||
|
||||
// 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space)
|
||||
input ypbpr_full,
|
||||
|
||||
// interlace (15khz) color
|
||||
input [7:0] r_i,
|
||||
input [7:0] g_i,
|
||||
input [7:0] b_i,
|
||||
|
||||
// interlace sync. Positive pulses.
|
||||
input hsync_i,
|
||||
input vsync_i,
|
||||
|
||||
// progressive (31khz) color
|
||||
input [7:0] r_p,
|
||||
input [7:0] g_p,
|
||||
input [7:0] b_p,
|
||||
|
||||
// progressive sync. Positive pulses.
|
||||
input hsync_p,
|
||||
input vsync_p,
|
||||
|
||||
// MiST video output signals
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
output VGA_VS,
|
||||
output VGA_HS
|
||||
);
|
||||
|
||||
wire [7:0] red = scandoubler_disable ? r_i : r_p;
|
||||
wire [7:0] green = scandoubler_disable ? g_i : g_p;
|
||||
wire [7:0] blue = scandoubler_disable ? b_i : b_p;
|
||||
|
||||
wire [5:0] yuv_full[225] = '{
|
||||
6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1,
|
||||
6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4,
|
||||
6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6,
|
||||
6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8,
|
||||
6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11,
|
||||
6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13,
|
||||
6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15,
|
||||
6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17,
|
||||
6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20,
|
||||
6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22,
|
||||
6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24,
|
||||
6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27,
|
||||
6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29,
|
||||
6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31,
|
||||
6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33,
|
||||
6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36,
|
||||
6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38,
|
||||
6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40,
|
||||
6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42,
|
||||
6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45,
|
||||
6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47,
|
||||
6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49,
|
||||
6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52,
|
||||
6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54,
|
||||
6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56,
|
||||
6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58,
|
||||
6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61,
|
||||
6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63,
|
||||
6'd63
|
||||
};
|
||||
|
||||
// http://marsee101.blog19.fc2.com/blog-entry-2311.html
|
||||
// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B)
|
||||
// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B)
|
||||
// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B)
|
||||
|
||||
wire [18:0] y_8 = 19'd04096 + ({red, 6'd0} + {red, 1'd0}) + ({green, 7'd0} + {green}) + ({blue, 4'd0} + {blue, 3'd0} + {blue});
|
||||
wire [18:0] pb_8 = 19'd32768 - ({red, 5'd0} + {red, 2'd0} + {red, 1'd0}) - ({green, 6'd0} + {green, 3'd0} + {green, 1'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 4'd0});
|
||||
wire [18:0] pr_8 = 19'd32768 + ({red, 6'd0} + {red, 5'd0} + {red, 4'd0}) - ({green, 6'd0} + {green, 4'd0} + {green, 3'd0} + {green, 2'd0} + {green, 1'd0}) - ({blue, 4'd0} + {blue , 1'd0});
|
||||
|
||||
wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8];
|
||||
wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8];
|
||||
wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8];
|
||||
|
||||
assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red[7:2];
|
||||
assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green[7:2];
|
||||
assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue[7:2];
|
||||
assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vsync_p;
|
||||
assign VGA_HS = scandoubler_disable ? ~(hsync_i ^ vsync_i) : ypbpr ? ~(hsync_p ^ vsync_p) : ~hsync_p;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user