2020-01-21 16:55:46 +00:00
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// Copyright (C) 2017-2020 Sorgelig
|
|
|
|
//
|
2021-01-23 12:09:42 +00:00
|
|
|
// This program is free software; you can redistribute it and/or modify it
|
|
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
// any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
// more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License along
|
|
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
//
|
2020-01-21 16:55:46 +00:00
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
// DW:
|
|
|
|
// 6 : 2R 2G 2B
|
|
|
|
// 8 : 3R 3G 2B
|
|
|
|
// 9 : 3R 3G 3B
|
|
|
|
// 12 : 4R 4G 4B
|
|
|
|
// 24 : 8R 8G 8B
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
module arcade_video #(parameter WIDTH=320, DW=8, GAMMA=1)
|
2020-01-21 16:55:46 +00:00
|
|
|
(
|
|
|
|
input clk_video,
|
|
|
|
input ce_pix,
|
|
|
|
|
|
|
|
input[DW-1:0] RGB_in,
|
|
|
|
input HBlank,
|
|
|
|
input VBlank,
|
|
|
|
input HSync,
|
|
|
|
input VSync,
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
output CLK_VIDEO,
|
|
|
|
output CE_PIXEL,
|
2020-01-21 16:55:46 +00:00
|
|
|
output [7:0] VGA_R,
|
|
|
|
output [7:0] VGA_G,
|
|
|
|
output [7:0] VGA_B,
|
|
|
|
output VGA_HS,
|
|
|
|
output VGA_VS,
|
|
|
|
output VGA_DE,
|
2021-01-23 12:09:42 +00:00
|
|
|
output [1:0] VGA_SL,
|
2020-01-21 16:55:46 +00:00
|
|
|
|
|
|
|
input [2:0] fx,
|
|
|
|
input forced_scandoubler,
|
|
|
|
inout [21:0] gamma_bus
|
|
|
|
);
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
assign CLK_VIDEO = clk_video;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
wire hs_fix,vs_fix;
|
|
|
|
sync_fix sync_v(CLK_VIDEO, HSync, hs_fix);
|
|
|
|
sync_fix sync_h(CLK_VIDEO, VSync, vs_fix);
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
reg [DW-1:0] RGB_fix;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
reg CE,HS,VS,HBL,VBL;
|
|
|
|
always @(posedge CLK_VIDEO) begin
|
|
|
|
reg old_ce;
|
|
|
|
old_ce <= ce_pix;
|
|
|
|
CE <= 0;
|
|
|
|
if(~old_ce & ce_pix) begin
|
|
|
|
CE <= 1;
|
|
|
|
HS <= hs_fix;
|
|
|
|
if(~HS & hs_fix) VS <= vs_fix;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
RGB_fix <= RGB_in;
|
|
|
|
HBL <= HBlank;
|
|
|
|
if(HBL & ~HBlank) VBL <= VBlank;
|
|
|
|
end
|
|
|
|
end
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
wire [7:0] R,G,B;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
|
|
|
generate
|
|
|
|
if(DW == 6) begin
|
2021-01-23 12:09:42 +00:00
|
|
|
assign R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]};
|
|
|
|
assign G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]};
|
|
|
|
assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
else if(DW == 8) begin
|
2021-01-23 12:09:42 +00:00
|
|
|
assign R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]};
|
|
|
|
assign G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]};
|
|
|
|
assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
else if(DW == 9) begin
|
2021-01-23 12:09:42 +00:00
|
|
|
assign R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]};
|
|
|
|
assign G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]};
|
|
|
|
assign B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
else if(DW == 12) begin
|
2021-01-23 12:09:42 +00:00
|
|
|
assign R = {RGB_fix[11:8],RGB_fix[11:8]};
|
|
|
|
assign G = {RGB_fix[7:4],RGB_fix[7:4]};
|
|
|
|
assign B = {RGB_fix[3:0],RGB_fix[3:0]};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
else begin // 24
|
2021-01-23 12:09:42 +00:00
|
|
|
assign R = RGB_fix[23:16];
|
|
|
|
assign G = RGB_fix[15:8];
|
|
|
|
assign B = RGB_fix[7:0];
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
assign VGA_SL = sl[1:0];
|
2020-01-21 16:55:46 +00:00
|
|
|
wire [2:0] sl = fx ? fx - 1'd1 : 3'd0;
|
|
|
|
wire scandoubler = fx || forced_scandoubler;
|
|
|
|
|
|
|
|
video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer
|
|
|
|
(
|
2021-03-03 09:35:46 +00:00
|
|
|
.CLK_VIDEO(CLK_VIDEO),
|
2021-01-23 12:09:42 +00:00
|
|
|
.ce_pix(CE),
|
2021-03-03 09:35:46 +00:00
|
|
|
.CE_PIXEL(CE_PIXEL),
|
2020-01-21 16:55:46 +00:00
|
|
|
|
|
|
|
.scandoubler(scandoubler),
|
|
|
|
.hq2x(fx==1),
|
|
|
|
.gamma_bus(gamma_bus),
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
.R((DW!=24) ? R[7:4] : R),
|
|
|
|
.G((DW!=24) ? G[7:4] : G),
|
|
|
|
.B((DW!=24) ? B[7:4] : B),
|
|
|
|
|
|
|
|
.HSync (HS),
|
|
|
|
.VSync (VS),
|
|
|
|
.HBlank(HBL),
|
|
|
|
.VBlank(VBL),
|
|
|
|
|
|
|
|
.VGA_R(VGA_R),
|
|
|
|
.VGA_G(VGA_G),
|
|
|
|
.VGA_B(VGA_B),
|
|
|
|
.VGA_VS(VGA_VS),
|
|
|
|
.VGA_HS(VGA_HS),
|
|
|
|
.VGA_DE(VGA_DE)
|
2020-01-21 16:55:46 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// Screen +90/-90 deg. rotation
|
2021-01-23 12:09:42 +00:00
|
|
|
// Copyright (C) 2020 Sorgelig
|
2020-01-21 16:55:46 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify it
|
|
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
// any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
// more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License along
|
|
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2021-01-23 12:09:42 +00:00
|
|
|
//
|
2020-01-21 16:55:46 +00:00
|
|
|
//============================================================================
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
module screen_rotate
|
2020-01-21 16:55:46 +00:00
|
|
|
(
|
2021-01-23 12:09:42 +00:00
|
|
|
input CLK_VIDEO,
|
|
|
|
input CE_PIXEL,
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
input [7:0] VGA_R,
|
|
|
|
input [7:0] VGA_G,
|
|
|
|
input [7:0] VGA_B,
|
|
|
|
input VGA_HS,
|
|
|
|
input VGA_VS,
|
|
|
|
input VGA_DE,
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
input rotate_ccw,
|
|
|
|
input no_rotate,
|
2022-03-07 09:07:01 +00:00
|
|
|
input flip,
|
|
|
|
output video_rotated,
|
|
|
|
|
|
|
|
output FB_EN,
|
|
|
|
output [4:0] FB_FORMAT,
|
|
|
|
output reg [11:0] FB_WIDTH,
|
|
|
|
output reg [11:0] FB_HEIGHT,
|
|
|
|
output [31:0] FB_BASE,
|
|
|
|
output [13:0] FB_STRIDE,
|
|
|
|
input FB_VBL,
|
|
|
|
input FB_LL,
|
2021-01-23 12:09:42 +00:00
|
|
|
|
|
|
|
output DDRAM_CLK,
|
|
|
|
input DDRAM_BUSY,
|
|
|
|
output [7:0] DDRAM_BURSTCNT,
|
|
|
|
output [28:0] DDRAM_ADDR,
|
|
|
|
output [63:0] DDRAM_DIN,
|
|
|
|
output [7:0] DDRAM_BE,
|
|
|
|
output DDRAM_WE,
|
|
|
|
output DDRAM_RD
|
2020-01-21 16:55:46 +00:00
|
|
|
);
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB
|
|
|
|
|
2022-03-07 09:07:01 +00:00
|
|
|
reg do_flip;
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
assign DDRAM_CLK = CLK_VIDEO;
|
|
|
|
assign DDRAM_BURSTCNT = 1;
|
|
|
|
assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]};
|
|
|
|
assign DDRAM_BE = ram_addr[2] ? 8'hF0 : 8'h0F;
|
|
|
|
assign DDRAM_DIN = {ram_data,ram_data};
|
|
|
|
assign DDRAM_WE = ram_wr;
|
|
|
|
assign DDRAM_RD = 0;
|
|
|
|
|
|
|
|
assign FB_EN = fb_en[2];
|
|
|
|
assign FB_FORMAT = 5'b00110;
|
|
|
|
assign FB_BASE = {MEM_BASE,o_fb,23'd0};
|
|
|
|
assign FB_STRIDE = stride;
|
|
|
|
|
|
|
|
function [1:0] buf_next;
|
|
|
|
input [1:0] a,b;
|
|
|
|
begin
|
|
|
|
buf_next = 1;
|
|
|
|
if ((a==0 && b==1) || (a==1 && b==0)) buf_next = 2;
|
|
|
|
if ((a==1 && b==2) || (a==2 && b==1)) buf_next = 0;
|
|
|
|
end
|
|
|
|
endfunction
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2022-03-07 09:07:01 +00:00
|
|
|
assign video_rotated = ~no_rotate;
|
|
|
|
|
|
|
|
always @(posedge CLK_VIDEO) begin
|
|
|
|
do_flip <= no_rotate && flip;
|
|
|
|
if( do_flip ) begin
|
|
|
|
FB_WIDTH <= hsz;
|
|
|
|
FB_HEIGHT <= vsz;
|
|
|
|
end else begin
|
|
|
|
FB_WIDTH <= vsz;
|
|
|
|
FB_HEIGHT <= hsz;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
reg [1:0] i_fb,o_fb;
|
|
|
|
always @(posedge CLK_VIDEO) begin
|
|
|
|
reg old_vbl,old_vs;
|
|
|
|
old_vbl <= FB_VBL;
|
|
|
|
old_vs <= VGA_VS;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
if(FB_LL) begin
|
|
|
|
if(~old_vbl & FB_VBL) o_fb<={1'b0,~i_fb[0]};
|
|
|
|
if(~old_vs & VGA_VS) i_fb<={1'b0,~i_fb[0]};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
2021-01-23 12:09:42 +00:00
|
|
|
else begin
|
|
|
|
if(~old_vbl & FB_VBL) o_fb<=buf_next(o_fb,i_fb);
|
|
|
|
if(~old_vs & VGA_VS) i_fb<=buf_next(i_fb,o_fb);
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
2021-01-23 12:09:42 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
initial begin
|
|
|
|
fb_en = 0;
|
|
|
|
end
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
reg [2:0] fb_en = 0;
|
|
|
|
reg [11:0] hsz = 320, vsz = 240;
|
|
|
|
reg [11:0] bwidth;
|
|
|
|
reg [22:0] bufsize;
|
|
|
|
always @(posedge CLK_VIDEO) begin
|
|
|
|
reg [11:0] hcnt = 0, vcnt = 0;
|
|
|
|
reg old_vs, old_de;
|
|
|
|
|
|
|
|
if(CE_PIXEL) begin
|
|
|
|
old_vs <= VGA_VS;
|
|
|
|
old_de <= VGA_DE;
|
2022-03-07 09:07:01 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
hcnt <= hcnt + 1'd1;
|
|
|
|
if(~old_de & VGA_DE) begin
|
|
|
|
hcnt <= 1;
|
|
|
|
vcnt <= vcnt + 1'd1;
|
|
|
|
end
|
2022-03-07 09:07:01 +00:00
|
|
|
if(old_de & ~VGA_DE) begin
|
|
|
|
hsz <= hcnt;
|
|
|
|
if( do_flip ) bwidth <= hcnt + 2'd3;
|
|
|
|
end
|
2021-01-23 12:09:42 +00:00
|
|
|
if(~old_vs & VGA_VS) begin
|
|
|
|
vsz <= vcnt;
|
2022-03-07 09:07:01 +00:00
|
|
|
if( !do_flip ) bwidth <= vcnt + 2'd3;
|
2021-01-23 12:09:42 +00:00
|
|
|
vcnt <= 0;
|
2022-03-07 09:07:01 +00:00
|
|
|
fb_en <= {fb_en[1:0], ~no_rotate | flip};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
2022-03-07 09:07:01 +00:00
|
|
|
if(old_vs & ~VGA_VS) bufsize <= (do_flip ? vsz : hsz ) * stride;
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
wire [13:0] stride = {bwidth[11:2], 4'd0};
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
reg [22:0] ram_addr, next_addr;
|
|
|
|
reg [31:0] ram_data;
|
|
|
|
reg ram_wr;
|
|
|
|
always @(posedge CLK_VIDEO) begin
|
|
|
|
reg [13:0] hcnt = 0;
|
|
|
|
reg old_vs, old_de;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
ram_wr <= 0;
|
2022-03-07 09:07:01 +00:00
|
|
|
if(CE_PIXEL && FB_EN) begin
|
2021-01-23 12:09:42 +00:00
|
|
|
old_vs <= VGA_VS;
|
|
|
|
old_de <= VGA_DE;
|
2020-01-21 16:55:46 +00:00
|
|
|
|
2021-01-23 12:09:42 +00:00
|
|
|
if(~old_vs & VGA_VS) begin
|
2022-03-07 09:07:01 +00:00
|
|
|
next_addr <=
|
|
|
|
do_flip ? bufsize-3'd4 :
|
|
|
|
rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
|
2021-01-23 12:09:42 +00:00
|
|
|
hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00};
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
2021-01-23 12:09:42 +00:00
|
|
|
if(VGA_DE) begin
|
|
|
|
ram_wr <= 1;
|
2022-03-07 09:07:01 +00:00
|
|
|
ram_data <= {8'd0,VGA_B,VGA_G,VGA_R};
|
2021-01-23 12:09:42 +00:00
|
|
|
ram_addr <= next_addr;
|
2022-03-07 09:07:01 +00:00
|
|
|
next_addr <=
|
|
|
|
do_flip ? next_addr-3'd4 :
|
|
|
|
rotate_ccw ? (next_addr - stride) : (next_addr + stride);
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
2022-03-07 09:07:01 +00:00
|
|
|
if(old_de & ~VGA_DE & ~do_flip) begin
|
2021-01-23 12:09:42 +00:00
|
|
|
next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt;
|
|
|
|
hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4);
|
2020-01-21 16:55:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule
|