Update sys.

This commit is contained in:
Sorgelig
2022-02-02 02:56:56 +08:00
parent e1bc579664
commit de030c679d
7 changed files with 396 additions and 126 deletions

View File

@@ -28,7 +28,7 @@ module emu
input RESET,
//Must be passed to hps_io module
inout [45:0] HPS_BUS,
inout [48:0] HPS_BUS,
//Base video clock. Usually equals to CLK_SYS.
output CLK_VIDEO,
@@ -927,7 +927,7 @@ always @(posedge CLK_VIDEO) if (ce_pix) begin
vbl <= VBlank;
casex({ulap_ena, ulap_mono})
'b0X: {Gx,Rx,Bx} <= {G, {3{I & G}}, G, {3{I & G}}, R, {3{I & R}}, R, {3{I & R}}, B, {3{I & B}}, B, {3{I & B}}};
'b0X: {Gx,Rx,Bx} <= {G, G, {6{I & G}}, R, R, {6{I & R}}, B, B, {6{I & B}}};
'b10: {Gx,Rx,Bx} <= {{2{ulap_color[7:5]}}, ulap_color[7:6], {2{ulap_color[4:2]}}, ulap_color[4:3], {4{ulap_color[1:0]}}};
'b11: {Gx,Rx,Bx} <= {3{ulap_color}};
endcase

View File

@@ -174,15 +174,16 @@ module screen_rotate
input rotate_ccw,
input no_rotate,
input flip,
output FB_EN,
output [4:0] FB_FORMAT,
output [11:0] FB_WIDTH,
output [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
output [13:0] FB_STRIDE,
input FB_VBL,
input FB_LL,
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,
output DDRAM_CLK,
input DDRAM_BUSY,
@@ -196,6 +197,8 @@ module screen_rotate
parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB
reg do_flip;
assign DDRAM_CLK = CLK_VIDEO;
assign DDRAM_BURSTCNT = 1;
assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]};
@@ -207,8 +210,6 @@ 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_WIDTH = vsz;
assign FB_HEIGHT = hsz;
assign FB_STRIDE = stride;
function [1:0] buf_next;
@@ -220,6 +221,17 @@ function [1:0] buf_next;
end
endfunction
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
reg [1:0] i_fb,o_fb;
always @(posedge CLK_VIDEO) begin
reg old_vbl,old_vs;
@@ -251,20 +263,23 @@ always @(posedge CLK_VIDEO) begin
if(CE_PIXEL) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
hcnt <= hcnt + 1'd1;
if(~old_de & VGA_DE) begin
hcnt <= 1;
vcnt <= vcnt + 1'd1;
end
if(old_de & ~VGA_DE) hsz <= hcnt;
if(old_de & ~VGA_DE) begin
hsz <= hcnt;
if( do_flip ) bwidth <= hcnt + 2'd3;
end
if(~old_vs & VGA_VS) begin
vsz <= vcnt;
bwidth <= vcnt + 2'd3;
if( !do_flip ) bwidth <= vcnt + 2'd3;
vcnt <= 0;
fb_en <= {fb_en[1:0], ~no_rotate};
fb_en <= {fb_en[1:0], ~no_rotate | flip};
end
if(old_vs & ~VGA_VS) bufsize <= hsz * stride;
if(old_vs & ~VGA_VS) bufsize <= (do_flip ? vsz : hsz ) * stride;
end
end
@@ -278,21 +293,25 @@ always @(posedge CLK_VIDEO) begin
reg old_vs, old_de;
ram_wr <= 0;
if(CE_PIXEL) begin
if(CE_PIXEL && FB_EN) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
if(~old_vs & VGA_VS) begin
next_addr <= rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
next_addr <=
do_flip ? bufsize-3'd4 :
rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00};
end
if(VGA_DE) begin
ram_wr <= 1;
ram_data <= {VGA_B,VGA_G,VGA_R};
ram_data <= {8'd0,VGA_B,VGA_G,VGA_R};
ram_addr <= next_addr;
next_addr <= rotate_ccw ? (next_addr - stride) : (next_addr + stride);
next_addr <=
do_flip ? next_addr-3'd4 :
rotate_ccw ? (next_addr - stride) : (next_addr + stride);
end
if(old_de & ~VGA_DE) begin
if(old_de & ~VGA_DE & ~do_flip) begin
next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt;
hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4);
end

