1
0
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:
sorgelig
2017-01-10 08:36:44 +08:00
parent 0a8088acde
commit 3067b3afe3
5 changed files with 141 additions and 11 deletions

View File

@@ -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),

View File

@@ -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};

View File

@@ -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

View File

@@ -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

View 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