Apple1_MiST/rtl/mist-modules/rgb2ypbpr.v

104 lines
1.9 KiB
Verilog

// Multiplier-based RGB -> YPbPr conversion
// Copyright 2020/2021 by Alastair M. Robinson
module RGBtoYPbPr
(
input clk,
input ena,
input [WIDTH-1:0] red_in,
input [WIDTH-1:0] green_in,
input [WIDTH-1:0] blue_in,
input hs_in,
input vs_in,
input cs_in,
input pixel_in,
output [WIDTH-1:0] red_out,
output [WIDTH-1:0] green_out,
output [WIDTH-1:0] blue_out,
output reg hs_out,
output reg vs_out,
output reg cs_out,
output reg pixel_out
);
parameter WIDTH = 8;
reg [8+WIDTH-1:0] r_y;
reg [8+WIDTH-1:0] g_y;
reg [8+WIDTH-1:0] b_y;
reg [8+WIDTH-1:0] r_b;
reg [8+WIDTH-1:0] g_b;
reg [8+WIDTH-1:0] b_b;
reg [8+WIDTH-1:0] r_r;
reg [8+WIDTH-1:0] g_r;
reg [8+WIDTH-1:0] b_r;
reg [8+WIDTH-1:0] y;
reg [8+WIDTH-1:0] b;
reg [8+WIDTH-1:0] r;
reg hs_d;
reg vs_d;
reg cs_d;
reg pixel_d;
assign red_out = r[8+WIDTH-1:8];
assign green_out = y[8+WIDTH-1:8];
assign blue_out = b[8+WIDTH-1:8];
// Multiply in the first stage...
always @(posedge clk) begin
hs_d <= hs_in; // Register sync, pixel clock, etc
vs_d <= vs_in; // so they're delayed the same amount as the incoming video
cs_d <= cs_in;
pixel_d <= pixel_in;
if(ena) begin
// (Y = 0.299*R + 0.587*G + 0.114*B)
r_y <= red_in * 8'd76;
g_y <= green_in * 8'd150;
b_y <= blue_in * 8'd29;
// (Pb = -0.169*R - 0.331*G + 0.500*B)
r_b <= red_in * 8'd43;
g_b <= green_in * 8'd84;
b_b <= blue_in * 8'd128;
// (Pr = 0.500*R - 0.419*G - 0.081*B)
r_r <= red_in * 8'd128;
g_r <= green_in * 8'd107;
b_r <= blue_in * 8'd20;
end else begin
r_r[8+WIDTH-1:8] <= red_in; // Passthrough
g_y[8+WIDTH-1:8] <= green_in;
b_b[8+WIDTH-1:8] <= blue_in;
end
end
// Second stage - adding
always @(posedge clk) begin
hs_out <= hs_d;
vs_out <= vs_d;
cs_out <= cs_d;
pixel_out <= pixel_d;
if(ena) begin
y <= r_y + g_y + b_y;
b <= 2'd2**(8+WIDTH-1) + b_b - r_b - g_b;
r <= 2'd2**(8+WIDTH-1) + r_r - g_r - b_r;
end else begin
y <= g_y; // Passthrough
b <= b_b;
r <= r_r;
end
end
endmodule