View File

@@ -151,6 +151,7 @@ ENTITY ascal IS
o_vs : OUT std_logic; -- V sync
o_de : OUT std_logic; -- Display Enable
o_vbl : OUT std_logic; -- V blank
o_brd : OUT std_logic; -- border enable
o_ce : IN std_logic; -- Clock Enable
o_clk : IN std_logic; -- Output clock
@@ -458,6 +459,7 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1;
SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 5);
SIGNAL o_hsp,o_vss : std_logic;
SIGNAL o_vcarrym,o_prim : boolean;
SIGNAL o_read,o_read_pre : std_logic;
SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2;
SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31;
@@ -485,6 +487,7 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_divstart : std_logic;
SIGNAL o_divrun : std_logic;
SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0);
SIGNAL o_vacptl : unsigned(1 DOWNTO 0);
-----------------------------------------------------------------------------
FUNCTION shift_ishift(shift : unsigned(0 TO 119);
@@ -705,8 +708,10 @@ ARCHITECTURE rtl OF ascal IS
RETURN x;
END FUNCTION;
SIGNAL o_h_frac2,o_v_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix;
SIGNAL o_h_near_pix,o_v_near_pix : type_pix;
-----------------------------------------------------------------------------
-- Nearest + Bilinear + Sharp Bilinear
@@ -718,6 +723,7 @@ ARCHITECTURE rtl OF ascal IS
TYPE type_bil_t IS RECORD
r,g,b : unsigned(8+FRAC DOWNTO 0);
END RECORD;
FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0);
p : arr_pix(0 TO 3)) RETURN type_bil_t IS
VARIABLE fp,fn : unsigned(FRAC DOWNTO 0);
@@ -725,7 +731,7 @@ ARCHITECTURE rtl OF ascal IS
VARIABLE x : type_bil_t;
CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0');
BEGIN
fp:='0' & f;
fp:=('0' & f) + (Z & f(FRAC-1));
fn:=('1' & Z) - fp;
u:=p(2).r * fp + p(1).r * fn;
x.r:=u;
@@ -735,7 +741,27 @@ ARCHITECTURE rtl OF ascal IS
x.b:=u;
RETURN x;
END FUNCTION;
FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0);
p : arr_pix(0 TO 3)) RETURN type_bil_t IS
VARIABLE fp,fn : unsigned(FRAC DOWNTO 0);
VARIABLE u : unsigned(8+FRAC DOWNTO 0);
VARIABLE x : type_bil_t;
CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0');
BEGIN
IF f(FRAC-1)='0' THEN
x.r := '0' & p(1).r & Z;
x.g := '0' & p(1).g & Z;
x.b := '0' & p(1).b & Z;
ELSE
x.r := '0' & p(2).r & Z;
x.g := '0' & p(2).g & Z;
x.b := '0' & p(2).b & Z;
END IF;
RETURN x;
END FUNCTION;
SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t;
SIGNAL o_h_near_t,o_v_near_t : type_bil_t;
SIGNAL i_h_bil_t : type_bil_t;
-----------------------------------------------------------------------------
@@ -1864,35 +1890,51 @@ BEGIN
o_state<=sHSYNC;
o_hsp<='0';
END IF;
o_prim<=true;
o_vcarrym<=false;
--------------------------------------------------
WHEN sHSYNC =>
dif_v:=(o_vacc_next - 2*o_vsize + 16384) MOD 16384;
dif_v :=(o_vacc_next - 2*o_vsize + 16384) MOD 16384;
IF o_prim THEN
IF dif_v>=8192 THEN
o_vacc <=o_vacc_next;
ELSE
o_vacc <=dif_v;
END IF;
END IF;
IF dif_v>=8192 THEN
o_vacc <=o_vacc_next;
o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192;
vcarry_v:=false;
ELSE
o_vacc <=dif_v;
o_vacc_next<=(dif_v + 2*o_ivsize + 8192) MOD 8192;
o_vacc_next<=dif_v;
vcarry_v:=true;
END IF;
o_divstart<='1';
IF o_vcpt_pre2=o_vmin THEN
o_vacc <=o_vacc_ini;
o_vacc_next<=o_vacc_ini + 2*o_ivsize;
o_vacpt<=x"001";
o_vacpt <=x"001";
o_vacptl<="01";
vcarry_v:=false;
END IF;
IF vcarry_v THEN
o_vacpt<=o_vacpt+1;
END IF;
IF vcarry_v AND o_prim THEN
o_vacptl<=o_vacptl+1;
END IF;
o_vcarrym <= o_vcarrym OR vcarry_v;
o_prim <= false;
o_hbcpt<=0; -- Clear burst counter on line
IF (o_vpe='1' AND vcarry_v) OR o_fload>0 THEN
o_state<=sREAD;
ELSE
o_state<=sDISP;
o_divstart<=to_std_logic(NOT vcarry_v);
IF NOT vcarry_v OR o_fload>0 THEN
IF (o_vpe='1' AND o_vcarrym) OR o_fload>0 THEN
o_state<=sREAD;
ELSE
o_state<=sDISP;
END IF;
END IF;
WHEN sREAD =>
@@ -1942,7 +1984,7 @@ BEGIN
o_alt<="0100";
ELSE
o_adrs<=to_unsigned(o_adrs_pre + (o_hbcpt * N_BURST),32);
o_alt<=altx(o_vacpt(1 DOWNTO 0) + 1);
o_alt<=altx(o_vacptl + 1);
END IF;
END IF;
@@ -2276,33 +2318,38 @@ BEGIN
o_hpixq<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0);
-- NEAREST / BILINEAR / SHARP BILINEAR ---------------
-- NEAREST -------------------------------------------
-- C2
o_h_near_frac<=near_frac(o_hfrac2);
-- C3
o_h_near_t<=near_calc(o_h_near_frac,o_hpixq);
-- C4 : Nearest
o_h_near_pix.r<=o_h_near_t.r(7+FRAC DOWNTO FRAC);
o_h_near_pix.g<=o_h_near_t.g(7+FRAC DOWNTO FRAC);
o_h_near_pix.b<=o_h_near_t.b(7+FRAC DOWNTO FRAC);
-- BILINEAR / SHARP BILINEAR ---------------
-- C1 : Pre-calc Sharp Bilinear
o_h_sbil_t<=sbil_frac1(o_hfrac1);
-- C2 : Select
o_h_frac2<=(OTHERS =>'0');
CASE o_hmode(1 DOWNTO 0) IS
WHEN "00" => -- Nearest
IF MASK(MASK_NEAREST)='1' THEN
o_h_frac2<=near_frac(o_hfrac2);
END IF;
WHEN "01" => -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
o_h_frac2<=bil_frac(o_hfrac2);
END IF;
WHEN "10" => -- Sharp Bilinear
IF MASK(MASK_SHARP_BILINEAR)='1' THEN
o_h_frac2<=sbil_frac2(o_hfrac2,o_h_sbil_t);
END IF;
WHEN OTHERS =>
NULL;
END CASE;
o_h_bil_frac<=(OTHERS =>'0');
IF o_hmode(0)='1' THEN -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
o_h_bil_frac<=bil_frac(o_hfrac2);
END IF;
ELSE -- Sharp Bilinear
IF MASK(MASK_SHARP_BILINEAR)='1' THEN
o_h_bil_frac<=sbil_frac2(o_hfrac2,o_h_sbil_t);
END IF;
END IF;
-- C3 : Opposite frac
o_h_bil_t<=bil_calc(o_h_frac2,o_hpixq);
o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq);
-- C4 : Nearest / Bilinear / Sharp Bilinear
-- C4 : Bilinear / Sharp Bilinear
o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC);
o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC);
o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC);
@@ -2340,9 +2387,12 @@ BEGIN
o_ldw<=(x"00",x"00",x"00");
CASE o_hmode(2 DOWNTO 0) IS
WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear
IF MASK(MASK_NEAREST)='1' OR
MASK(MASK_BILINEAR)='1' OR
WHEN "000" => -- Nearest
IF MASK(MASK_NEAREST)='1' THEN
o_ldw<=o_h_near_pix;
END IF;
WHEN "001" | "010" => -- Bilinear | Sharp Bilinear
IF MASK(MASK_BILINEAR)='1' OR
MASK(MASK_SHARP_BILINEAR)='1' THEN
o_ldw<=o_h_bil_pix;
END IF;
@@ -2441,7 +2491,7 @@ BEGIN
-- CYCLE 2 -----------------------------------------
-- Lines reordering
CASE o_vacpt(1 DOWNTO 0) IS
CASE o_vacptl IS
WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3);
WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0);
WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1);
@@ -2461,31 +2511,37 @@ BEGIN
o_vpixq1<=o_vpixq;
-- NEAREST / BILINEAR / SHARP BILINEAR -------------
-- NEAREST -----------------------------------------
-- C4
o_v_near_frac<=near_frac(o_vfrac);
-- C5
o_v_near_t<=near_calc(o_v_near_frac,o_vpixq1);
-- C6 : Nearest
o_v_near_pix.r<=o_v_near_t.r(7+FRAC DOWNTO FRAC);
o_v_near_pix.g<=o_v_near_t.g(7+FRAC DOWNTO FRAC);
o_v_near_pix.b<=o_v_near_t.b(7+FRAC DOWNTO FRAC);
-- BILINEAR / SHARP BILINEAR -----------------------
-- C3 : Pre-calc Sharp Bilinear
o_v_sbil_t<=sbil_frac1(o_vfrac);
-- C4 : Select
o_v_frac<=(OTHERS =>'0');
CASE o_vmode(1 DOWNTO 0) IS
WHEN "00" => -- Nearest
IF MASK(MASK_NEAREST)='1' THEN
o_v_frac<=near_frac(o_vfrac);
END IF;
WHEN "01" => -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
o_v_frac<=bil_frac(o_vfrac);
END IF;
WHEN "10" => -- Sharp Bilinear
IF MASK(MASK_SHARP_BILINEAR)='1' THEN
o_v_frac<=sbil_frac2(o_vfrac,o_v_sbil_t);
END IF;
WHEN OTHERS => NULL;
END CASE;
o_v_bil_frac<=(OTHERS =>'0');
IF o_vmode(0)='1' THEN -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
o_v_bil_frac<=bil_frac(o_vfrac);
END IF;
ELSE -- Sharp Bilinear
IF MASK(MASK_SHARP_BILINEAR)='1' THEN
o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t);
END IF;
END IF;
o_v_bil_t<=bil_calc(o_v_frac,o_vpixq1);
o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq1);
-- C6 : Nearest / Bilinear / Sharp Bilinear
-- C6 : Bilinear / Sharp Bilinear
o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC);
o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC);
o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC);
@@ -2524,11 +2580,17 @@ BEGIN
o_r<=x"00";
o_g<=x"00";
o_b<=x"00";
o_brd<= not o_pev(5);
CASE o_vmode(2 DOWNTO 0) IS
WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear
IF MASK(MASK_NEAREST)='1' OR
MASK(MASK_BILINEAR)='1' OR
WHEN "000" => -- Nearest
IF MASK(MASK_NEAREST)='1' THEN
o_r<=o_v_near_pix.r;
o_g<=o_v_near_pix.g;
o_b<=o_v_near_pix.b;
END IF;
WHEN "001" | "010" => -- Bilinear | Sharp Bilinear
IF MASK(MASK_BILINEAR)='1' OR
MASK(MASK_SHARP_BILINEAR)='1' THEN
o_r<=o_v_bil_pix.r;
o_g<=o_v_bil_pix.g;

