mirror of
https://github.com/UzixLS/zxkit1-vga-scandoubler-firmware.git
synced 2025-07-18 23:01:27 +03:00
first working version
This commit is contained in:
@ -15,3 +15,5 @@ Jumpers:
|
|||||||
* VGA_SCART - no effect
|
* VGA_SCART - no effect
|
||||||
* SET_FK_IN - no effect
|
* SET_FK_IN - no effect
|
||||||
* SET_FK_OUT - no effect
|
* SET_FK_OUT - no effect
|
||||||
|
|
||||||
|
**PCB modification:** to get this firmware working you need to bridge CPLD pin 90 and pin 83.
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
create_clock -name F14 -period 14.1MHz [get_ports {F14}]
|
create_clock -name F14 -period 14.1MHz [get_ports {F14}]
|
||||||
create_generated_clock -name F14_2 -source [get_ports {F14}] -phase 45 [get_ports {F14_2}]
|
create_generated_clock -name F14_2 -source [get_ports {F14}] -phase 45 [get_ports {F14_2}]
|
||||||
|
create_clock -name F28 -period 28.1MHz [get_ports {F28}]
|
||||||
|
@ -95,7 +95,8 @@ set_location_assignment PIN_68 -to G_VGA
|
|||||||
set_location_assignment PIN_70 -to B_VGA
|
set_location_assignment PIN_70 -to B_VGA
|
||||||
set_location_assignment PIN_71 -to VSYNC_VGA
|
set_location_assignment PIN_71 -to VSYNC_VGA
|
||||||
set_location_assignment PIN_72 -to HSYNC_VGA
|
set_location_assignment PIN_72 -to HSYNC_VGA
|
||||||
set_location_assignment PIN_83 -to SYNC_VIDEO
|
set_location_assignment PIN_83 -to F28o
|
||||||
|
set_location_assignment PIN_90 -to F28
|
||||||
set_location_assignment PIN_84 -to SET_FK_OUT
|
set_location_assignment PIN_84 -to SET_FK_OUT
|
||||||
set_location_assignment PIN_85 -to SET_FK_IN
|
set_location_assignment PIN_85 -to SET_FK_IN
|
||||||
set_location_assignment PIN_92 -to VGA_SCART
|
set_location_assignment PIN_92 -to VGA_SCART
|
||||||
|
106
scandoubler.v
106
scandoubler.v
@ -8,6 +8,8 @@ module scandoubler(
|
|||||||
input SSI_IN,
|
input SSI_IN,
|
||||||
input F14,
|
input F14,
|
||||||
input F14_2,
|
input F14_2,
|
||||||
|
output F28o,
|
||||||
|
input F28,
|
||||||
|
|
||||||
input INVERSE_RGBI,
|
input INVERSE_RGBI,
|
||||||
input INVERSE_KSI,
|
input INVERSE_KSI,
|
||||||
@ -17,33 +19,35 @@ module scandoubler(
|
|||||||
input SET_FK_IN,
|
input SET_FK_IN,
|
||||||
input SET_FK_OUT,
|
input SET_FK_OUT,
|
||||||
|
|
||||||
output R_VGA,
|
output reg R_VGA,
|
||||||
output G_VGA,
|
output reg G_VGA,
|
||||||
output B_VGA,
|
output reg B_VGA,
|
||||||
output [2:0] I_VGA,
|
output reg [2:0] I_VGA,
|
||||||
output VSYNC_VGA,
|
output reg VSYNC_VGA,
|
||||||
output HSYNC_VGA,
|
output reg HSYNC_VGA,
|
||||||
|
|
||||||
output R_VIDEO,
|
output R_VIDEO,
|
||||||
output G_VIDEO,
|
output G_VIDEO,
|
||||||
output B_VIDEO,
|
output B_VIDEO,
|
||||||
output [2:0] I_VIDEO,
|
output [2:0] I_VIDEO,
|
||||||
output SYNC_VIDEO,
|
// output SYNC_VIDEO,
|
||||||
|
|
||||||
output A17,
|
output A17,
|
||||||
output [16:0] A,
|
output reg [16:0] A,
|
||||||
output WE,
|
output reg WE,
|
||||||
|
output reg UB,
|
||||||
|
output reg LB,
|
||||||
output OE,
|
output OE,
|
||||||
output UB,
|
|
||||||
output LB,
|
|
||||||
inout [15:0] D
|
inout [15:0] D
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assign F28o = F14 ^ F14_2 ^ INVERSE_F14MHZ;
|
||||||
|
|
||||||
reg ssi = 0, ksi0 = 0;
|
reg ssi = 0, ksi0 = 0;
|
||||||
wire ksi = ksi0 ^ ~KSI_IN;
|
wire ksi = ksi0 ^ ~KSI_IN;
|
||||||
reg [6:0] ssi_cnt = 0;
|
reg [7:0] ssi_cnt = 0;
|
||||||
always @(posedge F14) begin
|
reg [7:0] ssi_len = 0;
|
||||||
|
always @(posedge F28) begin
|
||||||
if (SSI_IN == ksi0) begin
|
if (SSI_IN == ksi0) begin
|
||||||
ssi_cnt <= ssi_cnt + 1'b1;
|
ssi_cnt <= ssi_cnt + 1'b1;
|
||||||
if (&ssi_cnt)
|
if (&ssi_cnt)
|
||||||
@ -51,6 +55,7 @@ always @(posedge F14) begin
|
|||||||
ssi <= 1'b0;
|
ssi <= 1'b0;
|
||||||
end
|
end
|
||||||
else if (|ssi_cnt) begin
|
else if (|ssi_cnt) begin
|
||||||
|
ssi_len <= ssi_cnt;
|
||||||
ssi_cnt <= 0;
|
ssi_cnt <= 0;
|
||||||
ssi <= 1'b1;
|
ssi <= 1'b1;
|
||||||
end
|
end
|
||||||
@ -59,57 +64,66 @@ always @(posedge F14) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [10:0] hcnt = 0;
|
reg [11:0] hcnt_in = 0;
|
||||||
reg [10:0] hlen = 0;
|
reg [11:0] hlen = 0;
|
||||||
reg even_line = 0;
|
reg even_line = 0;
|
||||||
always @(posedge F14) begin
|
always @(posedge F28) begin
|
||||||
if (ssi) begin
|
if (ssi) begin
|
||||||
even_line = !even_line;
|
even_line <= !even_line;
|
||||||
hlen <= hcnt;
|
hlen <= hcnt_in;
|
||||||
hcnt <= 0;
|
hcnt_in <= 0;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
hcnt <= hcnt + 1'b1;
|
hcnt_in <= hcnt_in + 1'b1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [9:0] hcnt_vga = 0;
|
reg [10:0] hcnt_vga = 0;
|
||||||
always @(posedge F14) begin
|
always @(posedge F28) begin
|
||||||
if (hcnt_vga == hlen[10:1] || ssi)
|
if (hcnt_vga == hlen[11:1] || ssi)
|
||||||
hcnt_vga <= 0;
|
hcnt_vga <= 0;
|
||||||
else
|
else
|
||||||
hcnt_vga <= hcnt_vga + 1'b1;
|
hcnt_vga <= hcnt_vga + 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign VSYNC_VGA = ~INVERSE_KSI ^ ksi;
|
|
||||||
assign HSYNC_VGA = ~INVERSE_SSI ^ (hcnt_vga < 54); // ~3.85us
|
|
||||||
|
|
||||||
assign OE = 1'b0;
|
|
||||||
assign A17 = 1'b0;
|
assign A17 = 1'b0;
|
||||||
wire write_screen = F14 ^ INVERSE_F14MHZ & !ssi;
|
assign OE = 1'b0;
|
||||||
assign WE = ~write_screen;
|
wire write_pixel = ~hcnt_in[0];
|
||||||
assign UB = write_screen? ~hcnt[0] : 1'b0;
|
reg [3:0] ibgr_reg1, ibgr_reg2, ibgr_in;
|
||||||
assign LB = write_screen? hcnt[0] : 1'b0;
|
always @(posedge F28) begin
|
||||||
assign A[16:0] = write_screen?
|
WE <= ~write_pixel;
|
||||||
{{6{1'b0}}, ~even_line, hcnt[10:1]} :
|
LB <= write_pixel? hcnt_in[1] : 1'b0;
|
||||||
{{6{1'b0}}, even_line, hcnt_vga} ;
|
UB <= write_pixel? ~hcnt_in[1] : 1'b0;
|
||||||
|
A[16:0] <= write_pixel?
|
||||||
|
{{6{1'b0}}, ~even_line, hcnt_in[11:2]} :
|
||||||
|
{{6{1'b0}}, even_line, hcnt_vga[10:1]} ;
|
||||||
|
|
||||||
assign D[15:0] = write_screen? {{4{1'b0}}, I_IN, B_IN, G_IN, R_IN, {4{1'b0}}, I_IN, B_IN, G_IN, R_IN} : {16{1'bz}};
|
ibgr_in = {4{~INVERSE_RGBI}} ^ {I_IN, B_IN, G_IN, R_IN};
|
||||||
|
if (write_pixel) begin
|
||||||
reg [3:0] ibgr_reg1, ibgr_reg2;
|
|
||||||
always @(posedge F14) begin
|
|
||||||
if (write_screen) begin
|
|
||||||
ibgr_reg1 <= D[3:0];
|
ibgr_reg1 <= D[3:0];
|
||||||
ibgr_reg2 <= D[11:8];
|
ibgr_reg2 <= D[11:8];
|
||||||
end
|
end
|
||||||
|
else begin
|
||||||
|
ibgr_reg1 <= ibgr_reg2;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assign R_VGA = (~INVERSE_RGBI) ^ (F14? ibgr_reg2[0] : ibgr_reg1[0]);
|
assign D[15:0] = !write_pixel?
|
||||||
assign G_VGA = (~INVERSE_RGBI) ^ (F14? ibgr_reg2[1] : ibgr_reg1[1]);
|
{{4{1'b0}}, ibgr_in, {4{1'b0}}, ibgr_in} :
|
||||||
assign B_VGA = (~INVERSE_RGBI) ^ (F14? ibgr_reg2[2] : ibgr_reg1[2]);
|
{16{1'bz}} ;
|
||||||
assign I_VGA[0] = (~INVERSE_RGBI) ^ (F14? ibgr_reg2[3] : ibgr_reg1[3]);
|
|
||||||
assign I_VGA[1] = (~INVERSE_RGBI) ^ (F14? ibgr_reg2[3] : ibgr_reg1[3]);
|
wire HBLANK_VGA = (hcnt_vga < (ssi_len[7:1]+ssi_len[7:2]));
|
||||||
assign I_VGA[2] = (~INVERSE_RGBI) ^ (F14? ibgr_reg2[3] : ibgr_reg1[3]);
|
always @(posedge F28) begin
|
||||||
|
VSYNC_VGA <= ~INVERSE_KSI ^ ksi;
|
||||||
|
HSYNC_VGA <= ~INVERSE_SSI ^ (hcnt_vga < ssi_len[7:1]);
|
||||||
|
R_VGA <= !HBLANK_VGA && (ibgr_reg1[0] );
|
||||||
|
G_VGA <= !HBLANK_VGA && (ibgr_reg1[1] );
|
||||||
|
// G_VGA <= !HBLANK_VGA && hcnt_vga[1];
|
||||||
|
B_VGA <= !HBLANK_VGA && (ibgr_reg1[2] );
|
||||||
|
I_VGA[0] <= !HBLANK_VGA && (ibgr_reg1[0] & ibgr_reg1[3]);
|
||||||
|
I_VGA[1] <= !HBLANK_VGA && (ibgr_reg1[1] & ibgr_reg1[3]);
|
||||||
|
I_VGA[2] <= !HBLANK_VGA && (ibgr_reg1[2] & ibgr_reg1[3]);
|
||||||
|
end
|
||||||
|
|
||||||
assign R_VIDEO = R_IN ^ ~INVERSE_RGBI;
|
assign R_VIDEO = R_IN ^ ~INVERSE_RGBI;
|
||||||
assign G_VIDEO = G_IN ^ ~INVERSE_RGBI;
|
assign G_VIDEO = G_IN ^ ~INVERSE_RGBI;
|
||||||
@ -117,7 +131,7 @@ assign B_VIDEO = B_IN ^ ~INVERSE_RGBI;
|
|||||||
assign I_VIDEO[0] = I_IN ^ ~INVERSE_RGBI;
|
assign I_VIDEO[0] = I_IN ^ ~INVERSE_RGBI;
|
||||||
assign I_VIDEO[1] = I_IN ^ ~INVERSE_RGBI;
|
assign I_VIDEO[1] = I_IN ^ ~INVERSE_RGBI;
|
||||||
assign I_VIDEO[2] = I_IN ^ ~INVERSE_RGBI;
|
assign I_VIDEO[2] = I_IN ^ ~INVERSE_RGBI;
|
||||||
assign SYNC_VIDEO = ~((SSI_IN ^ ~INVERSE_SSI) ^ (KSI_IN ^ ~INVERSE_KSI));
|
// assign SYNC_VIDEO = ~((SSI_IN ^ ~INVERSE_SSI) ^ (KSI_IN ^ ~INVERSE_KSI));
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -53,6 +53,8 @@ initial begin
|
|||||||
end
|
end
|
||||||
assign d = n_ramwr? ram_q0 : {16{1'bz}};
|
assign d = n_ramwr? ram_q0 : {16{1'bz}};
|
||||||
|
|
||||||
|
|
||||||
|
wire clk28;
|
||||||
scandoubler scandoubler1(
|
scandoubler scandoubler1(
|
||||||
.R_IN(1'b1),
|
.R_IN(1'b1),
|
||||||
.G_IN(1'b1),
|
.G_IN(1'b1),
|
||||||
@ -62,6 +64,8 @@ scandoubler scandoubler1(
|
|||||||
.SSI_IN(csync),
|
.SSI_IN(csync),
|
||||||
.F14(clk14),
|
.F14(clk14),
|
||||||
.F14_2(clk14_2),
|
.F14_2(clk14_2),
|
||||||
|
.F28o(clk28),
|
||||||
|
.F28(clk28),
|
||||||
.INVERSE_RGBI(1'b1),
|
.INVERSE_RGBI(1'b1),
|
||||||
.INVERSE_KSI(1'b1),
|
.INVERSE_KSI(1'b1),
|
||||||
.INVERSE_SSI(1'b1),
|
.INVERSE_SSI(1'b1),
|
||||||
@ -79,7 +83,7 @@ scandoubler scandoubler1(
|
|||||||
.G_VIDEO(),
|
.G_VIDEO(),
|
||||||
.B_VIDEO(),
|
.B_VIDEO(),
|
||||||
.I_VIDEO(),
|
.I_VIDEO(),
|
||||||
.SYNC_VIDEO(),
|
// .SYNC_VIDEO(),
|
||||||
.A17(ram_addr_a[17]),
|
.A17(ram_addr_a[17]),
|
||||||
.A(ram_addr_a[16:0]),
|
.A(ram_addr_a[16:0]),
|
||||||
.WE(n_ramwr),
|
.WE(n_ramwr),
|
||||||
@ -94,7 +98,7 @@ initial begin
|
|||||||
$dumpvars();
|
$dumpvars();
|
||||||
rst_n = 0;
|
rst_n = 0;
|
||||||
#5 rst_n = 1;
|
#5 rst_n = 1;
|
||||||
#2100000 $finish;
|
// #2100000 $finish;
|
||||||
#21000000 $finish;
|
#21000000 $finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user