View File

@@ -24,13 +24,13 @@
// Use buffer to access SD card. It's time-critical part.
//
// WIDE=1 for 16 bit file I/O
// VDNUM 1..4
// VDNUM 1..10
// BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384
//
module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0)
(
input clk_sys,
inout [45:0] HPS_BUS,
inout [48:0] HPS_BUS,
// buttons up to 32
output reg [31:0] joystick_0,
@@ -41,12 +41,19 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [31:0] joystick_5,
// analog -127..+127, Y: [15:8], X: [7:0]
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output reg [15:0] joystick_analog_2,
output reg [15:0] joystick_analog_3,
output reg [15:0] joystick_analog_4,
output reg [15:0] joystick_analog_5,
output reg [15:0] joystick_l_analog_0,
output reg [15:0] joystick_l_analog_1,
output reg [15:0] joystick_l_analog_2,
output reg [15:0] joystick_l_analog_3,
output reg [15:0] joystick_l_analog_4,
output reg [15:0] joystick_l_analog_5,
output reg [15:0] joystick_r_analog_0,
output reg [15:0] joystick_r_analog_1,
output reg [15:0] joystick_r_analog_2,
output reg [15:0] joystick_r_analog_3,
output reg [15:0] joystick_r_analog_4,
output reg [15:0] joystick_r_analog_5,
// paddle 0..255
output reg [7:0] paddle_0,
@@ -104,6 +111,7 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2
output reg [DW:0] ioctl_dout,
output reg ioctl_upload = 0, // signal indicating an active upload
input ioctl_upload_req,
input [DW:0] ioctl_din,
output reg ioctl_rd,
output reg [31:0] ioctl_file_ext,
@@ -250,6 +258,8 @@ always@(posedge clk_sys) begin : uio_block
reg [3:0] stflg = 0;
reg [63:0] status_req;
reg old_status_set = 0;
reg old_upload_req = 0;
reg upload_req = 0;
reg old_info = 0;
reg [7:0] info_n = 0;
reg [15:0] tmp1;
@@ -261,6 +271,9 @@ always@(posedge clk_sys) begin : uio_block
stflg <= stflg + 1'd1;
status_req <= status_in;
end
old_upload_req <= ioctl_upload_req;
if(~old_upload_req & ioctl_upload_req) upload_req <= 1;
old_info <= info_req;
if(~old_info & info_req) info_n <= info;
@@ -303,11 +316,13 @@ always@(posedge clk_sys) begin : uio_block
'h0X17,
'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end
'h29: io_dout <= {4'hA, stflg};
'h2B: io_dout <= 1;
'h2B: io_dout <= {HPS_BUS[48:46],4'b0010};
'h2F: io_dout <= 1;
'h32: io_dout <= gamma_bus[21];
'h36: begin io_dout <= info_n; info_n <= 0; end
'h39: io_dout <= 1;
'h3C: if(upload_req) begin io_dout <= 1; upload_req <= 0; end
'h3E: io_dout <= 1; // shadow mask
endcase
sd_buff_addr <= 0;
@@ -380,17 +395,17 @@ always@(posedge clk_sys) begin : uio_block
io_dout <= sd_buff_din[sdn_ack];
end
// joystick analog
// joystick left analog
'h1a: if(!byte_cnt[MAX_W:2]) begin
case(byte_cnt[1:0])
1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index
2: case(stick_idx)
0: joystick_analog_0 <= io_din;
1: joystick_analog_1 <= io_din;
2: joystick_analog_2 <= io_din;
3: joystick_analog_3 <= io_din;
4: joystick_analog_4 <= io_din;
5: joystick_analog_5 <= io_din;
0: joystick_l_analog_0 <= io_din;
1: joystick_l_analog_1 <= io_din;
2: joystick_l_analog_2 <= io_din;
3: joystick_l_analog_3 <= io_din;
4: joystick_l_analog_4 <= io_din;
5: joystick_l_analog_5 <= io_din;
15: case(pdsp_idx)
0: paddle_0 <= io_din[7:0];
1: paddle_1 <= io_din[7:0];
@@ -409,6 +424,21 @@ always@(posedge clk_sys) begin : uio_block
endcase
end
// joystick right analog
'h3d: if(!byte_cnt[MAX_W:2]) begin
case(byte_cnt[1:0])
1: stick_idx <= io_din[3:0]; // first byte is joystick index
2: case(stick_idx)
0: joystick_r_analog_0 <= io_din;
1: joystick_r_analog_1 <= io_din;
2: joystick_r_analog_2 <= io_din;
3: joystick_r_analog_3 <= io_din;
4: joystick_r_analog_4 <= io_din;
5: joystick_r_analog_5 <= io_din;
endcase
endcase
end
// notify image selection
'h1c: begin
img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1;

136
sys/shadowmask.sv Normal file
View File

@@ -0,0 +1,136 @@
module shadowmask
(
input clk,
input clk_sys,
input cmd_wr,
input [15:0] cmd_in,
input [23:0] din,
input hs_in,vs_in,
input de_in,
input brd_in,
input enable,
output reg [23:0] dout,
output reg hs_out,vs_out,
output reg de_out
);
reg [4:0] hmax;
reg [4:0] vmax;
reg [7:0] mask_idx;
reg mask_2x;
reg mask_rotate;
reg mask_enable;
reg [10:0] mask_lut[256];
always @(posedge clk) begin
reg [4:0] hcount;
reg [4:0] vcount;
reg [3:0] hindex;
reg [3:0] vindex;
reg [4:0] hmax2;
reg [4:0] vmax2;
reg [11:0] pcnt,pde;
reg old_hs, old_vs, old_brd;
reg next_v;
old_hs <= hs_in;
old_vs <= vs_in;
old_brd<= brd_in;
// hcount and vcount counts pixel rows and columns
// hindex and vindex half the value of the counters for double size patterns
// hindex2, vindex2 swap the h and v counters for drawing rotated masks
hindex <= mask_2x ? hcount[4:1] : hcount[3:0];
vindex <= mask_2x ? vcount[4:1] : vcount[3:0];
mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex};
// hmax and vmax store these sizes
// hmax2 and vmax2 swap the values to handle rotation
hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x;
vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x;
pcnt <= pcnt+1'd1;
if(old_brd && ~brd_in) pde <= pcnt-4'd3;
hcount <= hcount+1'b1;
if(hcount == hmax2 || pde == pcnt) hcount <= 0;
if(~old_brd && brd_in) next_v <= 1;
if(old_vs && ~vs_in) vcount <= 0;
if(old_hs && ~hs_in) begin
vcount <= vcount + next_v;
next_v <= 0;
pcnt <= 0;
if (vcount == vmax2) vcount <= 0;
end
end
reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers
always @(posedge clk) begin
reg [10:0] lut;
lut <= mask_lut[mask_idx];
r_mul <= 5'b10000; g_mul <= 5'b10000; b_mul <= 5'b10000; // default 100% to all channels
if (mask_enable) begin
r_mul <= lut[10] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]};
g_mul <= lut[9] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]};
b_mul <= lut[8] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]};
end
end
always @(posedge clk) begin
reg [11:0] vid;
reg [7:0] r1, g1, b1;
reg [7:0] r2, g2, b2;
reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5%
reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100%
reg [8:0] r4, g4, b4;
// C1 - data input
{r1,g1,b1} <= din;
vid <= {vid[8:0],vs_in, hs_in, de_in};
// C2 - relax timings
{r2,g2,b2} <= {r1,g1,b1};
// C3 - perform multiplications
r3_x <= ({4{r_mul[0]}} & r2[7:4]) + ({8{r_mul[1]}} & r2[7:3]);
r3_y <= ({6{r_mul[2]}} & r2[7:2]) + ({7{r_mul[3]}} & r2[7:1]) + ({9{r_mul[4]}} & r2[7:0]);
g3_x <= ({4{g_mul[0]}} & g2[7:4]) + ({8{g_mul[1]}} & g2[7:3]);
g3_y <= ({6{g_mul[2]}} & g2[7:2]) + ({7{g_mul[3]}} & g2[7:1]) + ({9{g_mul[4]}} & g2[7:0]);
b3_x <= ({4{b_mul[0]}} & b2[7:4]) + ({8{b_mul[1]}} & b2[7:3]);
b3_y <= ({6{b_mul[2]}} & b2[7:2]) + ({7{b_mul[3]}} & b2[7:1]) + ({9{b_mul[4]}} & b2[7:0]);
// C4 - combine results
r4 <= r3_x + r3_y;
g4 <= g3_x + g3_y;
b4 <= b3_x + b3_y;
// C5 - clamp and output
dout <= {{8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0]};
{vs_out,hs_out,de_out} <= vid[11:9];
end
// clock in mask commands
always @(posedge clk_sys) begin
reg m_enable;
reg [7:0] idx;
if (cmd_wr) begin
case(cmd_in[15:13])
3'b000: begin {m_enable, mask_rotate, mask_2x} <= cmd_in[3:1]; idx <= 0; end
3'b001: vmax <= cmd_in[3:0];
3'b010: hmax <= cmd_in[3:0];
3'b011: begin mask_lut[idx] <= cmd_in[10:0]; idx <= idx + 1'd1; end
endcase
end
mask_enable <= m_enable & enable;
end
endmodule

View File

@@ -7,6 +7,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) m
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) shadowmask.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ]

View File

@@ -295,7 +295,7 @@ reg [31:0] cfg_custom_p2;
reg [4:0] vol_att;
initial vol_att = 5'b11111;
reg [6:0] coef_addr;
reg [8:0] coef_addr;
reg [8:0] coef_data;
reg coef_wr = 0;
@@ -336,6 +336,10 @@ always@(posedge clk_sys) begin
old_strobe <= io_strobe;
coef_wr <= 0;
`ifndef MISTER_DEBUG_NOHDMI
shadowmask_wr <= 0;
`endif
if(~io_uio) begin
has_cmd <= 0;
cmd <= 0;
@@ -363,6 +367,7 @@ always@(posedge clk_sys) begin
end
end
else begin
cnt <= cnt + 1'd1;
if(cmd == 1) begin
cfg <= io_din;
cfg_set <= 1;
@@ -370,7 +375,6 @@ always@(posedge clk_sys) begin
end
if(cmd == 'h20) begin
cfg_set <= 0;
cnt <= cnt + 1'd1;
if(cnt<8) begin
case(cnt[2:0])
0: if(WIDTH != io_din[11:0]) WIDTH <= io_din[11:0];
@@ -402,7 +406,6 @@ always@(posedge clk_sys) begin
end
end
if(cmd == 'h2F) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]};
1: LFB_BASE[15:0] <= io_din[15:0];
@@ -419,12 +422,14 @@ always@(posedge clk_sys) begin
if(cmd == 'h25) {led_overtake, led_state} <= io_din;
if(cmd == 'h26) vol_att <= io_din[4:0];
if(cmd == 'h27) VSET <= io_din[11:0];
if(cmd == 'h2A) {coef_wr,coef_addr,coef_data} <= {1'b1,io_din};
if(cmd == 'h2A) begin
if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[8:0]};
else coef_addr <= io_din[8:0];
end
if(cmd == 'h2B) scaler_flt <= io_din[2:0];
if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]};
if(cmd == 'h38) vs_line <= io_din[11:0];
if(cmd == 'h39) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: acx_att <= io_din[4:0];
1: aflt_rate[15:0] <= io_din;
@@ -444,7 +449,6 @@ always@(posedge clk_sys) begin
endcase
end
if(cmd == 'h3A) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: arc1x <= io_din[12:0];
1: arc1y <= io_din[12:0];
@@ -452,6 +456,9 @@ always@(posedge clk_sys) begin
3: arc2y <= io_din[12:0];
endcase
end
`ifndef MISTER_DEBUG_NOHDMI
if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din};
`endif
end
end
@@ -618,7 +625,7 @@ wire [15:0] vbuf_byteenable;
wire vbuf_write;
wire [23:0] hdmi_data;
wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl;
wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd;
wire freeze;
`ifndef MISTER_DEBUG_NOHDMI
@@ -634,6 +641,7 @@ ascal
.PALETTE2("false"),
`endif
`endif
.FRAC(6),
.N_DW(128),
.N_AW(28)
)
@@ -667,6 +675,7 @@ ascal
.o_vs (hdmi_vs),
.o_de (hdmi_de),
.o_vbl (hdmi_vbl),
.o_brd (hdmi_brd),
.o_lltune (lltune),
.htotal (WIDTH + HFP + HBP + HS),
.hsstart (WIDTH + HFP),
@@ -1049,34 +1058,43 @@ cyclonev_hps_interface_peripheral_i2c hdmi_i2c
);
`ifndef MISTER_DEBUG_NOHDMI
wire [23:0] hdmi_data_sl;
wire hdmi_de_sl, hdmi_vs_sl, hdmi_hs_sl;
`ifdef MISTER_FB
reg dis_output;
always @(posedge clk_hdmi) begin
reg dis;
dis <= fb_force_blank;
dis <= fb_force_blank & ~LFB_EN;
dis_output <= dis;
end
`else
wire dis_output = 0;
`endif
scanlines #(1) HDMI_scanlines
wire [23:0] hdmi_data_mask;
wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask;
reg [15:0] shadowmask_data;
reg shadowmask_wr = 0;
shadowmask HDMI_shadowmask
(
.clk(clk_hdmi),
.clk_sys(clk_sys),
.cmd_wr(shadowmask_wr),
.cmd_in(shadowmask_data),
.scanlines(scanlines),
.din(dis_output ? 24'd0 : hdmi_data),
.hs_in(hdmi_hs),
.vs_in(hdmi_vs),
.de_in(hdmi_de),
.dout(hdmi_data_sl),
.hs_out(hdmi_hs_sl),
.vs_out(hdmi_vs_sl),
.de_out(hdmi_de_sl)
.brd_in(hdmi_brd),
.enable(~LFB_EN),
.dout(hdmi_data_mask),
.hs_out(hdmi_hs_mask),
.vs_out(hdmi_vs_mask),
.de_out(hdmi_de_mask)
);
wire [23:0] hdmi_data_osd;
@@ -1091,10 +1109,10 @@ osd hdmi_osd
.io_din(io_din),
.clk_video(clk_hdmi),
.din(hdmi_data_sl),
.hs_in(hdmi_hs_sl),
.vs_in(hdmi_vs_sl),
.de_in(hdmi_de_sl),
.din(hdmi_data_mask),
.hs_in(hdmi_hs_mask),
.vs_in(hdmi_vs_mask),
.de_in(hdmi_de_mask),
.dout(hdmi_data_osd),
.hs_out(hdmi_hs_osd),
@@ -1462,12 +1480,12 @@ wire [6:0] user_out, user_in;
assign clk_ihdmi= clk_vid;
assign ce_hpix = ce_pix;
assign hr_out = r_out;
assign hg_out = g_out;
assign hb_out = b_out;
assign hhs_fix = hs_fix;
assign hvs_fix = vs_fix;
assign hde_emu = de_emu;
assign hr_out = vga_data_sl[23:16];
assign hg_out = vga_data_sl[15:8];
assign hb_out = vga_data_sl[7:0];
assign hhs_fix = vga_hs_sl;
assign hvs_fix = vga_vs_sl;
assign hde_emu = vga_de_sl;
wire uart_dtr;
wire uart_dsr;
@@ -1504,11 +1522,15 @@ wire [13:0] fb_stride;
assign fb_stride = 0;
`endif
reg [1:0] sl_r;
wire [1:0] sl = sl_r;
always @(posedge clk_sys) sl_r <= FB_EN ? 2'b00 : scanlines;
emu emu
(
.CLK_50M(FPGA_CLK2_50),
.RESET(reset),
.HPS_BUS({f1, HDMI_TX_VS,
.HPS_BUS({fb_en, sl, f1, HDMI_TX_VS,
clk_100m, clk_ihdmi,
ce_hpix, hde_emu, hhs_fix, hvs_fix,
io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}),